Merge mozilla-central to autoland
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 28 Nov 2016 16:48:44 +0100
changeset 324531 2348f42371f9b1384392bbdaf956f6d53fdcc3f6
parent 324530 3f0ad2d2c5941e532a934eeb9a04c248ab01e450 (current diff)
parent 324430 8387a4ada9a5c4cab059d8fafe0f8c933e83c149 (diff)
child 324532 849f80eca8e6f6a5cef250efd5510801606c1a53
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
milestone53.0a1
Merge mozilla-central to autoland
python/compare-locales/compare_locales/tests/test_defines.py
python/compare-locales/compare_locales/tests/test_parser.py
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<blocklist lastupdate="1480165607548" xmlns="http://www.mozilla.org/2006/addons-blocklist">
+<blocklist lastupdate="1480338419582" xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem blockID="i545" id="superlrcs@svenyor.net">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i167" id="{b64982b1-d112-42b5-b1e4-d3867c4533f8}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
--- a/browser/extensions/aushelper/bootstrap.js
+++ b/browser/extensions/aushelper/bootstrap.js
@@ -81,17 +81,16 @@ function startup() {
             cpuRevMatch = true;
           }
           break;
         }
       } catch (e) {
         if (i == keyNames.length - 1) {
           // The registry key name's value was not successfully queried.
           cpuRevMatch = null;
-          Cu.reportError("Error getting CPU revision. Exception: " + e);
           TelemetryLog.log("AUSHELPER_CPU_REV_ERROR", [e]);
         }
       }
     }
   } catch (ex) {
     cpuRevMatch = null;
     Cu.reportError("Error getting CPU revision. Exception: " + ex);
     TelemetryLog.log("AUSHELPER_CPU_REV_ERROR", [ex]);
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -8133,16 +8133,97 @@ exports.CSS_PROPERTIES = {
       8
     ],
     "values": [
       "inherit",
       "initial",
       "unset"
     ]
   },
+  "place-content": {
+    "isInherited": false,
+    "subproperties": [
+      "align-content",
+      "justify-content"
+    ],
+    "supports": [],
+    "values": [
+      "baseline",
+      "center",
+      "end",
+      "flex-end",
+      "flex-start",
+      "inherit",
+      "initial",
+      "last baseline",
+      "left",
+      "normal",
+      "right",
+      "space-around",
+      "space-between",
+      "space-evenly",
+      "start",
+      "stretch",
+      "unset"
+    ]
+  },
+  "place-items": {
+    "isInherited": false,
+    "subproperties": [
+      "align-items",
+      "justify-items"
+    ],
+    "supports": [],
+    "values": [
+      "auto",
+      "baseline",
+      "center",
+      "end",
+      "flex-end",
+      "flex-start",
+      "inherit",
+      "initial",
+      "last baseline",
+      "left",
+      "normal",
+      "right",
+      "self-end",
+      "self-start",
+      "start",
+      "stretch",
+      "unset"
+    ]
+  },
+  "place-self": {
+    "isInherited": false,
+    "subproperties": [
+      "align-self",
+      "justify-self"
+    ],
+    "supports": [],
+    "values": [
+      "auto",
+      "baseline",
+      "center",
+      "end",
+      "flex-end",
+      "flex-start",
+      "inherit",
+      "initial",
+      "last baseline",
+      "left",
+      "normal",
+      "right",
+      "self-end",
+      "self-start",
+      "start",
+      "stretch",
+      "unset"
+    ]
+  },
   "pointer-events": {
     "isInherited": true,
     "subproperties": [
       "pointer-events"
     ],
     "supports": [],
     "values": [
       "all",
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -434,23 +434,22 @@ MediaKeys::Init(ErrorResult& aRv)
                NS_ConvertUTF8toUTF16(topLevelOrigin),
                KeySystemToGMPName(mKeySystem),
                inPrivateBrowsing);
 
   return promise.forget();
 }
 
 void
-MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId)
+MediaKeys::OnCDMCreated(PromiseId aId, const uint32_t aPluginId)
 {
   RefPtr<DetailedPromise> promise(RetrievePromise(aId));
   if (!promise) {
     return;
   }
-  mNodeId = aNodeId;
   RefPtr<MediaKeys> keys(this);
   EME_LOG("MediaKeys[%p]::OnCDMCreated() resolve promise id=%d", this, aId);
   promise->MaybeResolve(keys);
   if (mCreatePromiseId == aId) {
     Release();
   }
 
   MediaKeySystemAccess::NotifyObservers(mParent,
@@ -550,23 +549,16 @@ already_AddRefed<MediaKeySession>
 MediaKeys::GetPendingSession(uint32_t aToken)
 {
   RefPtr<MediaKeySession> session;
   mPendingSessions.Get(aToken, getter_AddRefs(session));
   mPendingSessions.Remove(aToken);
   return session.forget();
 }
 
-const nsCString&
-MediaKeys::GetNodeId() const
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  return mNodeId;
-}
-
 bool
 MediaKeys::IsBoundToMediaElement() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mElement != nullptr;
 }
 
 nsresult
--- a/dom/media/eme/MediaKeys.h
+++ b/dom/media/eme/MediaKeys.h
@@ -78,18 +78,17 @@ public:
 
   already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
 
   // Removes and returns MediaKeySession from the set of sessions awaiting
   // their sessionId to be assigned.
   already_AddRefed<MediaKeySession> GetPendingSession(uint32_t aToken);
 
   // Called once a Init() operation succeeds.
-  void OnCDMCreated(PromiseId aId,
-                    const nsACString& aNodeId, const uint32_t aPluginId);
+  void OnCDMCreated(PromiseId aId, const uint32_t aPluginId);
 
   // Called once the CDM generates a sessionId while servicing a
   // MediaKeySession.generateRequest() or MediaKeySession.load() call,
   // once the sessionId of a MediaKeySession is known.
   void OnSessionIdReady(MediaKeySession* aSession);
 
   // Called once a LoadSession succeeds.
   void OnSessionLoaded(PromiseId aId, bool aSuccess);
@@ -115,18 +114,16 @@ public:
   void ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken);
 
   // Reject promise with DOMException corresponding to aExceptionCode.
   void RejectPromise(PromiseId aId, nsresult aExceptionCode,
                      const nsCString& aReason);
   // Resolves promise with "undefined".
   void ResolvePromise(PromiseId aId);
 
-  const nsCString& GetNodeId() const;
-
   void Shutdown();
 
   // Called by CDMProxy when CDM crashes or shuts down. It is different from
   // Shutdown which is called from the script/dom side.
   void Terminated();
 
   // Returns true if this MediaKeys has been bound to a media element.
   bool IsBoundToMediaElement() const;
@@ -143,17 +140,16 @@ private:
   // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,
   // and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
   RefPtr<CDMProxy> mProxy;
 
   RefPtr<HTMLMediaElement> mElement;
 
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   const nsString mKeySystem;
-  nsCString mNodeId;
   KeySessionHashMap mKeySessions;
   PromiseHashMap mPromises;
   PendingKeySessionsHashMap mPendingSessions;
   PromiseId mCreatePromiseId;
 
   RefPtr<nsIPrincipal> mPrincipal;
   RefPtr<nsIPrincipal> mTopLevelPrincipal;
 
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
@@ -383,17 +383,17 @@ void
 MediaDrmCDMProxy::OnCDMCreated(uint32_t aPromiseId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
 
   if (mCDM) {
-    mKeys->OnCDMCreated(aPromiseId, GetNodeId(), 0);
+    mKeys->OnCDMCreated(aPromiseId, 0);
     return;
   }
 
   // No CDM? Just reject the promise.
   mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                        NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()"));
 }
 
--- a/dom/media/gmp/GMPCDMProxy.cpp
+++ b/dom/media/gmp/GMPCDMProxy.cpp
@@ -269,17 +269,17 @@ void
 GMPCDMProxy::OnCDMCreated(uint32_t aPromiseId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   MOZ_ASSERT(!GetNodeId().IsEmpty());
   if (mCDM) {
-    mKeys->OnCDMCreated(aPromiseId, GetNodeId(), mCDM->GetPluginId());
+    mKeys->OnCDMCreated(aPromiseId, mCDM->GetPluginId());
   } else {
     // No CDM? Just reject the promise.
     mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                          NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()"));
   }
 }
 
 void
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -653,16 +653,41 @@ nsCSPParser::schemeSource()
   // then we are not parsing a scheme; but rather a host;
   if (peek(isNumberToken) || peek(WILDCARD)) {
     return nullptr;
   }
 
   return new nsCSPSchemeSrc(scheme);
 }
 
+bool IsValidBase64Value(const char16_t* cur, const char16_t* end)
+{
+  // May end with one or two =
+  if (end > cur && *(end-1) == EQUALS) end--;
+  if (end > cur && *(end-1) == EQUALS) end--;
+
+  // Must have at least one character aside from any =
+  if (end == cur) {
+    return false;
+  }
+
+  // Rest is all A-Za-z0-9+/-_
+  for (; cur < end; ++cur) {
+    if (!((*cur >= 'a' && *cur <= 'z') ||
+          (*cur >= 'A' && *cur <= 'Z') ||
+          (*cur >= '0' && *cur <= '9') ||
+          *cur == PLUS || *cur == SLASH ||
+          *cur == DASH || *cur == UNDERLINE)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 // nonce-source = "'nonce-" nonce-value "'"
 nsCSPNonceSrc*
 nsCSPParser::nonceSource()
 {
   CSPPARSERLOG(("nsCSPParser::nonceSource, mCurToken: %s, mCurValue: %s",
                NS_ConvertUTF16toUTF8(mCurToken).get(),
                NS_ConvertUTF16toUTF8(mCurValue).get()));
 
@@ -675,16 +700,20 @@ nsCSPParser::nonceSource()
 
   // Trim surrounding single quotes
   const nsAString& expr = Substring(mCurToken, 1, mCurToken.Length() - 2);
 
   int32_t dashIndex = expr.FindChar(DASH);
   if (dashIndex < 0) {
     return nullptr;
   }
+  if (!IsValidBase64Value(expr.BeginReading() + dashIndex + 1, expr.EndReading())) {
+    return nullptr;
+  }
+
   // cache if encountering hash or nonce to invalidate unsafe-inline
   mHasHashOrNonce = true;
   return new nsCSPNonceSrc(Substring(expr,
                                      dashIndex + 1,
                                      expr.Length() - dashIndex + 1));
 }
 
 // hash-source = "'" hash-algo "-" base64-value "'"
@@ -704,16 +733,20 @@ nsCSPParser::hashSource()
   // Trim surrounding single quotes
   const nsAString& expr = Substring(mCurToken, 1, mCurToken.Length() - 2);
 
   int32_t dashIndex = expr.FindChar(DASH);
   if (dashIndex < 0) {
     return nullptr;
   }
 
+  if (!IsValidBase64Value(expr.BeginReading() + dashIndex + 1, expr.EndReading())) {
+    return nullptr;
+  }
+
   nsAutoString algo(Substring(expr, 0, dashIndex));
   nsAutoString hash(Substring(expr, dashIndex + 1, expr.Length() - dashIndex + 1));
 
   for (uint32_t i = 0; i < kHashSourceValidFnsLen; i++) {
     if (algo.LowerCaseEqualsASCII(kHashSourceValidFns[i])) {
       // cache if encountering hash or nonce to invalidate unsafe-inline
       mHasHashOrNonce = true;
       return new nsCSPHashSrc(algo, hash);
--- a/dom/security/test/gtest/TestCSPParser.cpp
+++ b/dom/security/test/gtest/TestCSPParser.cpp
@@ -221,16 +221,20 @@ TEST(CSPParser, Directives)
     { "font-src http://www.example.com",
       "font-src http://www.example.com" },
     { "connect-src http://www.example.com",
       "connect-src http://www.example.com" },
     { "report-uri http://www.example.com",
       "report-uri http://www.example.com/" },
     { "script-src 'nonce-correctscriptnonce'",
       "script-src 'nonce-correctscriptnonce'" },
+    { "script-src 'nonce-a'",
+      "script-src 'nonce-a'" },
+    { "script-src 'sha256-a'",
+      "script-src 'sha256-a'" },
     { "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='",
       "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" },
     { "referrer no-referrer",
       "referrer no-referrer" },
     { "require-sri-for script style",
       "require-sri-for script style"},
     { "script-src 'nonce-foo' 'unsafe-inline' ",
       "script-src 'nonce-foo' 'unsafe-inline'" },
@@ -537,16 +541,44 @@ TEST(CSPParser, PoliciesWithInvalidSrc)
     { "script-src http://www.example.com:88//path-1",
       "script-src 'none'" },
     { "script-src http://www.example.com:88.js",
       "script-src 'none'" },
     { "script-src http://www.example.com:*.js",
       "script-src 'none'" },
     { "script-src http://www.example.com:*.",
       "script-src 'none'" },
+    { "script-src 'nonce-{invalid}'",
+      "script-src 'none'" },
+    { "script-src 'sha256-{invalid}'",
+      "script-src 'none'" },
+    { "script-src 'nonce-in$valid'",
+      "script-src 'none'" },
+    { "script-src 'sha256-in$valid'",
+      "script-src 'none'" },
+    { "script-src 'nonce-invalid==='",
+      "script-src 'none'" },
+    { "script-src 'sha256-invalid==='",
+      "script-src 'none'" },
+    { "script-src 'nonce-==='",
+      "script-src 'none'" },
+    { "script-src 'sha256-==='",
+      "script-src 'none'" },
+    { "script-src 'nonce-=='",
+      "script-src 'none'" },
+    { "script-src 'sha256-=='",
+      "script-src 'none'" },
+    { "script-src 'nonce-='",
+      "script-src 'none'" },
+    { "script-src 'sha256-='",
+      "script-src 'none'" },
+    { "script-src 'nonce-'",
+      "script-src 'none'" },
+    { "script-src 'sha256-'",
+      "script-src 'none'" },
     { "connect-src http://www.example.com/foo%zz;",
       "connect-src 'none'" },
     { "script-src https://foo.com/%$",
       "script-src 'none'" },
     { "require-SRI-for script elephants",
       "require-sri-for script"},
     { "sandbox    foo",
       "sandbox"},
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1665,26 +1665,31 @@ gfxPlatform::InitBackendPrefs(uint32_t a
       mFallbackCanvasBackend =
           GetCanvasBackendPref(aCanvasBitmask &
                                ~(BackendTypeBit(mPreferredCanvasBackend) | BackendTypeBit(BackendType::DIRECT2D)));
     } else {
       mFallbackCanvasBackend =
           GetCanvasBackendPref(aCanvasBitmask & ~BackendTypeBit(mPreferredCanvasBackend));
     }
 
+
     mContentBackendBitmask = aContentBitmask;
     mContentBackend = GetContentBackendPref(mContentBackendBitmask);
     if (mContentBackend == BackendType::NONE) {
         mContentBackend = aContentDefault;
         // mContentBackendBitmask is our canonical reference for supported
         // backends so we need to add the default if we are using it and
         // overriding the prefs.
         mContentBackendBitmask |= BackendTypeBit(aContentDefault);
     }
 
+    uint32_t swBackendBits = BackendTypeBit(BackendType::SKIA) |
+                             BackendTypeBit(BackendType::CAIRO);
+    mSoftwareBackend = GetContentBackendPref(swBackendBits);
+
     if (XRE_IsParentProcess()) {
         gfxVars::SetContentBackend(mContentBackend);
     }
 }
 
 /* static */ BackendType
 gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask)
 {
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -289,16 +289,21 @@ public:
 
     // Get the default content backend that will be used with the default
     // compositor. If the compositor is known when calling this function,
     // GetContentBackendFor() should be called instead.
     mozilla::gfx::BackendType GetDefaultContentBackend() {
       return mContentBackend;
     }
 
+    /// Return the software backend to use by default.
+    mozilla::gfx::BackendType GetSoftwareBackend() {
+        return mSoftwareBackend;
+    }
+
     // Return the best content backend available that is compatible with the
     // given layers backend.
     virtual mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) {
       return mContentBackend;
     }
 
     mozilla::gfx::BackendType GetPreferredCanvasBackend() {
       return mPreferredCanvasBackend;
@@ -825,16 +830,18 @@ private:
     nsCOMPtr<nsIObserver> mMemoryPressureObserver;
 
     // The preferred draw target backend to use for canvas
     mozilla::gfx::BackendType mPreferredCanvasBackend;
     // The fallback draw target backend to use for canvas, if the preferred backend fails
     mozilla::gfx::BackendType mFallbackCanvasBackend;
     // The backend to use for content
     mozilla::gfx::BackendType mContentBackend;
+    // The backend to use when we need it not to be accelerated.
+    mozilla::gfx::BackendType mSoftwareBackend;
     // Bitmask of backend types we can use to render content
     uint32_t mContentBackendBitmask;
 
     mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
     mozilla::widget::GfxInfoCollector<gfxPlatform> mApzSupportCollector;
     mozilla::widget::GfxInfoCollector<gfxPlatform> mTilesInfoCollector;
 
     RefPtr<mozilla::gfx::DrawEventRecorder> mRecorder;
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3418,17 +3418,17 @@ ASTSerializer::function(ParseNode* pn, A
     RootedAtom funcAtom(cx, func->name());
     if (!optIdentifier(funcAtom, nullptr, &id))
         return false;
 
     NodeVector args(cx);
     NodeVector defaults(cx);
 
     RootedValue body(cx), rest(cx);
-    if (func->hasRest())
+    if (pn->pn_funbox->hasRest())
         rest.setUndefined();
     else
         rest.setNull();
     return functionArgsAndBody(pn->pn_body, args, defaults, isAsync, isExpression, &body, &rest) &&
            builder.function(type, &pn->pn_pos, id, args, defaults, body,
                             rest, generatorStyle, isAsync, isExpression, dst);
 }
 
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -1754,17 +1754,17 @@ js::intrinsic_GetElemBaseForLambda(JSCon
 
     if (!lambda.is<JSFunction>())
         return true;
 
     RootedFunction fun(cx, &lambda.as<JSFunction>());
     if (!fun->isInterpreted() || fun->isClassConstructor())
         return true;
 
-    JSScript* script = fun->getOrCreateScript(cx);
+    JSScript* script = JSFunction::getOrCreateScript(cx, fun);
     if (!script)
         return false;
 
     jsbytecode* pc = script->code();
 
     /*
      * JSOP_GETALIASEDVAR tells us exactly where to find the base object 'b'.
      * Rule out the (unlikely) possibility of a function with environment
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -3269,23 +3269,23 @@ ByteSizeOfScript(JSContext*cx, unsigned 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!args.requireAtLeast(cx, "byteSizeOfScript", 1))
         return false;
     if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
         JS_ReportErrorASCII(cx, "Argument must be a Function object");
         return false;
     }
 
-    JSFunction* fun = &args[0].toObject().as<JSFunction>();
+    RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
     if (fun->isNative()) {
         JS_ReportErrorASCII(cx, "Argument must be a scripted function");
         return false;
     }
 
-    RootedScript script(cx, fun->getOrCreateScript(cx));
+    RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
     if (!script)
         return false;
 
     mozilla::MallocSizeOf mallocSizeOf = cx->runtime()->debuggerMallocSizeOf;
 
     {
         // We can't tolerate the GC moving things around while we're using a
         // ubi::Node. Check that nothing we do causes a GC.
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -225,17 +225,17 @@ static const ClassOps ScalarTypeDescrCla
 const Class js::ScalarTypeDescr::class_ = {
     "Scalar",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     &ScalarTypeDescrClassOps
 };
 
 const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
-    JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, JSFUN_HAS_REST),
+    JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
     JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
     JS_FS_END
 };
 
 uint32_t
 ScalarTypeDescr::size(Type t)
 {
     return AssertedCast<uint32_t>(Scalar::byteSize(t));
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -281,17 +281,18 @@ BytecodeCompiler::handleParseFailure(con
 }
 
 bool
 BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment)
 {
     RootedObject env(cx, environment);
     while (env->is<EnvironmentObject>() || env->is<DebugEnvironmentProxy>()) {
         if (env->is<CallObject>()) {
-            RootedScript script(cx, env->as<CallObject>().callee().getOrCreateScript(cx));
+            RootedFunction fun(cx, &env->as<CallObject>().callee());
+            RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
             if (!script)
                 return false;
             if (script->argumentsHasVarBinding()) {
                 if (!JSScript::argumentsOptimizationFailed(cx, script))
                     return false;
             }
         }
         env = env->enclosingEnvironment();
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1048,17 +1048,17 @@ BytecodeEmitter::EmitterScope::enterFunc
             NameLocationMap::AddPtr p = cache.lookupForAdd(bi.name());
 
             // The only duplicate bindings that occur are simple formal
             // parameters, in which case the last position counts, so update the
             // location.
             if (p) {
                 MOZ_ASSERT(bi.kind() == BindingKind::FormalParameter);
                 MOZ_ASSERT(!funbox->hasDestructuringArgs);
-                MOZ_ASSERT(!funbox->function()->hasRest());
+                MOZ_ASSERT(!funbox->hasRest());
                 p->value() = loc;
                 continue;
             }
 
             if (!cache.add(p, bi.name(), loc)) {
                 ReportOutOfMemory(bce->cx);
                 return false;
             }
@@ -8014,17 +8014,17 @@ BytecodeEmitter::isRestParameter(ParseNo
 {
     if (!sc->isFunctionBox()) {
         *result = false;
         return true;
     }
 
     FunctionBox* funbox = sc->asFunctionBox();
     RootedFunction fun(cx, funbox->function());
-    if (!fun->hasRest()) {
+    if (!funbox->hasRest()) {
         *result = false;
         return true;
     }
 
     if (!pn->isKind(PNK_NAME)) {
         if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) {
             ParseNode* pn2 = pn->pn_head;
             if (pn2->getKind() == PNK_NAME && pn2->name() == cx->names().allowContentSpread)
@@ -8957,17 +8957,17 @@ BytecodeEmitter::emitFunctionFormalParam
 bool
 BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
 {
     ParseNode* funBody = pn->last();
     FunctionBox* funbox = sc->asFunctionBox();
     EmitterScope* funScope = innermostEmitterScope;
 
     bool hasParameterExprs = funbox->hasParameterExprs;
-    bool hasRest = funbox->function()->hasRest();
+    bool hasRest = funbox->hasRest();
 
     uint16_t argSlot = 0;
     for (ParseNode* arg = pn->pn_head; arg != funBody; arg = arg->pn_next, argSlot++) {
         ParseNode* bindingElement = arg;
         ParseNode* initializer = nullptr;
         if (arg->isKind(PNK_ASSIGN)) {
             bindingElement = arg->pn_left;
             initializer = arg->pn_right;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -460,45 +460,43 @@ FunctionBox::FunctionBox(ExclusiveContex
     insideUseAsm(false),
     isAnnexB(false),
     wasEmitted(false),
     declaredArguments(false),
     usesArguments(false),
     usesApply(false),
     usesThis(false),
     usesReturn(false),
+    hasRest_(false),
     funCxFlags()
 {
     // Functions created at parse time may be set singleton after parsing and
     // baked into JIT code, so they must be allocated tenured. They are held by
     // the JSScript so cannot be collected during a minor GC anyway.
     MOZ_ASSERT(fun->isTenured());
 }
 
 void
 FunctionBox::initFromLazyFunction()
 {
     JSFunction* fun = function();
-    length = fun->nargs() - fun->hasRest();
     if (fun->lazyScript()->isDerivedClassConstructor())
         setDerivedClassConstructor();
     if (fun->lazyScript()->needsHomeObject())
         setNeedsHomeObject();
     enclosingScope_ = fun->lazyScript()->enclosingScope();
     initWithEnclosingScope(enclosingScope_);
 }
 
 void
 FunctionBox::initStandaloneFunction(Scope* enclosingScope)
 {
     // Standalone functions are Function or Generator constructors and are
     // always scoped to the global.
     MOZ_ASSERT(enclosingScope->is<GlobalScope>());
-    JSFunction* fun = function();
-    length = fun->nargs() - fun->hasRest();
     enclosingScope_ = enclosingScope;
     allowNewTarget_ = true;
     thisBinding_ = ThisBinding::Function;
 }
 
 void
 FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing, FunctionSyntaxKind kind)
 {
@@ -2243,16 +2241,18 @@ Parser<SyntaxParseHandler>::finishFuncti
         return false;
 
     // Flags that need to be copied into the JSScript when we do the full
     // parse.
     if (pc->sc()->strict())
         lazy->setStrict();
     lazy->setGeneratorKind(funbox->generatorKind());
     lazy->setAsyncKind(funbox->asyncKind());
+    if (funbox->hasRest())
+        lazy->setHasRest();
     if (funbox->isLikelyConstructorWrapper())
         lazy->setLikelyConstructorWrapper();
     if (funbox->isDerivedClassConstructor())
         lazy->setIsDerivedClassConstructor();
     if (funbox->needsHomeObject())
         lazy->setNeedsHomeObject();
     if (funbox->declaredArguments)
         lazy->setShouldDeclareArguments();
@@ -2806,17 +2806,17 @@ Parser<ParseHandler>::functionArguments(
                 disallowDuplicateParams = true;
                 if (duplicatedParam) {
                     // Has duplicated args before the rest parameter.
                     error(JSMSG_BAD_DUP_ARGS);
                     return false;
                 }
 
                 hasRest = true;
-                funbox->function()->setHasRest();
+                funbox->setHasRest();
 
                 if (!tokenStream.getToken(&tt))
                     return false;
 
                 if (tt != TOK_NAME && tt != TOK_YIELD && tt != TOK_LB && tt != TOK_LC) {
                     error(JSMSG_NO_REST_NAME);
                     return false;
                 }
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -466,16 +466,17 @@ class FunctionBox : public ObjectBox, pu
     bool            wasEmitted:1;           /* Bytecode has been emitted for this function. */
 
     // Fields for use in heuristics.
     bool            declaredArguments:1;    /* the Parser declared 'arguments' */
     bool            usesArguments:1;        /* contains a free use of 'arguments' */
     bool            usesApply:1;            /* contains an f.apply() call */
     bool            usesThis:1;             /* contains 'this' */
     bool            usesReturn:1;           /* contains a 'return' statement */
+    bool            hasRest_:1;             /* has rest parameter */
 
     FunctionContextFlags funCxFlags;
 
     FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
                 Directives directives, bool extraWarnings, GeneratorKind generatorKind,
                 FunctionAsyncKind asyncKind);
 
     MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
@@ -534,16 +535,21 @@ class FunctionBox : public ObjectBox, pu
     GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
     bool isGenerator() const { return generatorKind() != NotGenerator; }
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
     FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
     bool isAsync() const { return asyncKind() == AsyncFunction; }
     bool isArrow() const { return function()->isArrow(); }
 
+    bool hasRest() const { return hasRest_; }
+    void setHasRest() {
+        hasRest_ = true;
+    }
+
     void setGeneratorKind(GeneratorKind kind) {
         // A generator kind can be set at initialization, or when "yield" is
         // first seen.  In both cases the transition can only happen from
         // NotGenerator.
         MOZ_ASSERT(!isGenerator());
         generatorKindBits_ = GeneratorKindAsBits(kind);
     }
 
@@ -562,17 +568,17 @@ class FunctionBox : public ObjectBox, pu
                                              funCxFlags.definitelyNeedsArgsObj   = true; }
     void setNeedsHomeObject()              { MOZ_ASSERT(function()->allowSuperProperty());
                                              funCxFlags.needsHomeObject          = true; }
     void setDerivedClassConstructor()      { MOZ_ASSERT(function()->isClassConstructor());
                                              funCxFlags.isDerivedClassConstructor = true; }
     void setHasInnerFunctions()            { funCxFlags.hasInnerFunctions         = true; }
 
     bool hasSimpleParameterList() const {
-        return !function()->hasRest() && !hasParameterExprs && !hasDestructuringArgs;
+        return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
     }
 
     bool hasMappedArgsObj() const {
         return !strict() && hasSimpleParameterList();
     }
 
     // Return whether this or an enclosing function is being parsed and
     // validated as asm.js. Note: if asm.js validation fails, this will be false
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/baseline-opt.js
@@ -0,0 +1,110 @@
+// Point-testing various optimizations in the wasm baseline compiler.
+
+load(libdir + "wasm.js");
+
+// Boolean optimization for control (bug 1286816).
+//
+// These optimizations combine a test (a comparison or Eqz) with an
+// immediately following conditional branch (BrIf, If, and Select), to
+// avoid generating a boolean value that is then tested with a
+// compare-to-zero.
+//
+// On AngryBots as of November 2016, 84% of all test instructions
+// (measured statically) are optimized by this method.
+
+function testEqzBrIf(value, type, untaken, taken, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (local i32)
+			    (set_local 0 (${type}.const ${value}))
+			    (set_local 1 (i32.const ${taken}))
+			    (block $b
+			     (br_if $b (${type}.eqz (get_local 0)))
+			     (set_local 1 (i32.const ${untaken})))
+			    (get_local 1))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64"].forEach(t => testEqzBrIf(0, t, 37, 42, 42)); // Taken
+["i32", "i64"].forEach(t => testEqzBrIf(1, t, 37, 42, 37)); // Untaken
+
+function testCmpBrIf(value, type, untaken, taken, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (local i32)
+			    (set_local 1 (i32.const ${taken}))
+			    (block $b
+			     (br_if $b (${type}.eq (get_local 0) (${type}.const ${value})))
+			     (set_local 1 (i32.const ${untaken})))
+			    (get_local 1))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64", "f32", "f64"].forEach(t => testCmpBrIf(0, t, 37, 42, 42)); // Branch taken
+["i32", "i64", "f32", "f64"].forEach(t => testCmpBrIf(1, t, 37, 42, 37)); // Branch untaken
+
+function testEqzSelect(value, type, iftrue, iffalse, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (set_local 0 (${type}.const ${value}))
+			    (select (i32.const ${iftrue})
+			            (i32.const ${iffalse})
+			            (${type}.eqz (get_local 0))))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64"].forEach(t => testEqzSelect(0, t, 42, 37, 42)); // Select first
+["i32", "i64"].forEach(t => testEqzSelect(1, t, 42, 37, 37)); // Select second
+
+function testCmpSelect(value, type, iftrue, iffalse, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (select (i32.const ${iftrue})
+			            (i32.const ${iffalse})
+			            (${type}.eq (get_local 0) (${type}.const ${value}))))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64", "f32", "f64"].forEach(t => testCmpSelect(0, t, 42, 37, 42)); // Select first
+["i32", "i64", "f32", "f64"].forEach(t => testCmpSelect(1, t, 42, 37, 37)); // Select second
+
+function testEqzIf(value, type, trueBranch, falseBranch, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (local i32)
+			    (set_local 0 (${type}.const ${value}))
+			    (if (${type}.eqz (get_local 0))
+				(set_local 1 (i32.const ${trueBranch}))
+			        (set_local 1 (i32.const ${falseBranch})))
+			    (get_local 1))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64"].forEach(t => testEqzIf(0, t, 42, 37, 42)); // Taken
+["i32", "i64"].forEach(t => testEqzIf(1, t, 42, 37, 37)); // Untaken
+
+function testCmpIf(value, type, trueBranch, falseBranch, expected) {
+    var f = wasmEvalText(`(module
+			   (func (result i32)
+			    (local ${type})
+			    (local i32)
+			    (if (${type}.eq (get_local 0) (${type}.const ${value}))
+				(set_local 1 (i32.const ${trueBranch}))
+			        (set_local 1 (i32.const ${falseBranch})))
+			    (get_local 1))
+			   (export "f" 0))`).exports["f"];
+    assertEq(f(), expected);
+}
+
+["i32", "i64", "f32", "f64"].forEach(t => testCmpIf(0, t, 42, 37, 42)); // Taken
+["i32", "i64", "f32", "f64"].forEach(t => testCmpIf(1, t, 42, 37, 37)); // Untaken
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -446,37 +446,29 @@ CacheIRCompiler::emitFailurePath(size_t 
 // BaselineCacheIRCompiler compiles CacheIR to BaselineIC native code.
 class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler
 {
     // Some Baseline IC stubs can be used in IonMonkey through SharedStubs.
     // Those stubs have different machine code, so we need to track whether
     // we're compiling for Baseline or Ion.
     ICStubEngine engine_;
 
-#ifdef DEBUG
-    uint32_t framePushedAtEnterStubFrame_;
-#endif
-
     uint32_t stubDataOffset_;
     bool inStubFrame_;
     bool makesGCCalls_;
 
-    void enterStubFrame(MacroAssembler& masm, Register scratch);
-    void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
-
     MOZ_MUST_USE bool callVM(MacroAssembler& masm, const VMFunction& fun);
 
   public:
+    friend class AutoStubFrame;
+
     BaselineCacheIRCompiler(JSContext* cx, const CacheIRWriter& writer, ICStubEngine engine,
                             uint32_t stubDataOffset)
       : CacheIRCompiler(cx, writer),
         engine_(engine),
-#ifdef DEBUG
-        framePushedAtEnterStubFrame_(0),
-#endif
         stubDataOffset_(stubDataOffset),
         inStubFrame_(false),
         makesGCCalls_(false)
     {}
 
     MOZ_MUST_USE bool init(CacheKind kind);
 
     JitCode* compile();
@@ -510,51 +502,81 @@ class MOZ_RAII BaselineCacheIRCompiler :
         if (!failurePaths.append(Move(newFailure)))
             return false;
 
         *failure = &failurePaths.back();
         return true;
     }
 };
 
-void
-BaselineCacheIRCompiler::enterStubFrame(MacroAssembler& masm, Register scratch)
+// Instructions that have to perform a callVM require a stub frame. Use
+// AutoStubFrame before allocating any registers, then call its enter() and
+// leave() methods to enter/leave the stub frame.
+class MOZ_RAII AutoStubFrame
 {
-    if (engine_ == ICStubEngine::Baseline) {
-        EmitBaselineEnterStubFrame(masm, scratch);
+    BaselineCacheIRCompiler& compiler;
 #ifdef DEBUG
-        framePushedAtEnterStubFrame_ = masm.framePushed();
+    uint32_t framePushedAtEnterStubFrame_;
 #endif
-    } else {
-        EmitIonEnterStubFrame(masm, scratch);
+    Maybe<AutoScratchRegister> tail;
+
+    AutoStubFrame(const AutoStubFrame&) = delete;
+    void operator=(const AutoStubFrame&) = delete;
+
+  public:
+    explicit AutoStubFrame(BaselineCacheIRCompiler& compiler)
+      : compiler(compiler),
+#ifdef DEBUG
+        framePushedAtEnterStubFrame_(0),
+#endif
+        tail()
+    {
+        // We use ICTailCallReg when entering the stub frame, so ensure it's not
+        // used for something else.
+        if (compiler.allocator.isAllocatable(ICTailCallReg))
+            tail.emplace(compiler.allocator, compiler.masm, ICTailCallReg);
     }
 
-    MOZ_ASSERT(!inStubFrame_);
-    inStubFrame_ = true;
-    makesGCCalls_ = true;
-}
+    void enter(MacroAssembler& masm, Register scratch) {
+        if (compiler.engine_ == ICStubEngine::Baseline) {
+            EmitBaselineEnterStubFrame(masm, scratch);
+#ifdef DEBUG
+            framePushedAtEnterStubFrame_ = masm.framePushed();
+#endif
+        } else {
+            EmitIonEnterStubFrame(masm, scratch);
+        }
 
-void
-BaselineCacheIRCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon)
-{
-    MOZ_ASSERT(inStubFrame_);
-    inStubFrame_ = false;
+        MOZ_ASSERT(!compiler.inStubFrame_);
+        compiler.inStubFrame_ = true;
+        compiler.makesGCCalls_ = true;
+    }
+    void leave(MacroAssembler& masm, bool calledIntoIon = false) {
+        MOZ_ASSERT(compiler.inStubFrame_);
+        compiler.inStubFrame_ = false;
 
-    if (engine_ == ICStubEngine::Baseline) {
+        if (compiler.engine_ == ICStubEngine::Baseline) {
 #ifdef DEBUG
-        masm.setFramePushed(framePushedAtEnterStubFrame_);
-        if (calledIntoIon)
-            masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
+            masm.setFramePushed(framePushedAtEnterStubFrame_);
+            if (calledIntoIon)
+                masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
 #endif
 
-        EmitBaselineLeaveStubFrame(masm, calledIntoIon);
-    } else {
-        EmitIonLeaveStubFrame(masm);
+            EmitBaselineLeaveStubFrame(masm, calledIntoIon);
+        } else {
+            EmitIonLeaveStubFrame(masm);
+        }
     }
-}
+
+#ifdef DEBUG
+    ~AutoStubFrame() {
+        MOZ_ASSERT(!compiler.inStubFrame_);
+    }
+#endif
+};
 
 bool
 BaselineCacheIRCompiler::callVM(MacroAssembler& masm, const VMFunction& fun)
 {
     MOZ_ASSERT(inStubFrame_);
 
     JitCode* code = cx_->jitRuntime()->getVMWrapper(fun);
     if (!code)
@@ -592,16 +614,17 @@ BaselineCacheIRCompiler::compile()
 
           default:
             MOZ_CRASH("Invalid op");
         }
 
         allocator.nextOp();
     } while (reader.more());
 
+    MOZ_ASSERT(!inStubFrame_);
     masm.assumeUnreachable("Should have returned from IC");
 
     // Done emitting the main IC code. Now emit the failure paths.
     for (size_t i = 0; i < failurePaths.length(); i++) {
         emitFailurePath(i);
         EmitStubGuardFailure(masm);
     }
 
@@ -1111,21 +1134,17 @@ BaselineCacheIRCompiler::emitLoadDynamic
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitCallScriptedGetterResult()
 {
     MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
 
-    // We use ICTailCallReg when entering the stub frame, so ensure it's not
-    // used for something else.
-    Maybe<AutoScratchRegister> tail;
-    if (allocator.isAllocatable(ICTailCallReg))
-        tail.emplace(allocator, masm, ICTailCallReg);
+    AutoStubFrame stubFrame(*this);
 
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address getterAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegisterExcluding code(allocator, masm, ArgumentsRectifierReg);
     AutoScratchRegister callee(allocator, masm);
     AutoScratchRegister scratch(allocator, masm);
 
@@ -1138,18 +1157,17 @@ BaselineCacheIRCompiler::emitCallScripte
         masm.loadPtr(getterAddr, callee);
         masm.branchIfFunctionHasNoScript(callee, failure->label());
         masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
         masm.loadBaselineOrIonRaw(code, code, failure->label());
     }
 
     allocator.discardStack(masm);
 
-    // Push a stub frame so that we can perform a non-tail call.
-    enterStubFrame(masm, scratch);
+    stubFrame.enter(masm, scratch);
 
     // Align the stack such that the JitFrameLayout is aligned on
     // JitStackAlignment.
     masm.alignJitStackBasedOnNArgs(0);
 
     // Getter is called with 0 arguments, just |obj| as thisv.
     // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
@@ -1172,89 +1190,79 @@ BaselineCacheIRCompiler::emitCallScripte
         masm.movePtr(ImmGCPtr(argumentsRectifier), code);
         masm.loadPtr(Address(code, JitCode::offsetOfCode()), code);
         masm.movePtr(ImmWord(0), ArgumentsRectifierReg);
     }
 
     masm.bind(&noUnderflow);
     masm.callJit(code);
 
-    leaveStubFrame(masm, true);
+    stubFrame.leave(masm, true);
     return true;
 }
 
 typedef bool (*DoCallNativeGetterFn)(JSContext*, HandleFunction, HandleObject, MutableHandleValue);
 static const VMFunction DoCallNativeGetterInfo =
     FunctionInfo<DoCallNativeGetterFn>(DoCallNativeGetter, "DoCallNativeGetter");
 
 bool
 BaselineCacheIRCompiler::emitCallNativeGetterResult()
 {
-    // We use ICTailCallReg when entering the stub frame, so ensure it's not
-    // used for something else.
-    Maybe<AutoScratchRegister> tail;
-    if (allocator.isAllocatable(ICTailCallReg))
-        tail.emplace(allocator, masm, ICTailCallReg);
+    AutoStubFrame stubFrame(*this);
 
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address getterAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
-    // Push a stub frame so that we can perform a non-tail call.
-    enterStubFrame(masm, scratch);
+    stubFrame.enter(masm, scratch);
 
     // Load the callee in the scratch register.
     masm.loadPtr(getterAddr, scratch);
 
     masm.Push(obj);
     masm.Push(scratch);
 
     if (!callVM(masm, DoCallNativeGetterInfo))
         return false;
 
-    leaveStubFrame(masm);
+    stubFrame.leave(masm);
     return true;
 }
 
 typedef bool (*ProxyGetPropertyFn)(JSContext*, HandleObject, HandleId, MutableHandleValue);
 static const VMFunction ProxyGetPropertyInfo =
     FunctionInfo<ProxyGetPropertyFn>(ProxyGetProperty, "ProxyGetProperty");
 
 bool
 BaselineCacheIRCompiler::emitCallProxyGetResult()
 {
-    // We use ICTailCallReg when entering the stub frame, so ensure it's not
-    // used for something else.
-    Maybe<AutoScratchRegister> tail;
-    if (allocator.isAllocatable(ICTailCallReg))
-        tail.emplace(allocator, masm, ICTailCallReg);
+    AutoStubFrame stubFrame(*this);
 
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address idAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
-    // Push a stub frame so that we can perform a non-tail call.
-    enterStubFrame(masm, scratch);
+    stubFrame.enter(masm, scratch);
 
     // Load the jsid in the scratch register.
     masm.loadPtr(idAddr, scratch);
 
     masm.Push(scratch);
     masm.Push(obj);
 
     if (!callVM(masm, ProxyGetPropertyInfo))
         return false;
 
-    leaveStubFrame(masm);
+    stubFrame.leave(masm);
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     AutoScratchRegister scratch(allocator, masm);
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -25,17 +25,16 @@ GetPropIRGenerator::GetPropIRGenerator(J
   : writer(cx),
     cx_(cx),
     pc_(pc),
     val_(val),
     name_(name),
     res_(res),
     engine_(engine),
     isTemporarilyUnoptimizable_(isTemporarilyUnoptimizable),
-    emitted_(false),
     preliminaryObjectAction_(PreliminaryObjectAction::None)
 {}
 
 static void
 EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderOp, NativeObject* holder,
                    Shape* shape)
 {
     if (holder->isFixedSlot(shape->slot())) {
@@ -46,47 +45,45 @@ EmitLoadSlotResult(CacheIRWriter& writer
     }
 }
 
 bool
 GetPropIRGenerator::tryAttachStub()
 {
     AutoAssertNoPendingException aanpe(cx_);
 
-    MOZ_ASSERT(!emitted_);
-
     ValOperandId valId(writer.setInputOperandId(0));
 
     if (val_.isObject()) {
         RootedObject obj(cx_, &val_.toObject());
         ObjOperandId objId = writer.guardIsObject(valId);
 
-        if (!emitted_ && !tryAttachObjectLength(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachNative(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachUnboxed(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachUnboxedExpando(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachTypedObject(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachModuleNamespace(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachWindowProxy(obj, objId))
-            return false;
-        if (!emitted_ && !tryAttachProxy(obj, objId))
-            return false;
-        return true;
+        if (tryAttachObjectLength(obj, objId))
+            return true;
+        if (tryAttachNative(obj, objId))
+            return true;
+        if (tryAttachUnboxed(obj, objId))
+            return true;
+        if (tryAttachUnboxedExpando(obj, objId))
+            return true;
+        if (tryAttachTypedObject(obj, objId))
+            return true;
+        if (tryAttachModuleNamespace(obj, objId))
+            return true;
+        if (tryAttachWindowProxy(obj, objId))
+            return true;
+        if (tryAttachProxy(obj, objId))
+            return true;
+        return false;
     }
 
-    if (!emitted_ && !tryAttachPrimitive(valId))
-        return false;
+    if (tryAttachPrimitive(valId))
+        return true;
 
-    return true;
+    return false;
 }
 
 static bool
 IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
                       jsbytecode* pc)
 {
     if (shape)
         return false;
@@ -297,64 +294,55 @@ EmitCallGetterResult(CacheIRWriter& writ
     }
 
     EmitCallGetterResultNoGuards(writer, obj, holder, shape, objId);
 }
 
 bool
 GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     RootedShape shape(cx_);
     RootedNativeObject holder(cx_);
 
     RootedId id(cx_, NameToId(name_));
     NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, obj, id, &holder, &shape, pc_,
                                                             engine_, isTemporarilyUnoptimizable_);
-    if (type == CanAttachNone)
-        return true;
-
-    emitted_ = true;
-
     switch (type) {
+      case CanAttachNone:
+        return false;
       case CanAttachReadSlot:
         if (holder) {
             EnsureTrackPropertyTypes(cx_, holder, NameToId(name_));
             if (obj == holder) {
                 // See the comment in StripPreliminaryObjectStubs.
                 if (IsPreliminaryObject(obj))
                     preliminaryObjectAction_ = PreliminaryObjectAction::NotePreliminary;
                 else
                     preliminaryObjectAction_ = PreliminaryObjectAction::Unlink;
             }
         }
         EmitReadSlotResult(writer, obj, holder, shape, objId);
         EmitReadSlotReturn(writer, obj, holder, shape);
-        break;
+        return true;
       case CanAttachCallGetter:
         EmitCallGetterResult(writer, obj, holder, shape, objId);
-        break;
-      default:
-        MOZ_CRASH("Bad NativeGetPropCacheability");
+        return true;
     }
 
-    return true;
+    MOZ_CRASH("Bad NativeGetPropCacheability");
 }
 
 bool
 GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId)
 {
     // Attach a stub when the receiver is a WindowProxy and we are calling some
     // kinds of JSNative getters on the Window object (the global object).
 
-    MOZ_ASSERT(!emitted_);
-
     if (!IsWindowProxy(obj))
-        return true;
+        return false;
 
     // This must be a WindowProxy for the current Window/global. Else it would
     // be a cross-compartment wrapper and IsWindowProxy returns false for
     // those.
     MOZ_ASSERT(obj->getClass() == cx_->maybeWindowProxyClass());
     MOZ_ASSERT(ToWindowIfWindowProxy(obj) == cx_->global());
 
     // Now try to do the lookup on the Window (the current global) and see if
@@ -363,63 +351,55 @@ GetPropIRGenerator::tryAttachWindowProxy
     RootedShape shape(cx_);
     RootedNativeObject holder(cx_);
     RootedId id(cx_, NameToId(name_));
     NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, windowObj, id, &holder, &shape, pc_,
                                                             engine_, isTemporarilyUnoptimizable_);
     if (type != CanAttachCallGetter ||
         !IsCacheableGetPropCallNative(windowObj, holder, shape))
     {
-        return true;
+        return false;
     }
 
     // Make sure the native getter is okay with the IC passing the Window
     // instead of the WindowProxy as |this| value.
     JSFunction* callee = &shape->getterObject()->as<JSFunction>();
     MOZ_ASSERT(callee->isNative());
     if (!callee->jitInfo() || callee->jitInfo()->needsOuterizedThisObject())
-        return true;
-
-    emitted_ = true;
+        return false;
 
     // Guard the incoming object is a WindowProxy and inline a getter call based
     // on the Window object.
     writer.guardClass(objId, GuardClassKind::WindowProxy);
     ObjOperandId windowObjId = writer.loadObject(windowObj);
     EmitCallGetterResult(writer, windowObj, holder, shape, windowObjId);
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
     MOZ_ASSERT(obj->is<ProxyObject>());
 
-    emitted_ = true;
-
     writer.guardIsProxy(objId);
 
     // Ensure that the incoming object is not a DOM proxy, so that we can get to
     // the specialized stubs
     writer.guardNotDOMProxy(objId);
 
     writer.callProxyGetResult(objId, NameToId(name_));
     writer.typeMonitorResult();
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
     MOZ_ASSERT(IsCacheableDOMProxy(obj));
 
-    emitted_ = true;
-
     writer.guardShape(objId, obj->maybeShape());
 
     // No need for more guards: we know this is a DOM proxy, since the shape
     // guard enforces a given JSClass, so just go ahead and emit the call to
     // ProxyGet.
     writer.callProxyGetResult(objId, NameToId(name_));
     writer.typeMonitorResult();
     return true;
@@ -457,31 +437,28 @@ CheckDOMProxyExpandoDoesNotShadow(CacheI
     } else {
         MOZ_CRASH("Invalid expando value");
     }
 }
 
 bool
 GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
     MOZ_ASSERT(IsCacheableDOMProxy(obj));
 
     RootedObject checkObj(cx_, obj->staticPrototype());
     RootedNativeObject holder(cx_);
     RootedShape shape(cx_);
 
     RootedId id(cx_, NameToId(name_));
     NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape,
                                                                 pc_, engine_,
                                                                 isTemporarilyUnoptimizable_);
     if (canCache == CanAttachNone)
-        return true;
-
-    emitted_ = true;
+        return false;
 
     writer.guardShape(objId, obj->maybeShape());
 
     // Guard that our expando object hasn't started shadowing this property.
     CheckDOMProxyExpandoDoesNotShadow(writer, obj, id, objId);
 
     if (holder) {
         // Found the property on the prototype chain. Treat it like a native
@@ -511,20 +488,18 @@ GetPropIRGenerator::tryAttachDOMProxyUns
     }
 
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (!obj->is<ProxyObject>())
-        return true;
+        return false;
 
     // Skim off DOM proxies.
     if (IsCacheableDOMProxy(obj)) {
         RootedId id(cx_, NameToId(name_));
         DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx_, obj, id);
         if (shadows == ShadowCheckFailed) {
             cx_->clearPendingException();
             return false;
@@ -537,88 +512,79 @@ GetPropIRGenerator::tryAttachProxy(Handl
     }
 
     return tryAttachGenericProxy(obj, objId);
 }
 
 bool
 GetPropIRGenerator::tryAttachUnboxed(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (!obj->is<UnboxedPlainObject>())
-        return true;
+        return false;
 
     const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(name_);
     if (!property)
-        return true;
+        return false;
 
     if (!cx_->runtime()->jitSupportsFloatingPoint)
-        return true;
+        return false;
 
     writer.guardGroup(objId, obj->group());
     writer.loadUnboxedPropertyResult(objId, property->type,
                                      UnboxedPlainObject::offsetOfData() + property->offset);
     if (property->type == JSVAL_TYPE_OBJECT)
         writer.typeMonitorResult();
     else
         writer.returnFromIC();
 
-    emitted_ = true;
     preliminaryObjectAction_ = PreliminaryObjectAction::Unlink;
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (!obj->is<UnboxedPlainObject>())
-        return true;
+        return false;
 
     UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
     if (!expando)
-        return true;
+        return false;
 
     Shape* shape = expando->lookup(cx_, NameToId(name_));
     if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
-        return true;
-
-    emitted_ = true;
+        return false;
 
     EmitReadSlotResult(writer, obj, obj, shape, objId);
     EmitReadSlotReturn(writer, obj, obj, shape);
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (!obj->is<TypedObject>() ||
         !cx_->runtime()->jitSupportsFloatingPoint ||
         cx_->compartment()->detachedTypedObjects)
     {
-        return true;
+        return false;
     }
 
     TypedObject* typedObj = &obj->as<TypedObject>();
     if (!typedObj->typeDescr().is<StructTypeDescr>())
-        return true;
+        return false;
 
     StructTypeDescr* structDescr = &typedObj->typeDescr().as<StructTypeDescr>();
     size_t fieldIndex;
     if (!structDescr->fieldIndex(NameToId(name_), &fieldIndex))
-        return true;
+        return false;
 
     TypeDescr* fieldDescr = &structDescr->fieldDescr(fieldIndex);
     if (!fieldDescr->is<SimpleTypeDescr>())
-        return true;
+        return false;
 
     Shape* shape = typedObj->maybeShape();
     TypedThingLayout layout = GetTypedThingLayout(shape->getObjectClass());
 
     uint32_t fieldOffset = structDescr->fieldOffset(fieldIndex);
     uint32_t typeDescr = SimpleTypeDescrKey(&fieldDescr->as<SimpleTypeDescr>());
 
     writer.guardNoDetachedTypedObjects();
@@ -635,139 +601,125 @@ GetPropIRGenerator::tryAttachTypedObject
         monitorLoad = type != ReferenceTypeDescr::TYPE_STRING;
     }
 
     if (monitorLoad)
         writer.typeMonitorResult();
     else
         writer.returnFromIC();
 
-    emitted_ = true;
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (name_ != cx_->names().length)
-        return true;
+        return false;
 
     if (obj->is<ArrayObject>()) {
         // Make sure int32 is added to the TypeSet before we attach a stub, so
         // the stub can return int32 values without monitoring the result.
         if (obj->as<ArrayObject>().length() > INT32_MAX)
-            return true;
+            return false;
 
         writer.guardClass(objId, GuardClassKind::Array);
         writer.loadInt32ArrayLengthResult(objId);
         writer.returnFromIC();
-        emitted_ = true;
         return true;
     }
 
     if (obj->is<UnboxedArrayObject>()) {
         writer.guardClass(objId, GuardClassKind::UnboxedArray);
         writer.loadUnboxedArrayLengthResult(objId);
         writer.returnFromIC();
-        emitted_ = true;
         return true;
     }
 
     if (obj->is<ArgumentsObject>() && !obj->as<ArgumentsObject>().hasOverriddenLength()) {
         if (obj->is<MappedArgumentsObject>()) {
             writer.guardClass(objId, GuardClassKind::MappedArguments);
         } else {
             MOZ_ASSERT(obj->is<UnmappedArgumentsObject>());
             writer.guardClass(objId, GuardClassKind::UnmappedArguments);
         }
         writer.loadArgumentsObjectLengthResult(objId);
         writer.returnFromIC();
-        emitted_ = true;
         return true;
     }
 
-    return true;
+    return false;
 }
 
 bool
 GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId)
 {
-    MOZ_ASSERT(!emitted_);
-
     if (!obj->is<ModuleNamespaceObject>())
-        return true;
+        return false;
 
     Rooted<ModuleNamespaceObject*> ns(cx_, &obj->as<ModuleNamespaceObject>());
     RootedModuleEnvironmentObject env(cx_);
     RootedShape shape(cx_);
     if (!ns->bindings().lookup(NameToId(name_), env.address(), shape.address()))
-        return true;
+        return false;
 
     // Don't emit a stub until the target binding has been initialized.
     if (env->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL))
-        return true;
+        return false;
 
     if (IsIonEnabled(cx_))
         EnsureTrackPropertyTypes(cx_, env, shape->propid());
 
-    emitted_ = true;
-
     // Check for the specific namespace object.
     writer.guardSpecificObject(objId, ns);
 
     ObjOperandId envId = writer.loadObject(env);
     EmitLoadSlotResult(writer, envId, env, shape);
     writer.typeMonitorResult();
     return true;
 }
 
 bool
 GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId)
 {
-    MOZ_ASSERT(!emitted_);
-
     JSValueType primitiveType;
     RootedNativeObject proto(cx_);
     if (val_.isString()) {
         if (name_ == cx_->names().length) {
             // String length is special-cased, see js::GetProperty.
-            return true;
+            return false;
         }
         primitiveType = JSVAL_TYPE_STRING;
         proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_String));
     } else if (val_.isNumber()) {
         primitiveType = JSVAL_TYPE_DOUBLE;
         proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Number));
     } else if (val_.isBoolean()) {
         primitiveType = JSVAL_TYPE_BOOLEAN;
         proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Boolean));
     } else if (val_.isSymbol()) {
         primitiveType = JSVAL_TYPE_SYMBOL;
         proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Symbol));
     } else {
         MOZ_ASSERT(val_.isNullOrUndefined() || val_.isMagic());
-        return true;
+        return false;
     }
     if (!proto)
-        return true;
+        return false;
 
     // Instantiate this property, for use during Ion compilation.
     RootedId id(cx_, NameToId(name_));
     if (IsIonEnabled(cx_))
         EnsureTrackPropertyTypes(cx_, proto, id);
 
     // For now, only look for properties directly set on the prototype.
     Shape* shape = proto->lookup(cx_, id);
     if (!shape || !shape->hasSlot() || !shape->hasDefaultGetter())
-        return true;
+        return false;
 
     writer.guardType(valId, primitiveType);
 
     ObjOperandId protoId = writer.loadObject(proto);
     writer.guardShape(protoId, proto->lastProperty());
     EmitLoadSlotResult(writer, protoId, proto, shape);
     writer.typeMonitorResult();
-
-    emitted_ = true;
     return true;
 }
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -514,47 +514,44 @@ class MOZ_RAII GetPropIRGenerator
     CacheIRWriter writer;
     JSContext* cx_;
     jsbytecode* pc_;
     HandleValue val_;
     HandlePropertyName name_;
     MutableHandleValue res_;
     ICStubEngine engine_;
     bool* isTemporarilyUnoptimizable_;
-    bool emitted_;
 
     enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
     PreliminaryObjectAction preliminaryObjectAction_;
 
-    MOZ_MUST_USE bool tryAttachNative(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId);
+    bool tryAttachNative(HandleObject obj, ObjOperandId objId);
+    bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId);
+    bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId);
+    bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId);
+    bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId);
+    bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId);
+    bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId);
 
-    MOZ_MUST_USE bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId);
-    MOZ_MUST_USE bool tryAttachProxy(HandleObject obj, ObjOperandId objId);
+    bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId);
+    bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId);
+    bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId);
+    bool tryAttachProxy(HandleObject obj, ObjOperandId objId);
 
-    MOZ_MUST_USE bool tryAttachPrimitive(ValOperandId valId);
+    bool tryAttachPrimitive(ValOperandId valId);
 
     GetPropIRGenerator(const GetPropIRGenerator&) = delete;
     GetPropIRGenerator& operator=(const GetPropIRGenerator&) = delete;
 
   public:
     GetPropIRGenerator(JSContext* cx, jsbytecode* pc, ICStubEngine engine,
                        bool* isTemporarilyUnoptimizable,
                        HandleValue val, HandlePropertyName name, MutableHandleValue res);
 
-    bool emitted() const { return emitted_; }
-
-    MOZ_MUST_USE bool tryAttachStub();
+    bool tryAttachStub();
 
     bool shouldUnlinkPreliminaryObjectStubs() const {
         return preliminaryObjectAction_ == PreliminaryObjectAction::Unlink;
     }
     bool shouldNotePreliminaryObjectStub() const {
         return preliminaryObjectAction_ == PreliminaryObjectAction::NotePreliminary;
     }
     const CacheIRWriter& writerRef() const {
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4110,27 +4110,27 @@ AnalyzePoppedThis(JSContext* cx, ObjectG
 static int
 CmpInstructions(const void* a, const void* b)
 {
     return (*static_cast<MInstruction * const*>(a))->id() -
            (*static_cast<MInstruction * const*>(b))->id();
 }
 
 bool
-jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
+jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, HandleFunction fun,
                                         ObjectGroup* group, HandlePlainObject baseobj,
                                         Vector<TypeNewScript::Initializer>* initializerList)
 {
     MOZ_ASSERT(cx->zone()->types.activeAnalysis);
 
     // When invoking 'new' on the specified script, try to find some properties
     // which will definitely be added to the created object before it has a
     // chance to escape and be accessed elsewhere.
 
-    RootedScript script(cx, fun->getOrCreateScript(cx));
+    RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
     if (!script)
         return false;
 
     if (!jit::IsIonEnabled(cx) || !jit::IsBaselineEnabled(cx) || !script->canBaselineCompile())
         return true;
 
     static const uint32_t MAX_SCRIPT_SIZE = 2000;
     if (script->length() > MAX_SCRIPT_SIZE)
--- a/js/src/jit/IonAnalysis.h
+++ b/js/src/jit/IonAnalysis.h
@@ -191,17 +191,17 @@ ConvertLinearSum(TempAllocator& alloc, M
                  bool convertConstant = false);
 
 // Convert the test 'sum >= 0' to a comparison, adding any necessary
 // instructions to the end of block.
 MCompare*
 ConvertLinearInequality(TempAllocator& alloc, MBasicBlock* block, const LinearSum& sum);
 
 MOZ_MUST_USE bool
-AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
+AnalyzeNewScriptDefiniteProperties(JSContext* cx, HandleFunction fun,
                                    ObjectGroup* group, HandlePlainObject baseobj,
                                    Vector<TypeNewScript::Initializer>* initializerList);
 
 MOZ_MUST_USE bool
 AnalyzeArgumentsUsage(JSContext* cx, JSScript* script);
 
 bool
 DeadIfUnused(const MDefinition* def);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -462,17 +462,18 @@ IonBuilder::canInlineTarget(JSFunction* 
                 return DontInline(nullptr, "Empty TypeSet for argument");
             }
         }
     }
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
     if (target->isInterpreted() && info().analysisMode() == Analysis_DefiniteProperties) {
-        RootedScript script(analysisContext, target->getOrCreateScript(analysisContext));
+        RootedFunction fun(analysisContext, target);
+        RootedScript script(analysisContext, JSFunction::getOrCreateScript(analysisContext, fun));
         if (!script)
             return InliningDecision_Error;
 
         if (!script->hasBaselineScript() && script->canBaselineCompile()) {
             MethodStatus status = BaselineCompile(analysisContext, script);
             if (status == Method_Error)
                 return InliningDecision_Error;
             if (status != Method_Compiled) {
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -973,17 +973,17 @@ class MacroAssembler : public MacroAssem
 
     // The supported condition are Equal, NotEqual, LessThan(orEqual), GreaterThan(orEqual),
     // Below(orEqual) and Above(orEqual).
     // When a fail label is not defined it will fall through to next instruction,
     // else jump to the fail label.
     inline void branch64(Condition cond, Register64 lhs, Imm64 val, Label* success,
                          Label* fail = nullptr) PER_ARCH;
     inline void branch64(Condition cond, Register64 lhs, Register64 rhs, Label* success,
-                         Label* fail = nullptr) DEFINED_ON(x86, x64, arm, mips32, mips64);
+                         Label* fail = nullptr) PER_ARCH;
     // On x86 and x64 NotEqual and Equal conditions are allowed for the branch64 variants
     // with Address as lhs. On others only the NotEqual condition.
     inline void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) PER_ARCH;
 
     // Compare the value at |lhs| with the value at |rhs|.  The scratch
     // register *must not* be the base of |lhs| or |rhs|.
     inline void branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
                          Label* label) PER_ARCH;
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -2467,19 +2467,17 @@ DoGetPropFallback(JSContext* cx, void* p
         if (!newStub)
             return false;
         stub->addNewStub(newStub);
         attached = true;
     }
 
     if (!attached && !JitOptions.disableCacheIR) {
         GetPropIRGenerator gen(cx, pc, engine, &isTemporarilyUnoptimizable, val, name, res);
-        if (!gen.tryAttachStub())
-            return false;
-        if (gen.emitted()) {
+        if (gen.tryAttachStub()) {
             ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), CacheKind::GetProp,
                                                         engine, info.outerScript(cx), stub);
             if (newStub) {
                 JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
                 attached = true;
                 if (gen.shouldNotePreliminaryObjectStub())
                     newStub->toCacheIR_Monitored()->notePreliminaryObject();
                 else if (gen.shouldUnlinkPreliminaryObjectStubs())
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -555,17 +555,17 @@ GetIntrinsicValue(JSContext* cx, HandleP
 bool
 CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval)
 {
     rval.set(MagicValue(JS_IS_CONSTRUCTING));
 
     if (callee->is<JSFunction>()) {
         RootedFunction fun(cx, &callee->as<JSFunction>());
         if (fun->isInterpreted() && fun->isConstructor()) {
-            JSScript* script = fun->getOrCreateScript(cx);
+            JSScript* script = JSFunction::getOrCreateScript(cx, fun);
             if (!script || !script->ensureHasTypes(cx))
                 return false;
             if (fun->isBoundFunction() || script->isDerivedClassConstructor()) {
                 rval.set(MagicValue(JS_UNINITIALIZED_LEXICAL));
             } else {
                 JSObject* thisObj = CreateThisForFunction(cx, callee, newTarget, GenericObject);
                 if (!thisObj)
                     return false;
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -1005,16 +1005,24 @@ Assembler::ConditionWithoutEqual(Conditi
         return GreaterThan;
       case Above:
       case AboveOrEqual:
         return Above;
       default:
         MOZ_CRASH("unexpected condition");
     }
 }
+
+Assembler::DoubleCondition
+Assembler::InvertCondition(DoubleCondition cond)
+{
+    const uint32_t ConditionInversionBit = 0x10000000;
+    return DoubleCondition(ConditionInversionBit ^ cond);
+}
+
 Imm8::TwoImm8mData
 Imm8::EncodeTwoImms(uint32_t imm)
 {
     // In the ideal case, we are looking for a number that (in binary) looks
     // like:
     //   0b((00)*)n_1((00)*)n_2((00)*)
     //      left  n1   mid  n2
     //   where both n_1 and n_2 fit into 8 bits.
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -1343,16 +1343,18 @@ class Assembler : public AssemblerShared
     void initWithAllocator() {
         m_buffer.initWithAllocator();
     }
 
     static Condition InvertCondition(Condition cond);
     static Condition UnsignedCondition(Condition cond);
     static Condition ConditionWithoutEqual(Condition cond);
 
+    static DoubleCondition InvertCondition(DoubleCondition cond);
+
     // MacroAssemblers hold onto gcthings, so they are traced by the GC.
     void trace(JSTracer* trc);
     void writeRelocation(BufferOffset src) {
         jumpRelocations_.writeUnsigned(src.getOffset());
     }
 
     // As opposed to x86/x64 version, the data relocation has to be executed
     // before to recover the pointer, and not after.
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -850,16 +850,22 @@ MacroAssembler::branch32(Condition cond,
 
 void
 MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, Label* success, Label* fail)
 {
     MOZ_CRASH("NYI: branch64 reg-imm");
 }
 
 void
+MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, Label* success, Label* fail)
+{
+    MOZ_CRASH("NYI: branch64 reg-reg");
+}
+
+void
 MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, Label* label)
 {
     MOZ_ASSERT(cond == Assembler::NotEqual,
                "other condition codes not supported");
 
     branchPtr(cond, lhs, ImmWord(val.value), label);
 }
 
--- a/js/src/jit/arm64/vixl/Assembler-vixl.h
+++ b/js/src/jit/arm64/vixl/Assembler-vixl.h
@@ -936,16 +936,20 @@ class Assembler : public MozBaseAssemble
     case pl:
       return mi;
     default:
       MOZ_CRASH("TODO: figure this case out.");
     }
     return static_cast<Condition>(cond ^ 1);
   }
 
+  static inline DoubleCondition InvertCondition(DoubleCondition cond) {
+    MOZ_CRASH("Not yet implemented: InvertCondition(DoubleCondition)");
+  }
+
   static inline Condition ConditionFromDoubleCondition(DoubleCondition cond) {
     VIXL_ASSERT(!(cond & DoubleConditionBitSpecial));
     return static_cast<Condition>(cond);
   }
 
   // Instruction set functions.
 
   // Branch / Jump instructions.
--- a/js/src/jit/x86-shared/Assembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.cpp
@@ -216,16 +216,49 @@ AssemblerX86Shared::ConditionWithoutEqua
       case Above:
       case AboveOrEqual:
         return Above;
       default:
         MOZ_CRASH("unexpected condition");
     }
 }
 
+AssemblerX86Shared::DoubleCondition
+AssemblerX86Shared::InvertCondition(DoubleCondition cond)
+{
+    switch (cond) {
+      case DoubleEqual:
+        return DoubleNotEqualOrUnordered;
+      case DoubleEqualOrUnordered:
+        return DoubleNotEqual;
+      case DoubleNotEqualOrUnordered:
+        return DoubleEqual;
+      case DoubleNotEqual:
+        return DoubleEqualOrUnordered;
+      case DoubleLessThan:
+        return DoubleGreaterThanOrEqualOrUnordered;
+      case DoubleLessThanOrUnordered:
+        return DoubleGreaterThanOrEqual;
+      case DoubleLessThanOrEqual:
+        return DoubleGreaterThanOrUnordered;
+      case DoubleLessThanOrEqualOrUnordered:
+        return DoubleGreaterThan;
+      case DoubleGreaterThan:
+        return DoubleLessThanOrEqualOrUnordered;
+      case DoubleGreaterThanOrUnordered:
+        return DoubleLessThanOrEqual;
+      case DoubleGreaterThanOrEqual:
+        return DoubleLessThanOrUnordered;
+      case DoubleGreaterThanOrEqualOrUnordered:
+        return DoubleLessThan;
+      default:
+        MOZ_CRASH("unexpected condition");
+    }
+}
+
 void
 AssemblerX86Shared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
                                                 const Disassembler::HeapAccess& heapAccess)
 {
 #ifdef DEBUG
     if (masm.oom())
         return;
     Disassembler::VerifyHeapAccess(masm.data() + begin, masm.data() + end, heapAccess);
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -382,16 +382,18 @@ class AssemblerX86Shared : public Assemb
         JS_STATIC_ASSERT(!((Equal | NotEqual | Above | AboveOrEqual | Below |
                             BelowOrEqual | Parity | NoParity) & DoubleConditionBits));
     }
 
     static Condition InvertCondition(Condition cond);
     static Condition UnsignedCondition(Condition cond);
     static Condition ConditionWithoutEqual(Condition cond);
 
+    static DoubleCondition InvertCondition(DoubleCondition cond);
+
     // Return the primary condition to test. Some primary conditions may not
     // handle NaNs properly and may therefore require a secondary condition.
     // Use NaNCondFromDoubleCondition to determine what else is needed.
     static inline Condition ConditionFromDoubleCondition(DoubleCondition cond) {
         return static_cast<Condition>(cond & ~DoubleConditionBits);
     }
 
     static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -641,17 +641,17 @@ BEGIN_TEST(test_JS_ubi_Node_scriptFilena
                    &val));
 
     CHECK(val.isObject());
     JS::RootedObject obj(cx, &val.toObject());
 
     CHECK(obj->is<JSFunction>());
     JS::RootedFunction func(cx, &obj->as<JSFunction>());
 
-    JS::RootedScript script(cx, func->getOrCreateScript(cx));
+    JS::RootedScript script(cx, JSFunction::getOrCreateScript(cx, func));
     CHECK(script);
     CHECK(script->filename());
 
     JS::ubi::Node node(script);
     const char* filename = node.scriptFilename();
     CHECK(filename);
     CHECK(strcmp(filename, script->filename()) == 0);
     CHECK(strcmp(filename, "my-cool-filename.js") == 0);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3419,20 +3419,17 @@ JS::NewFunctionFromSpec(JSContext* cx, c
         if (!name)
             return nullptr;
         RootedValue funVal(cx);
         if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs,
                                                  &funVal))
         {
             return nullptr;
         }
-        JSFunction* fun = &funVal.toObject().as<JSFunction>();
-        if (fs->flags & JSFUN_HAS_REST)
-            fun->setHasRest();
-        return fun;
+        return &funVal.toObject().as<JSFunction>();
     }
 
     RootedAtom atom(cx, IdToFunctionName(cx, id));
     if (!atom)
         return nullptr;
 
     JSFunction* fun;
     if (!fs->call.op)
@@ -3524,17 +3521,17 @@ CloneFunctionObject(JSContext* cx, Handl
         RootedValue v(cx, ObjectValue(*funobj));
         ReportIsNotFunction(cx, v);
         return nullptr;
     }
 
     RootedFunction fun(cx, &funobj->as<JSFunction>());
     if (fun->isInterpretedLazy()) {
         AutoCompartment ac(cx, funobj);
-        if (!fun->getOrCreateScript(cx))
+        if (!JSFunction::getOrCreateScript(cx, fun))
             return nullptr;
     }
 
     if (!IsFunctionCloneable(fun)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
         return nullptr;
     }
 
@@ -3556,17 +3553,17 @@ CloneFunctionObject(JSContext* cx, Handl
     if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
         // If the script is to be reused, either the script can already handle
         // non-syntactic scopes, or there is only the standard global lexical
         // scope.
 #ifdef DEBUG
         // Fail here if we OOM during debug asserting.
         // CloneFunctionReuseScript will delazify the script anyways, so we
         // are not creating an extra failure condition for DEBUG builds.
-        if (!fun->getOrCreateScript(cx))
+        if (!JSFunction::getOrCreateScript(cx, fun))
             return nullptr;
         MOZ_ASSERT(scope->as<GlobalScope>().isSyntactic() ||
                    fun->nonLazyScript()->hasNonSyntacticScope());
 #endif
         return CloneFunctionReuseScript(cx, fun, env, fun->getAllocKind());
     }
 
     JSFunction* clone = CloneFunctionAndScript(cx, fun, env, scope, fun->getAllocKind());
@@ -4211,17 +4208,17 @@ JS_GetScriptBaseLineNumber(JSContext* cx
 
 JS_PUBLIC_API(JSScript*)
 JS_GetFunctionScript(JSContext* cx, HandleFunction fun)
 {
     if (fun->isNative())
         return nullptr;
     if (fun->isInterpretedLazy()) {
         AutoCompartment funCompartment(cx, fun);
-        JSScript* script = fun->getOrCreateScript(cx);
+        JSScript* script = JSFunction::getOrCreateScript(cx, fun);
         if (!script)
             MOZ_CRASH();
         return script;
     }
     return fun->nonLazyScript();
 }
 
 /*
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -870,21 +870,17 @@ class MOZ_STACK_CLASS SourceBufferHolder
                                            containing this property */
 #define JSPROP_INTERNAL_USE_BIT 0x80    /* internal JS engine use only */
 #define JSFUN_STUB_GSOPS       0x200    /* use JS_PropertyStub getter/setter
                                            instead of defaulting to class gsops
                                            for property holding function */
 
 #define JSFUN_CONSTRUCTOR      0x400    /* native that can be called as a ctor */
 
-//                             0x800    /* Unused */
-
-#define JSFUN_HAS_REST        0x1000    /* function has ...rest parameter. */
-
-#define JSFUN_FLAGS_MASK      0x1e00    /* | of all the JSFUN_* flags */
+#define JSFUN_FLAGS_MASK       0x600    /* | of all the JSFUN_* flags */
 
 /*
  * If set, will allow redefining a non-configurable property, but only on a
  * non-DOM global.  This is a temporary hack that will need to go away in bug
  * 1105518.
  */
 #define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1707,21 +1707,21 @@ MatchNumericComparator(JSContext* cx, co
 {
     if (!v.isObject())
         return Match_None;
 
     JSObject& obj = v.toObject();
     if (!obj.is<JSFunction>())
         return Match_None;
 
-    JSFunction* fun = &obj.as<JSFunction>();
+    RootedFunction fun(cx, &obj.as<JSFunction>());
     if (!fun->isInterpreted() || fun->isClassConstructor())
         return Match_None;
 
-    JSScript* script = fun->getOrCreateScript(cx);
+    JSScript* script = JSFunction::getOrCreateScript(cx, fun);
     if (!script)
         return Match_Failure;
 
     jsbytecode* pc = script->code();
 
     uint16_t arg0, arg1;
     if (JSOp(*pc) != JSOP_GETARG)
         return Match_None;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -1047,28 +1047,28 @@ CreateLazyScriptsForCompartment(JSContex
     // Methods, for instance {get method() {}}, are extended functions that can
     // be relazified, so we need to handle those as well.
     if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED))
         return false;
 
     // Create scripts for each lazy function, updating the list of functions to
     // process with any newly exposed inner functions in created scripts.
     // A function cannot be delazified until its outer script exists.
+    RootedFunction fun(cx);
     for (size_t i = 0; i < lazyFunctions.length(); i++) {
-        JSFunction* fun = &lazyFunctions[i]->as<JSFunction>();
+        fun = &lazyFunctions[i]->as<JSFunction>();
 
         // lazyFunctions may have been populated with multiple functions for
         // a lazy script.
         if (!fun->isInterpretedLazy())
             continue;
 
-        LazyScript* lazy = fun->lazyScript();
-        bool lazyScriptHadNoScript = !lazy->maybeScript();
+        bool lazyScriptHadNoScript = !fun->lazyScript()->maybeScript();
 
-        JSScript* script = fun->getOrCreateScript(cx);
+        JSScript* script = JSFunction::getOrCreateScript(cx, fun);
         if (!script)
             return false;
         if (lazyScriptHadNoScript && !AddInnerLazyFunctionsFromScript(script, lazyFunctions))
             return false;
     }
 
     return true;
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -492,17 +492,17 @@ fun_resolve(JSContext* cx, HandleObject 
         //     assertEq(f.length, 0);  // gets Function.prototype.length!
         //     assertEq(f.name, "");  // gets Function.prototype.name!
         // We use the RESOLVED_LENGTH and RESOLVED_NAME flags as a hack to prevent this
         // bug.
         if (isLength) {
             if (fun->hasResolvedLength())
                 return true;
 
-            if (!fun->getUnresolvedLength(cx, &v))
+            if (!JSFunction::getUnresolvedLength(cx, fun, &v))
                 return false;
         } else {
             if (fun->hasResolvedName())
                 return true;
 
             // Don't define an own .name property for unnamed functions.
             JSAtom* name = fun->getUnresolvedName(cx);
             if (name == nullptr)
@@ -933,17 +933,17 @@ const Class JSFunction::class_ = {
     &JSFunctionClassSpec
 };
 
 const Class* const js::FunctionClassPtr = &JSFunction::class_;
 
 JSString*
 js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
 {
-    if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
+    if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
         return nullptr;
 
     if (IsAsmJSModule(fun))
         return AsmJSModuleToString(cx, fun, !prettyPrint);
     if (IsAsmJSFunction(fun))
         return AsmJSFunctionToString(cx, fun);
 
     if (IsWrappedAsyncFunction(fun)) {
@@ -1264,45 +1264,43 @@ JSFunction::isDerivedClassConstructor()
         }
     } else {
         derived = nonLazyScript()->isDerivedClassConstructor();
     }
     MOZ_ASSERT_IF(derived, isClassConstructor());
     return derived;
 }
 
-bool
-JSFunction::getLength(JSContext* cx, uint16_t* length)
+/* static */ bool
+JSFunction::getLength(JSContext* cx, HandleFunction fun, uint16_t* length)
 {
-    JS::RootedFunction self(cx, this);
-    MOZ_ASSERT(!self->isBoundFunction());
-    if (self->isInterpretedLazy() && !self->getOrCreateScript(cx))
+    MOZ_ASSERT(!fun->isBoundFunction());
+    if (fun->isInterpretedLazy() && !getOrCreateScript(cx, fun))
         return false;
 
-    *length = self->hasScript() ? self->nonLazyScript()->funLength()
-                                : (self->nargs() - self->hasRest());
+    *length = fun->isNative() ? fun->nargs() : fun->nonLazyScript()->funLength();
     return true;
 }
 
-bool
-JSFunction::getUnresolvedLength(JSContext* cx, MutableHandleValue v)
+/* static */ bool
+JSFunction::getUnresolvedLength(JSContext* cx, HandleFunction fun, MutableHandleValue v)
 {
-    MOZ_ASSERT(!IsInternalFunctionObject(*this));
-    MOZ_ASSERT(!hasResolvedLength());
+    MOZ_ASSERT(!IsInternalFunctionObject(*fun));
+    MOZ_ASSERT(!fun->hasResolvedLength());
 
     // Bound functions' length can have values up to MAX_SAFE_INTEGER, so
     // they're handled differently from other functions.
-    if (isBoundFunction()) {
-        MOZ_ASSERT(getExtendedSlot(BOUND_FUN_LENGTH_SLOT).isNumber());
-        v.set(getExtendedSlot(BOUND_FUN_LENGTH_SLOT));
+    if (fun->isBoundFunction()) {
+        MOZ_ASSERT(fun->getExtendedSlot(BOUND_FUN_LENGTH_SLOT).isNumber());
+        v.set(fun->getExtendedSlot(BOUND_FUN_LENGTH_SLOT));
         return true;
     }
 
     uint16_t length;
-    if (!getLength(cx, &length))
+    if (!JSFunction::getLength(cx, fun, &length))
         return false;
 
     v.setInt32(length);
     return true;
 }
 
 JSAtom*
 JSFunction::getUnresolvedName(JSContext* cx)
@@ -1349,23 +1347,20 @@ JSFunction::getBoundFunctionThis() const
 static ArrayObject*
 GetBoundFunctionArguments(const JSFunction* boundFun)
 {
     js::Value argsVal = BoundFunctionEnvironmentSlotValue(boundFun, JSSLOT_BOUND_FUNCTION_ARGS);
     return &argsVal.toObject().as<ArrayObject>();
 }
 
 const js::Value&
-JSFunction::getBoundFunctionArgument(JSContext* cx, unsigned which) const
+JSFunction::getBoundFunctionArgument(unsigned which) const
 {
     MOZ_ASSERT(which < getBoundFunctionArgumentCount());
-
-    RootedArrayObject boundArgs(cx, GetBoundFunctionArguments(this));
-    RootedValue res(cx);
-    return boundArgs->getDenseElement(which);
+    return GetBoundFunctionArguments(this)->getDenseElement(which);
 }
 
 size_t
 JSFunction::getBoundFunctionArgumentCount() const
 {
     return GetBoundFunctionArguments(this)->length();
 }
 
@@ -1563,17 +1558,17 @@ fun_isGenerator(JSContext* cx, unsigned 
 const JSFunctionSpec js::function_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,   fun_toSource,   0,0),
 #endif
     JS_FN(js_toString_str,   fun_toString,   0,0),
     JS_FN(js_apply_str,      fun_apply,      2,0),
     JS_FN(js_call_str,       fun_call,       1,0),
     JS_FN("isGenerator",     fun_isGenerator,0,0),
-    JS_SELF_HOSTED_FN("bind", "FunctionBind", 2, JSFUN_HAS_REST),
+    JS_SELF_HOSTED_FN("bind", "FunctionBind", 2, 0),
     JS_SYM_FN(hasInstance, fun_symbolHasInstance, 1, JSPROP_READONLY | JSPROP_PERMANENT),
     JS_FS_END
 };
 
 // ES 2017 draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077 19.2.1.1.1.
 static bool
 FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generatorKind,
                     FunctionAsyncKind asyncKind)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -56,17 +56,16 @@ class JSFunction : public js::NativeObje
                                      * expression closure: function(x) x*x */
         HAS_GUESSED_ATOM = 0x0020,  /* function had no explicit name, but a
                                        name was guessed for it anyway */
         LAMBDA           = 0x0040,  /* function comes from a FunctionExpression, ArrowFunction, or
                                        Function() call (not a FunctionDeclaration or nonstandard
                                        function-statement) */
         SELF_HOSTED      = 0x0080,  /* function is self-hosted builtin and must not be
                                        decompilable nor constructible. */
-        HAS_REST         = 0x0100,  /* function has a rest (...) parameter */
         INTERPRETED_LAZY = 0x0200,  /* function is interpreted but doesn't have a script yet */
         RESOLVED_LENGTH  = 0x0400,  /* f.length has been resolved (see fun_resolve). */
         RESOLVED_NAME    = 0x0800,  /* f.name has been resolved (see fun_resolve). */
 
         FUNCTION_KIND_SHIFT = 13,
         FUNCTION_KIND_MASK  = 0x7 << FUNCTION_KIND_SHIFT,
 
         ASMJS_KIND = AsmJS << FUNCTION_KIND_SHIFT,
@@ -90,17 +89,17 @@ class JSFunction : public js::NativeObje
         INTERPRETED_LAMBDA = INTERPRETED | LAMBDA | CONSTRUCTOR,
         INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND,
         INTERPRETED_LAMBDA_GENERATOR = INTERPRETED | LAMBDA,
         INTERPRETED_NORMAL = INTERPRETED | CONSTRUCTOR,
         INTERPRETED_GENERATOR = INTERPRETED,
         NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME,
 
         STABLE_ACROSS_CLONES = CONSTRUCTOR | EXPR_BODY | HAS_GUESSED_ATOM | LAMBDA |
-                               SELF_HOSTED |  HAS_REST | FUNCTION_KIND_MASK
+                               SELF_HOSTED | FUNCTION_KIND_MASK
     };
 
     static_assert((INTERPRETED | INTERPRETED_LAZY) == js::JS_FUNCTION_INTERPRETED_BITS,
                   "jsfriendapi.h's JSFunction::INTERPRETED-alike is wrong");
     static_assert(((FunctionKindLimit - 1) << FUNCTION_KIND_SHIFT) <= FUNCTION_KIND_MASK,
                   "FunctionKind doesn't fit into flags_");
 
   private:
@@ -178,17 +177,16 @@ class JSFunction : public js::NativeObje
     /* Possible attributes of a native function: */
     bool isAsmJSNative()            const { return kind() == AsmJS; }
 
     /* Possible attributes of an interpreted function: */
     bool isExprBody()               const { return flags() & EXPR_BODY; }
     bool hasGuessedAtom()           const { return flags() & HAS_GUESSED_ATOM; }
     bool isLambda()                 const { return flags() & LAMBDA; }
     bool isBoundFunction()          const { return flags() & BOUND_FUN; }
-    bool hasRest()                  const { return flags() & HAS_REST; }
     bool isInterpretedLazy()        const { return flags() & INTERPRETED_LAZY; }
     bool hasScript()                const { return flags() & INTERPRETED; }
 
     bool infallibleIsDefaultClassConstructor(JSContext* cx) const;
 
     // Arrow functions store their lexical new.target in the first extended slot.
     bool isArrow()                  const { return kind() == Arrow; }
     // Every class-constructor is also a method.
@@ -259,21 +257,16 @@ class JSFunction : public js::NativeObje
         setKind(ClassConstructor);
     }
 
     // Can be called multiple times by the parser.
     void setArgCount(uint16_t nargs) {
         this->nargs_ = nargs;
     }
 
-    // Can be called multiple times by the parser.
-    void setHasRest() {
-        flags_ |= HAS_REST;
-    }
-
     void setIsBoundFunction() {
         MOZ_ASSERT(!isBoundFunction());
         flags_ |= BOUND_FUN;
     }
 
     void setIsSelfHostedBuiltin() {
         MOZ_ASSERT(isInterpreted());
         MOZ_ASSERT(!isSelfHostedBuiltin());
@@ -306,17 +299,18 @@ class JSFunction : public js::NativeObje
 
     void setAsyncKind(js::FunctionAsyncKind asyncKind) {
         if (isInterpretedLazy())
             lazyScript()->setAsyncKind(asyncKind);
         else
             nonLazyScript()->setAsyncKind(asyncKind);
     }
 
-    bool getUnresolvedLength(JSContext* cx, js::MutableHandleValue v);
+    static bool getUnresolvedLength(JSContext* cx, js::HandleFunction fun,
+                                    js::MutableHandleValue v);
 
     JSAtom* getUnresolvedName(JSContext* cx);
 
     JSAtom* name() const { return hasGuessedAtom() ? nullptr : atom_.get(); }
 
     // Because display names (see Debugger.Object.displayName) are already stored
     // on functions and will always contain a valid es6 function name, as described
     // in "ECMA-262 (2016-02-27) 9.2.11 SetFunctionName," we have opted to save
@@ -398,26 +392,25 @@ class JSFunction : public js::NativeObje
     //
     // - For inlined functions which may have a LazyScript but whose JSScript
     //   is known to exist, existingScript() will get the script and delazify
     //   the function if necessary. If the function should not be delazified,
     //   use existingScriptNonDelazifying().
     //
     // - For functions known to have a JSScript, nonLazyScript() will get it.
 
-    JSScript* getOrCreateScript(JSContext* cx) {
-        MOZ_ASSERT(isInterpreted());
+    static JSScript* getOrCreateScript(JSContext* cx, js::HandleFunction fun) {
+        MOZ_ASSERT(fun->isInterpreted());
         MOZ_ASSERT(cx);
-        if (isInterpretedLazy()) {
-            JS::RootedFunction self(cx, this);
-            if (!createScriptForLazilyInterpretedFunction(cx, self))
+        if (fun->isInterpretedLazy()) {
+            if (!createScriptForLazilyInterpretedFunction(cx, fun))
                 return nullptr;
-            return self->nonLazyScript();
+            return fun->nonLazyScript();
         }
-        return nonLazyScript();
+        return fun->nonLazyScript();
     }
 
     JSScript* existingScriptNonDelazifying() const {
         MOZ_ASSERT(isInterpreted());
         if (isInterpretedLazy()) {
             // Get the script from the canonical function. Ion used the
             // canonical function to inline the script and because it has
             // Baseline code it has not been relazified. Note that we can't
@@ -452,17 +445,17 @@ class JSFunction : public js::NativeObje
         return !u.i.s.script_;
     }
 
     JSScript* nonLazyScript() const {
         MOZ_ASSERT(!hasUncompiledScript());
         return u.i.s.script_;
     }
 
-    bool getLength(JSContext* cx, uint16_t* length);
+    static bool getLength(JSContext* cx, js::HandleFunction fun, uint16_t* length);
 
     js::LazyScript* lazyScript() const {
         MOZ_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
         return u.i.s.lazy_;
     }
 
     js::LazyScript* lazyScriptOrNull() const {
         MOZ_ASSERT(isInterpretedLazy());
@@ -565,17 +558,17 @@ class JSFunction : public js::NativeObje
     }
 
     inline void trace(JSTracer* trc);
 
     /* Bound function accessors. */
 
     JSObject* getBoundFunctionTarget() const;
     const js::Value& getBoundFunctionThis() const;
-    const js::Value& getBoundFunctionArgument(JSContext* cx, unsigned which) const;
+    const js::Value& getBoundFunctionArgument(unsigned which) const;
     size_t getBoundFunctionArgumentCount() const;
 
   private:
     js::GCPtrScript& mutableScript() {
         MOZ_ASSERT(hasScript());
         return *(js::GCPtrScript*)&u.i.s.script_;
     }
 
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -83,17 +83,17 @@ CloneFunctionObjectIfNotSingleton(JSCont
     gc::AllocKind extendedFinalizeKind = gc::AllocKind::FUNCTION_EXTENDED;
     gc::AllocKind kind = fun->isExtended()
                          ? extendedFinalizeKind
                          : finalizeKind;
 
     if (CanReuseScriptForClone(cx->compartment(), fun, parent))
         return CloneFunctionReuseScript(cx, fun, parent, kind, newKind, proto);
 
-    RootedScript script(cx, fun->getOrCreateScript(cx));
+    RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
     if (!script)
         return nullptr;
     RootedScope enclosingScope(cx, script->enclosingScope());
     return CloneFunctionAndScript(cx, fun, parent, enclosingScope, kind, proto);
 }
 
 } /* namespace js */
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -946,17 +946,17 @@ js::CreateThisForFunctionWithProto(JSCon
         }
 
         res = CreateThisForFunctionWithGroup(cx, group, newKind);
     } else {
         res = NewBuiltinClassInstance<PlainObject>(cx, newKind);
     }
 
     if (res) {
-        JSScript* script = callee->as<JSFunction>().getOrCreateScript(cx);
+        JSScript* script = JSFunction::getOrCreateScript(cx, callee.as<JSFunction>());
         if (!script)
             return nullptr;
         TypeScript::SetThis(cx, script, TypeSet::ObjectType(res));
     }
 
     return res;
 }
 
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2134,16 +2134,17 @@ GenerateLcovInfo(JSContext* cx, JSCompar
 
         // We found the top-level script, visit all the functions reachable
         // from the top-level function, and delazify them.
         Rooted<ScriptVector> queue(cx, ScriptVector(cx));
         if (!queue.append(topLevel))
             return false;
 
         RootedScript script(cx);
+        RootedFunction fun(cx);
         do {
             script = queue.popCopy();
             compCover.collectCodeCoverageInfo(comp, script->sourceObject(), script);
 
             // Iterate from the last to the first object in order to have
             // the functions them visited in the opposite order when popping
             // elements from the stack of remaining scripts, such that the
             // functions are more-less listed with increasing line numbers.
@@ -2151,25 +2152,25 @@ GenerateLcovInfo(JSContext* cx, JSCompar
                 continue;
             size_t idx = script->objects()->length;
             while (idx--) {
                 JSObject* obj = script->getObject(idx);
 
                 // Only continue on JSFunction objects.
                 if (!obj->is<JSFunction>())
                     continue;
-                JSFunction& fun = obj->as<JSFunction>();
+                fun = &obj->as<JSFunction>();
 
                 // Let's skip wasm for now.
-                if (!fun.isInterpreted())
+                if (!fun->isInterpreted())
                     continue;
 
                 // Queue the script in the list of script associated to the
                 // current source.
-                JSScript* childScript = fun.getOrCreateScript(cx);
+                JSScript* childScript = JSFunction::getOrCreateScript(cx, fun);
                 if (!childScript || !queue.append(childScript))
                     return false;
             }
         } while (!queue.empty());
     }
 
     bool isEmpty = true;
     compCover.exportInto(out, &isEmpty);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -312,16 +312,17 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         NeedsArgsObj,
         HasMappedArgsObj,
         FunctionHasThisBinding,
         FunctionHasExtraBodyVarScope,
         IsGeneratorExp,
         IsLegacyGenerator,
         IsStarGenerator,
         IsAsync,
+        HasRest,
         OwnSource,
         ExplicitUseStrict,
         SelfHosted,
         HasSingleton,
         TreatAsRunOnce,
         HasLazyScript,
         HasNonSyntacticScope,
         HasInnerFunctions,
@@ -427,16 +428,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         if (script->isGeneratorExp())
             scriptBits |= (1 << IsGeneratorExp);
         if (script->isLegacyGenerator())
             scriptBits |= (1 << IsLegacyGenerator);
         if (script->isStarGenerator())
             scriptBits |= (1 << IsStarGenerator);
         if (script->asyncKind() == AsyncFunction)
             scriptBits |= (1 << IsAsync);
+        if (script->hasRest())
+            scriptBits |= (1 << HasRest);
         if (script->hasSingletons())
             scriptBits |= (1 << HasSingleton);
         if (script->treatAsRunOnce())
             scriptBits |= (1 << TreatAsRunOnce);
         if (script->isRelazifiable())
             scriptBits |= (1 << HasLazyScript);
         if (script->hasNonSyntacticScope())
             scriptBits |= (1 << HasNonSyntacticScope);
@@ -578,16 +581,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         if (scriptBits & (1 << IsLegacyGenerator)) {
             MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
             script->setGeneratorKind(LegacyGenerator);
         } else if (scriptBits & (1 << IsStarGenerator))
             script->setGeneratorKind(StarGenerator);
 
         if (scriptBits & (1 << IsAsync))
             script->setAsyncKind(AsyncFunction);
+        if (scriptBits & (1 << HasRest))
+            script->setHasRest();
     }
 
     JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
     JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
 
     if (scriptBits & (1 << OwnSource)) {
         if (!script->scriptSource()->performXDR<mode>(xdr))
             return false;
@@ -2618,16 +2623,18 @@ JSScript::initFromFunctionBox(ExclusiveC
     script->functionHasThisBinding_ = funbox->hasThisBinding();
     script->functionHasExtraBodyVarScope_ = funbox->hasExtraBodyVarScope();
 
     script->funLength_ = funbox->length;
 
     script->isGeneratorExp_ = funbox->isGenexpLambda;
     script->setGeneratorKind(funbox->generatorKind());
     script->setAsyncKind(funbox->asyncKind());
+    if (funbox->hasRest())
+        script->setHasRest();
 
     PositionalFormalParameterIter fi(script);
     while (fi && !fi.closedOver())
         fi++;
     script->funHasAnyAliasedFormal_ = !!fi;
 
     script->setHasInnerFunctions(funbox->hasInnerFunctions());
 }
@@ -3220,17 +3227,17 @@ js::detail::CopyScript(JSContext* cx, Ha
                         MOZ_ASSERT(innerFun->isAsmJSNative());
                         JS_ReportErrorASCII(cx, "AsmJS modules do not yet support cloning.");
                         return false;
                     }
                     clone = innerFun;
                 } else {
                     if (innerFun->isInterpretedLazy()) {
                         AutoCompartment ac(cx, innerFun);
-                        if (!innerFun->getOrCreateScript(cx))
+                        if (!JSFunction::getOrCreateScript(cx, innerFun))
                             return false;
                     }
 
                     Scope* enclosing = innerFun->nonLazyScript()->enclosingScope();
                     RootedScope enclosingClone(cx, scopes[FindScopeIndex(src, *enclosing)]);
                     clone = CloneInnerInterpretedFunction(cx, enclosingClone, innerFun);
                 }
             } else {
@@ -3278,16 +3285,17 @@ js::detail::CopyScript(JSContext* cx, Ha
     dst->treatAsRunOnce_ = src->treatAsRunOnce();
     dst->hasInnerFunctions_ = src->hasInnerFunctions();
     dst->isGeneratorExp_ = src->isGeneratorExp();
     dst->setGeneratorKind(src->generatorKind());
     dst->isDerivedClassConstructor_ = src->isDerivedClassConstructor();
     dst->needsHomeObject_ = src->needsHomeObject();
     dst->isDefaultClassConstructor_ = src->isDefaultClassConstructor();
     dst->isAsync_ = src->asyncKind() == AsyncFunction;
+    dst->hasRest_ = src->hasRest_;
 
     if (nconsts != 0) {
         GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
         dst->consts()->vector = vector;
         for (unsigned i = 0; i < nconsts; ++i)
             MOZ_ASSERT_IF(vector[i].isMarkable(), vector[i].toString()->isAtom());
     }
     if (nobjects != 0) {
@@ -4011,16 +4019,17 @@ LazyScript::Create(ExclusiveContext* cx,
         PackedView p;
         uint64_t packedFields;
     };
 
     p.version = version;
     p.shouldDeclareArguments = false;
     p.hasThisBinding = false;
     p.isAsync = false;
+    p.hasRest = false;
     p.numClosedOverBindings = closedOverBindings.length();
     p.numInnerFunctions = innerFunctions.length();
     p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
     p.strict = false;
     p.bindingsAccessedDynamically = false;
     p.hasDebuggerStatement = false;
     p.hasDirectEval = false;
     p.isLikelyConstructorWrapper = false;
@@ -4152,17 +4161,17 @@ JSScript::hasLoops()
             return true;
     }
     return false;
 }
 
 bool
 JSScript::mayReadFrameArgsDirectly()
 {
-    return argumentsHasVarBinding() || (function() && function()->hasRest());
+    return argumentsHasVarBinding() || hasRest();
 }
 
 static inline void
 LazyScriptHash(uint32_t lineno, uint32_t column, uint32_t begin, uint32_t end,
                HashNumber hashes[3])
 {
     HashNumber hash = lineno;
     hash = RotateLeft(hash, 4) ^ column;
@@ -4237,17 +4246,17 @@ JSScript::AutoDelazify::holdScript(JS::H
         if (fun->compartment()->isSelfHosting) {
             // The self-hosting compartment is shared across runtimes, so we
             // can't use JSAutoCompartment: it could cause races. Functions in
             // the self-hosting compartment will never be lazy, so we can safely
             // assume we don't have to delazify.
             script_ = fun->nonLazyScript();
         } else {
             JSAutoCompartment ac(cx_, fun);
-            script_ = fun->getOrCreateScript(cx_);
+            script_ = JSFunction::getOrCreateScript(cx_, fun);
             if (script_) {
                 oldDoNotRelazify_ = script_->doNotRelazify_;
                 script_->setDoNotRelazify(true);
             }
         }
     }
 }
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1007,16 +1007,18 @@ class JSScript : public js::gc::TenuredC
 
     bool needsHomeObject_:1;
 
     bool isDerivedClassConstructor_:1;
     bool isDefaultClassConstructor_:1;
 
     bool isAsync_:1;
 
+    bool hasRest_:1;
+
     // Add padding so JSScript is gc::Cell aligned. Make padding protected
     // instead of private to suppress -Wunused-private-field compiler warnings.
   protected:
 #if JS_BITS_PER_WORD == 32
     // Currently no padding is needed.
 #endif
 
     //
@@ -1303,16 +1305,23 @@ class JSScript : public js::gc::TenuredC
     js::FunctionAsyncKind asyncKind() const {
         return isAsync_ ? js::AsyncFunction : js::SyncFunction;
     }
 
     void setAsyncKind(js::FunctionAsyncKind kind) {
         isAsync_ = kind == js::AsyncFunction;
     }
 
+    bool hasRest() const {
+        return hasRest_;
+    }
+    void setHasRest() {
+        hasRest_ = true;
+    }
+
     void setNeedsHomeObject() {
         needsHomeObject_ = true;
     }
     bool needsHomeObject() const {
         return needsHomeObject_;
     }
 
     bool isDerivedClassConstructor() const {
@@ -1935,16 +1944,17 @@ class LazyScript : public gc::TenuredCel
         uint32_t bindingsAccessedDynamically : 1;
         uint32_t hasDebuggerStatement : 1;
         uint32_t hasDirectEval : 1;
         uint32_t isLikelyConstructorWrapper : 1;
         uint32_t hasBeenCloned : 1;
         uint32_t treatAsRunOnce : 1;
         uint32_t isDerivedClassConstructor : 1;
         uint32_t needsHomeObject : 1;
+        uint32_t hasRest : 1;
     };
 
     union {
         PackedView p_;
         uint64_t packedFields_;
     };
 
     // Source location for the script.
@@ -2063,16 +2073,23 @@ class LazyScript : public gc::TenuredCel
     FunctionAsyncKind asyncKind() const {
         return p_.isAsync ? AsyncFunction : SyncFunction;
     }
 
     void setAsyncKind(FunctionAsyncKind kind) {
         p_.isAsync = kind == AsyncFunction;
     }
 
+    bool hasRest() const {
+        return p_.hasRest;
+    }
+    void setHasRest() {
+        p_.hasRest = true;
+    }
+
     bool strict() const {
         return p_.strict;
     }
     void setStrict() {
         p_.strict = true;
     }
 
     bool bindingsAccessedDynamically() const {
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -73,17 +73,18 @@ ScriptAndCounts::ScriptAndCounts(ScriptA
 void
 SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame,
                         HandleScript script, JSObject* argsobj);
 
 inline JSFunction*
 LazyScript::functionDelazifying(JSContext* cx) const
 {
     Rooted<const LazyScript*> self(cx, this);
-    if (self->function_ && !self->function_->getOrCreateScript(cx))
+    RootedFunction fun(cx, self->function_);
+    if (self->function_ && !JSFunction::getOrCreateScript(cx, fun))
         return nullptr;
     return self->function_;
 }
 
 } // namespace js
 
 inline JSFunction*
 JSScript::functionDelazifying() const
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2951,17 +2951,17 @@ js::str_fromCodePoint(JSContext* cx, uns
     args.rval().setString(str);
     return true;
 }
 
 static const JSFunctionSpec string_static_methods[] = {
     JS_INLINABLE_FN("fromCharCode", js::str_fromCharCode, 1, 0, StringFromCharCode),
     JS_INLINABLE_FN("fromCodePoint", js::str_fromCodePoint, 1, 0, StringFromCodePoint),
 
-    JS_SELF_HOSTED_FN("raw",             "String_static_raw",           2,JSFUN_HAS_REST),
+    JS_SELF_HOSTED_FN("raw",             "String_static_raw",           2,0),
     JS_SELF_HOSTED_FN("substring",       "String_static_substring",     3,0),
     JS_SELF_HOSTED_FN("substr",          "String_static_substr",        3,0),
     JS_SELF_HOSTED_FN("slice",           "String_static_slice",         3,0),
 
     JS_SELF_HOSTED_FN("match",           "String_generic_match",        2,0),
     JS_SELF_HOSTED_FN("replace",         "String_generic_replace",      3,0),
     JS_SELF_HOSTED_FN("search",          "String_generic_search",       2,0),
     JS_SELF_HOSTED_FN("split",           "String_generic_split",        3,0),
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2308,17 +2308,17 @@ ValueToScript(JSContext* cx, HandleValue
     if (IsWrappedAsyncFunction(fun))
         fun = GetUnwrappedAsyncFunction(fun);
 
     if (!fun->isInterpreted()) {
         JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_SCRIPTS_ONLY);
         return nullptr;
     }
 
-    JSScript* script = fun->getOrCreateScript(cx);
+    JSScript* script = JSFunction::getOrCreateScript(cx, fun);
     if (!script)
         return nullptr;
 
     if (funp)
         *funp = fun;
 
     return script;
 }
@@ -2708,17 +2708,17 @@ DisassembleScript(JSContext* cx, HandleS
         for (unsigned i = 0; i != objects->length; ++i) {
             JSObject* obj = objects->vector[i];
             if (obj->is<JSFunction>()) {
                 if (sp->put("\n") < 0)
                     return false;
 
                 RootedFunction fun(cx, &obj->as<JSFunction>());
                 if (fun->isInterpreted()) {
-                    RootedScript script(cx, fun->getOrCreateScript(cx));
+                    RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
                     if (script) {
                         if (!DisassembleScript(cx, script, fun, lines, recursive, sourceNotes, sp))
                             return false;
                     }
                 } else {
                     if (sp->put("[native code]\n") < 0)
                         return false;
                 }
@@ -5362,17 +5362,17 @@ DumpScopeChain(JSContext* cx, unsigned a
     RootedScript script(cx);
 
     if (obj->is<JSFunction>()) {
         RootedFunction fun(cx, &obj->as<JSFunction>());
         if (!fun->isInterpreted()) {
             ReportUsageErrorASCII(cx, callee, "Argument must be an interpreted function");
             return false;
         }
-        script = fun->getOrCreateScript(cx);
+        script = JSFunction::getOrCreateScript(cx, fun);
     } else {
         script = obj->as<ModuleObject>().script();
     }
 
     script->bodyScope()->dump();
 
     args.rval().setUndefined();
     return true;
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -468,17 +468,17 @@ MappedArgSetter(JSContext* cx, HandleObj
     if (!GetOwnPropertyDescriptor(cx, argsobj, id, &desc))
         return false;
     MOZ_ASSERT(desc.object());
     unsigned attrs = desc.attributes();
     MOZ_ASSERT(!(attrs & JSPROP_READONLY));
     attrs &= (JSPROP_ENUMERATE | JSPROP_PERMANENT); /* only valid attributes */
 
     RootedFunction callee(cx, &argsobj->callee());
-    RootedScript script(cx, callee->getOrCreateScript(cx));
+    RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
     if (!script)
         return false;
 
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
             argsobj->setElement(cx, arg, vp);
             if (arg < script->functionNonDelazifying()->nargs())
@@ -623,17 +623,17 @@ MappedArgumentsObject::obj_definePropert
     if (isMapped) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (desc.isAccessorDescriptor()) {
             if (!argsobj->markElementDeleted(cx, arg))
                 return false;
         } else {
             if (desc.hasValue()) {
                 RootedFunction callee(cx, &argsobj->callee());
-                RootedScript script(cx, callee->getOrCreateScript(cx));
+                RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
                 if (!script)
                     return false;
                 argsobj->setElement(cx, arg, desc.value());
                 if (arg < script->functionNonDelazifying()->nargs())
                     TypeScript::SetArgument(cx, script, arg, desc.value());
             }
             if (desc.hasWritable() && !desc.writable()) {
                 if (!argsobj->markElementDeleted(cx, arg))
--- a/js/src/vm/AsyncFunction.cpp
+++ b/js/src/vm/AsyncFunction.cpp
@@ -116,17 +116,17 @@ js::WrapAsyncFunctionWithProto(JSContext
     MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default"
                       "%FunctionPrototype% fallback in NewFunctionWithProto().");
 
     // Create a new function with AsyncFunctionPrototype, reusing the name and
     // the length of `unwrapped`.
 
     RootedAtom funName(cx, unwrapped->name());
     uint16_t length;
-    if (!unwrapped->getLength(cx, &length))
+    if (!JSFunction::getLength(cx, unwrapped, &length))
         return nullptr;
 
     // Steps 3 (partially).
     RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncFunction, length,
                                                     JSFunction::NATIVE_FUN, nullptr,
                                                     funName, proto,
                                                     AllocKind::FUNCTION_EXTENDED,
                                                     TenuredObject));
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -220,17 +220,17 @@ static const Class DebuggerSource_class 
 
 /*** Utils ***************************************************************************************/
 
 static inline bool
 EnsureFunctionHasScript(JSContext* cx, HandleFunction fun)
 {
     if (fun->isInterpretedLazy()) {
         AutoCompartment ac(cx, fun);
-        return !!fun->getOrCreateScript(cx);
+        return !!JSFunction::getOrCreateScript(cx, fun);
     }
     return true;
 }
 
 static inline JSScript*
 GetOrCreateFunctionScript(JSContext* cx, HandleFunction fun)
 {
     MOZ_ASSERT(fun->isInterpreted());
@@ -9690,17 +9690,17 @@ DebuggerObject::getBoundArguments(JSCont
 
     RootedFunction referent(cx, &object->referent()->as<JSFunction>());
     Debugger* dbg = object->owner();
 
     size_t length = referent->getBoundFunctionArgumentCount();
     if (!result.resize(length))
         return false;
     for (size_t i = 0; i < length; i++) {
-        result[i].set(referent->getBoundFunctionArgument(cx, i));
+        result[i].set(referent->getBoundFunctionArgument(i));
         if (!dbg->wrapDebuggeeValue(cx, result[i]))
             return false;
     }
     return true;
 }
 
 /* static */ SavedFrame*
 Debugger::getObjectAllocationSite(JSObject& obj)
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -1415,17 +1415,18 @@ class DebugEnvironmentProxyHandler : pub
         if (env->is<ModuleEnvironmentObject>()) {
             /* Everything is aliased and stored in the environment object. */
             return true;
         }
 
         /* Handle unaliased formals, vars, lets, and consts at function scope. */
         if (env->is<CallObject>()) {
             CallObject& callobj = env->as<CallObject>();
-            RootedScript script(cx, callobj.callee().getOrCreateScript(cx));
+            RootedFunction fun(cx, &callobj.callee());
+            RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
             if (!script->ensureHasTypes(cx) || !script->ensureHasAnalyzedArgsUsage(cx))
                 return false;
 
             BindingIter bi(script);
             while (bi && NameToId(bi.name()->asPropertyName()) != id)
                 bi++;
             if (!bi)
                 return true;
@@ -2950,17 +2951,17 @@ GetDebugEnvironment(JSContext* cx, const
 
 JSObject*
 js::GetDebugEnvironmentForFunction(JSContext* cx, HandleFunction fun)
 {
     assertSameCompartment(cx, fun);
     MOZ_ASSERT(CanUseDebugEnvironmentMaps(cx));
     if (!DebugEnvironments::updateLiveEnvironments(cx))
         return nullptr;
-    JSScript* script = fun->getOrCreateScript(cx);
+    JSScript* script = JSFunction::getOrCreateScript(cx, fun);
     if (!script)
         return nullptr;
     EnvironmentIter ei(cx, fun->environment(), script->enclosingScope());
     return GetDebugEnvironment(cx, ei);
 }
 
 JSObject*
 js::GetDebugEnvironmentForFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc)
@@ -3458,21 +3459,23 @@ RemoveReferencedNames(JSContext* cx, Han
         }
 
         if (name)
             remainingNames.remove(name);
     }
 
     if (script->hasObjects()) {
         ObjectArray* objects = script->objects();
+        RootedFunction fun(cx);
+        RootedScript innerScript(cx);
         for (size_t i = 0; i < objects->length; i++) {
             JSObject* obj = objects->vector[i];
             if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
-                JSFunction* fun = &obj->as<JSFunction>();
-                RootedScript innerScript(cx, fun->getOrCreateScript(cx));
+                fun = &obj->as<JSFunction>();
+                innerScript = JSFunction::getOrCreateScript(cx, fun);
                 if (!innerScript)
                     return false;
 
                 if (!RemoveReferencedNames(cx, innerScript, remainingNames))
                     return false;
             }
         }
     }
@@ -3525,21 +3528,23 @@ AnalyzeEntrainedVariablesInScript(JSCont
             buf.putString(r.front());
         }
 
         printf("%s\n", buf.string());
     }
 
     if (innerScript->hasObjects()) {
         ObjectArray* objects = innerScript->objects();
+        RootedFunction fun(cx);
+        RootedScript innerInnerScript(cx);
         for (size_t i = 0; i < objects->length; i++) {
             JSObject* obj = objects->vector[i];
             if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
-                JSFunction* fun = &obj->as<JSFunction>();
-                RootedScript innerInnerScript(cx, fun->getOrCreateScript(cx));
+                fun = &obj->as<JSFunction>();
+                innerInnerScript = JSFunction::getOrCreateScript(cx, fun);
                 if (!innerInnerScript ||
                     !AnalyzeEntrainedVariablesInScript(cx, script, innerInnerScript))
                 {
                     return false;
                 }
             }
         }
     }
@@ -3560,21 +3565,23 @@ AnalyzeEntrainedVariablesInScript(JSCont
 // |bar| unnecessarily entrains |b|, and |baz| unnecessarily entrains |a|.
 bool
 js::AnalyzeEntrainedVariables(JSContext* cx, HandleScript script)
 {
     if (!script->hasObjects())
         return true;
 
     ObjectArray* objects = script->objects();
+    RootedFunction fun(cx);
+    RootedScript innerScript(cx);
     for (size_t i = 0; i < objects->length; i++) {
         JSObject* obj = objects->vector[i];
         if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
-            JSFunction* fun = &obj->as<JSFunction>();
-            RootedScript innerScript(cx, fun->getOrCreateScript(cx));
+            fun = &obj->as<JSFunction>();
+            innerScript = JSFunction::getOrCreateScript(cx, fun);
             if (!innerScript)
                 return false;
 
             if (script->functionDelazifying() && script->functionDelazifying()->needsCallObject()) {
                 if (!AnalyzeEntrainedVariablesInScript(cx, script, innerScript))
                     return false;
             }
 
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -830,17 +830,17 @@ class FastCallGuard
     }
 
     bool call(JSContext* cx, HandleValue callee, HandleValue thisv, MutableHandleValue rval) {
         args_.CallArgs::setCallee(callee);
         args_.CallArgs::setThis(thisv);
 
         if (useIon_ && fun_) {
             if (!script_) {
-                script_ = fun_->getOrCreateScript(cx);
+                script_ = JSFunction::getOrCreateScript(cx, fun_);
                 if (!script_)
                     return false;
             }
             MOZ_ASSERT(fun_->nonLazyScript() == script_);
 
             jit::MethodStatus status = jit::CanEnterUsingFastInvoke(cx, script_, args_.length());
             if (status == jit::Method_Error)
                 return false;
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -277,18 +277,16 @@ MakeDefaultConstructor(JSContext* cx, JS
                                                           /* nargs = */ !!derived,
                                                           proto, TenuredObject, &ctor))
     {
         return nullptr;
     }
 
     ctor->setIsConstructor();
     ctor->setIsClassConstructor();
-    if (derived)
-        ctor->setHasRest();
 
     MOZ_ASSERT(ctor->infallibleIsDefaultClassConstructor(cx));
 
     return ctor;
 }
 
 bool
 js::ReportIsNotFunction(JSContext* cx, HandleValue v, int numToSkip, MaybeConstruct construct)
@@ -443,28 +441,28 @@ js::InternalCallOrConstruct(JSContext* c
         MOZ_ASSERT_IF(construct, !args.callee().constructHook());
         JSNative call = args.callee().callHook();
         if (!call)
             return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct);
         return CallJSNative(cx, call, args);
     }
 
     /* Invoke native functions. */
-    JSFunction* fun = &args.callee().as<JSFunction>();
+    RootedFunction fun(cx, &args.callee().as<JSFunction>());
     if (construct != CONSTRUCT && fun->isClassConstructor()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CALL_CLASS_CONSTRUCTOR);
         return false;
     }
 
     if (fun->isNative()) {
         MOZ_ASSERT_IF(construct, !fun->isConstructor());
         return CallJSNative(cx, fun->native(), args);
     }
 
-    if (!fun->getOrCreateScript(cx))
+    if (!JSFunction::getOrCreateScript(cx, fun))
         return false;
 
     /* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */
     InvokeState state(cx, args, construct);
 
     // Check to see if createSingleton flag should be set for this frame.
     if (construct) {
         jsbytecode* pc;
@@ -2926,17 +2924,17 @@ CASE(JSOP_FUNCALL)
         TypeScript::Monitor(cx, script, REGS.pc, newsp[-1]);
         REGS.sp = newsp;
         ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
     }
 
     {
         MOZ_ASSERT(maybeFun);
         ReservedRooted<JSFunction*> fun(&rootFunction0, maybeFun);
-        ReservedRooted<JSScript*> funScript(&rootScript0, fun->getOrCreateScript(cx));
+        ReservedRooted<JSScript*> funScript(&rootScript0, JSFunction::getOrCreateScript(cx, fun));
         if (!funScript)
             goto error;
 
         bool createSingleton = ObjectGroup::useSingletonForNewObject(cx, script, REGS.pc);
 
         TypeMonitorCall(cx, args, construct);
 
         mozilla::Maybe<InvokeState> state;
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -305,17 +305,17 @@ JSObject::splicePrototype(JSContext* cx,
 JSObject::makeLazyGroup(JSContext* cx, HandleObject obj)
 {
     MOZ_ASSERT(obj->hasLazyGroup());
     MOZ_ASSERT(cx->compartment() == obj->compartment());
 
     /* De-lazification of functions can GC, so we need to do it up here. */
     if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpretedLazy()) {
         RootedFunction fun(cx, &obj->as<JSFunction>());
-        if (!fun->getOrCreateScript(cx))
+        if (!JSFunction::getOrCreateScript(cx, fun))
             return nullptr;
     }
 
     // Find flags which need to be specified immediately on the object.
     // Don't track whether singletons are packed.
     ObjectGroupFlags initialFlags = OBJECT_FLAG_SINGLETON | OBJECT_FLAG_NON_PACKED;
 
     if (obj->isIteratedSingleton())
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -456,17 +456,17 @@ intrinsic_FinishBoundFunctionInit(JSCont
     }
 
     double argCount = args[2].toNumber();
     double length = 0.0;
 
     // Try to avoid invoking the resolve hook.
     if (targetObj->is<JSFunction>() && !targetObj->as<JSFunction>().hasResolvedLength()) {
         RootedValue targetLength(cx);
-        if (!targetObj->as<JSFunction>().getUnresolvedLength(cx, &targetLength))
+        if (!JSFunction::getUnresolvedLength(cx, targetObj.as<JSFunction>(), &targetLength))
             return false;
 
         length = Max(0.0, targetLength.toNumber() - argCount);
     } else {
         // 19.2.3.2 Function.prototype.bind, step 5.
         bool hasLength;
         RootedId idRoot(cx, NameToId(cx->names().length));
         if (!HasOwnProperty(cx, targetObj, idRoot, &hasLength))
@@ -3001,33 +3001,33 @@ JSRuntime::cloneSelfHostedFunctionScript
         return false;
     // JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
     // aren't any.
     MOZ_ASSERT(!sourceFun->isGenerator());
     MOZ_ASSERT(targetFun->isExtended());
     MOZ_ASSERT(targetFun->isInterpretedLazy());
     MOZ_ASSERT(targetFun->isSelfHostedBuiltin());
 
-    RootedScript sourceScript(cx, sourceFun->getOrCreateScript(cx));
+    RootedScript sourceScript(cx, JSFunction::getOrCreateScript(cx, sourceFun));
     if (!sourceScript)
         return false;
 
     // Assert that there are no intervening scopes between the global scope
     // and the self-hosted script. Toplevel lexicals are explicitly forbidden
     // by the parser when parsing self-hosted code. The fact they have the
     // global lexical scope on the scope chain is for uniformity and engine
     // invariants.
     MOZ_ASSERT(sourceScript->outermostScope()->enclosing()->kind() == ScopeKind::Global);
     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
     if (!CloneScriptIntoFunction(cx, emptyGlobalScope, targetFun, sourceScript))
         return false;
     MOZ_ASSERT(!targetFun->isInterpretedLazy());
 
     MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
-    MOZ_ASSERT(sourceFun->hasRest() == targetFun->hasRest());
+    MOZ_ASSERT(sourceScript->hasRest() == targetFun->nonLazyScript()->hasRest());
 
     // The target function might have been relazified after its flags changed.
     targetFun->setFlags(targetFun->flags() | sourceFun->flags());
     return true;
 }
 
 bool
 JSRuntime::getUnclonedSelfHostedValue(JSContext* cx, HandlePropertyName name,
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -331,17 +331,17 @@ InterpreterStack::pushInlineFrame(JSCont
 }
 
 MOZ_ALWAYS_INLINE bool
 InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                            HandleFunction callee, HandleValue newTarget,
                                            HandleObject envChain)
 {
     MOZ_ASSERT(callee->isGenerator());
-    RootedScript script(cx, callee->getOrCreateScript(cx));
+    RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
     InterpreterFrame* prev = regs.fp();
     jsbytecode* prevpc = regs.pc;
     Value* prevsp = regs.sp;
     MOZ_ASSERT(prev);
 
     script->ensureNonLazyCanonicalFunction(cx);
 
     LifoAlloc::Mark mark = allocator_.mark();
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -80,17 +80,17 @@ bool
 InterpreterFrame::isNonGlobalEvalFrame() const
 {
     return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
 }
 
 JSObject*
 InterpreterFrame::createRestParameter(JSContext* cx)
 {
-    MOZ_ASSERT(callee().hasRest());
+    MOZ_ASSERT(script()->hasRest());
     unsigned nformal = callee().nargs() - 1, nactual = numActualArgs();
     unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
     Value* restvp = argv() + nformal;
     return ObjectGroup::newArrayObject(cx, restvp, nrest, GenericObject,
                                        ObjectGroup::NewArrayKind::UnknownIndex);
 }
 
 static inline void
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -3816,17 +3816,18 @@ TypeNewScript::maybeAnalyze(JSContext* c
     RootedObjectGroup groupRoot(cx, group);
     templateObject_ = NewObjectWithGroup<PlainObject>(cx, groupRoot, kind, TenuredObject);
     if (!templateObject_)
         return false;
 
     Vector<Initializer> initializerVector(cx);
 
     RootedPlainObject templateRoot(cx, templateObject());
-    if (!jit::AnalyzeNewScriptDefiniteProperties(cx, function(), group, templateRoot, &initializerVector))
+    RootedFunction fun(cx, function());
+    if (!jit::AnalyzeNewScriptDefiniteProperties(cx, fun, group, templateRoot, &initializerVector))
         return false;
 
     if (!group->newScript())
         return true;
 
     MOZ_ASSERT(OnlyHasDataProperties(templateObject()->lastProperty()));
 
     if (templateObject()->slotSpan() != 0) {
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -3246,17 +3246,17 @@ CheckModuleLevelName(ModuleValidator& m,
 
     return true;
 }
 
 static bool
 CheckFunctionHead(ModuleValidator& m, ParseNode* fn)
 {
     JSFunction* fun = FunctionObject(fn);
-    if (fun->hasRest())
+    if (fn->pn_funbox->hasRest())
         return m.fail(fn, "rest args not allowed");
     if (fun->isExprBody())
         return m.fail(fn, "expression closures not allowed");
     if (fn->pn_funbox->hasDestructuringArgs)
         return m.fail(fn, "destructuring args not allowed");
     return true;
 }
 
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -48,28 +48,16 @@
  *
  *
  * High-value code generation improvements:
  *
  * - (Bug 1316803) Opportunities for cheaply folding in a constant rhs to
  *   arithmetic operations, we do this already for I32 add and shift operators,
  *   this reduces register pressure and instruction count.
  *
- * - (Bug 1286816) Opportunities for cheaply folding in a constant rhs to
- *   conditionals.
- *
- * - (Bug 1286816) Boolean evaluation for control can be optimized by pushing a
- *   bool-generating operation onto the value stack in the same way that we now
- *   push latent constants and local lookups, or (easier) by remembering the
- *   operation in a side location if the next Op will consume it.
- *
- * - (Bug 1286816) brIf pessimizes by branching over code that performs stack
- *   cleanup and a branch.  If no cleanup is needed we can just branch
- *   conditionally to the target.
- *
  * - (Bug 1316804) brTable pessimizes by always dispatching to code that pops
  *   the stack and then jumps to the code for the target case.  If no cleanup is
  *   needed we could just branch conditionally to the target; if the same amount
  *   of cleanup is needed for all cases then the cleanup can be done before the
  *   dispatch.  Both are highly likely.
  *
  * - (Bug 1316806) Register management around calls: At the moment we sync the
  *   value stack unconditionally (this is simple) but there are probably many
@@ -152,16 +140,17 @@ struct BaseCompilePolicy : OpIterPolicy
 typedef OpIter<BaseCompilePolicy> BaseOpIter;
 
 typedef bool IsUnsigned;
 typedef bool IsSigned;
 typedef bool ZeroOnOverflow;
 typedef bool IsKnownNotZero;
 typedef bool HandleNaNSpecially;
 typedef bool PopStack;
+typedef bool InvertBranch;
 typedef unsigned ByteSize;
 typedef unsigned BitSize;
 
 // UseABI::Wasm implies that the Tls/Heap/Global registers are nonvolatile,
 // except when InterModule::True is also set, when they are volatile.
 //
 // UseABI::System implies that the Tls/Heap/Global registers are volatile.
 // Additionally, the parameter passing mechanism may be slightly different from
@@ -485,16 +474,22 @@ class BaseCompiler
         // Scratch registers are available to use in OOL code.
         //
         // All other registers must be explicitly saved and restored
         // by the OOL code before being used.
 
         virtual void generate(MacroAssembler& masm) = 0;
     };
 
+    enum class LatentOp {
+        None,
+        Compare,
+        Eqz
+    };
+
     const ModuleEnvironment&    env_;
     BaseOpIter                  iter_;
     const FuncBytes&            func_;
     size_t                      lastReadCallSite_;
     TempAllocator&              alloc_;
     const ValTypeVector&        locals_;         // Types of parameters and locals
     int32_t                     localSize_;      // Size of local area in bytes (stable after beginFunction)
     int32_t                     varLow_;         // Low byte offset of local area for true locals (not parameters)
@@ -507,16 +502,21 @@ class BaseCompiler
     ValTypeVector               SigF_;
     ValTypeVector               SigI_;
     ValTypeVector               Sig_;
     Label                       returnLabel_;
     Label                       outOfLinePrologue_;
     Label                       bodyLabel_;
     TrapOffset                  prologueTrapOffset_;
 
+    LatentOp                    latentOp_;       // Latent operation for branch (seen next)
+    ValType                     latentType_;     // Operand type, if latentOp_ is true
+    Assembler::Condition        latentIntCmp_;   // Comparison operator, if latentOp_ == Compare, int types
+    Assembler::DoubleCondition  latentDoubleCmp_;// Comparison operator, if latentOp_ == Compare, float types
+
     FuncCompileResults&         compileResults_;
     MacroAssembler&             masm;            // No '_' suffix - too tedious...
 
     AllocatableGeneralRegisterSet availGPR_;
     AllocatableFloatRegisterSet availFPU_;
 #ifdef DEBUG
     bool                        scratchRegisterTaken_;
 #endif
@@ -1820,16 +1820,30 @@ class BaseCompiler
 
     void maybeUnreserveJoinRegI(ExprType type) {
         if (type == ExprType::I32)
             freeI32(joinRegI32);
         else if (type == ExprType::I64)
             freeI64(joinRegI64);
     }
 
+    RegI32 popI32NotJoinReg(ExprType type) {
+        maybeReserveJoinRegI(type);
+        RegI32 r = popI32();
+        maybeUnreserveJoinRegI(type);
+        return r;
+    }
+
+    RegI64 popI64NotJoinReg(ExprType type) {
+        maybeReserveJoinRegI(type);
+        RegI64 r = popI64();
+        maybeUnreserveJoinRegI(type);
+        return r;
+    }
+
     // Return the amount of execution stack consumed by the top numval
     // values on the value stack.
 
     size_t stackConsumed(size_t numval) {
         size_t size = 0;
         MOZ_ASSERT(numval <= stk_.length());
         for (uint32_t i = stk_.length() - 1; numval > 0; numval--, i--) {
             // The size computations come from the implementation of Push() in
@@ -1909,16 +1923,21 @@ class BaseCompiler
     // stack as that will happen as compilation leaves the block.
 
     void popStackBeforeBranch(uint32_t framePushed) {
         uint32_t frameHere = masm.framePushed();
         if (frameHere > framePushed)
             masm.addPtr(ImmWord(frameHere - framePushed), StackPointer);
     }
 
+    bool willPopStackBeforeBranch(uint32_t framePushed) {
+        uint32_t frameHere = masm.framePushed();
+        return frameHere > framePushed;
+    }
+
     // Before exiting a nested control region, pop the execution stack
     // to the level expected by the nesting region, and free the
     // stack.
 
     void popStackOnBlockExit(uint32_t framePushed) {
         uint32_t frameHere = masm.framePushed();
         if (frameHere > framePushed) {
             if (deadCode_)
@@ -3619,23 +3638,156 @@ class BaseCompiler
 
     bool isCompilingAsmJS() const {
         return env_.kind == ModuleKind::AsmJS;
     }
 
     TrapOffset trapOffset() const {
         return iter_.trapOffset();
     }
+
     Maybe<TrapOffset> trapIfNotAsmJS() const {
         return isCompilingAsmJS() ? Nothing() : Some(trapOffset());
     }
+
     TrapDesc trap(Trap t) const {
         return TrapDesc(trapOffset(), t, masm.framePushed());
     }
 
+    ////////////////////////////////////////////////////////////
+    //
+    // Machinery for optimized conditional branches.
+    //
+    // To disable this optimization it is enough always to return false from
+    // sniffConditionalControl{Cmp,Eqz}.
+
+    struct BranchState {
+        static const int32_t NoPop = ~0;
+
+        union {
+            struct {
+                RegI32 lhs;
+                RegI32 rhs;
+                int32_t imm;
+                bool rhsImm;
+            } i32;
+            struct {
+                RegI64 lhs;
+                RegI64 rhs;
+                int64_t imm;
+                bool rhsImm;
+            } i64;
+            struct {
+                RegF32 lhs;
+                RegF32 rhs;
+            } f32;
+            struct {
+                RegF64 lhs;
+                RegF64 rhs;
+            } f64;
+        };
+
+        Label* const label;        // The target of the branch, never NULL
+        const int32_t framePushed; // Either NoPop, or the value to pop to along the taken edge
+        const bool invertBranch;   // If true, invert the sense of the branch
+        const ExprType resultType; // The result propagated along the edges, or Void
+
+        explicit BranchState(Label* label, int32_t framePushed = NoPop,
+                             uint32_t invertBranch = false, ExprType resultType = ExprType::Void)
+          : label(label),
+            framePushed(framePushed),
+            invertBranch(invertBranch),
+            resultType(resultType)
+        {}
+    };
+
+    void setLatentCompare(Assembler::Condition compareOp, ValType operandType) {
+        latentOp_ = LatentOp::Compare;
+        latentType_ = operandType;
+        latentIntCmp_ = compareOp;
+    }
+
+    void setLatentCompare(Assembler::DoubleCondition compareOp, ValType operandType) {
+        latentOp_ = LatentOp::Compare;
+        latentType_ = operandType;
+        latentDoubleCmp_ = compareOp;
+    }
+
+    void setLatentEqz(ValType operandType) {
+        latentOp_ = LatentOp::Eqz;
+        latentType_ = operandType;
+    }
+
+    void resetLatentOp() {
+        latentOp_ = LatentOp::None;
+    }
+
+    void branchTo(Assembler::DoubleCondition c, RegF64 lhs, RegF64 rhs, Label* l) {
+        masm.branchDouble(c, lhs, rhs, l);
+    }
+
+    void branchTo(Assembler::DoubleCondition c, RegF32 lhs, RegF32 rhs, Label* l) {
+        masm.branchFloat(c, lhs, rhs, l);
+    }
+
+    void branchTo(Assembler::Condition c, RegI32 lhs, RegI32 rhs, Label* l) {
+        masm.branch32(c, lhs, rhs, l);
+    }
+
+    void branchTo(Assembler::Condition c, RegI32 lhs, Imm32 rhs, Label* l) {
+        masm.branch32(c, lhs, rhs, l);
+    }
+
+    void branchTo(Assembler::Condition c, RegI64 lhs, RegI64 rhs, Label* l) {
+        masm.branch64(c, lhs, rhs, l);
+    }
+
+    void branchTo(Assembler::Condition c, RegI64 lhs, Imm64 rhs, Label* l) {
+        masm.branch64(c, lhs, rhs, l);
+    }
+
+    // Emit a conditional branch that optionally and optimally cleans up the CPU
+    // stack before we branch.
+    //
+    // Cond is either Assembler::Condition or Assembler::DoubleCondition.
+    //
+    // Lhs is Register, Register64, or FloatRegister.
+    //
+    // Rhs is either the same as Lhs, or an immediate expression compatible with
+    // Lhs "when applicable".
+
+    template<typename Cond, typename Lhs, typename Rhs>
+    void jumpConditionalWithJoinReg(BranchState* b, Cond cond, Lhs lhs, Rhs rhs)
+    {
+        AnyReg r = popJoinRegUnlessVoid(b->resultType);
+
+        if (b->framePushed != BranchState::NoPop && willPopStackBeforeBranch(b->framePushed)) {
+            Label notTaken;
+            branchTo(b->invertBranch ? cond : Assembler::InvertCondition(cond), lhs, rhs, &notTaken);
+            popStackBeforeBranch(b->framePushed);
+            masm.jump(b->label);
+            masm.bind(&notTaken);
+        } else {
+            branchTo(b->invertBranch ? Assembler::InvertCondition(cond) : cond, lhs, rhs, b->label);
+        }
+
+        pushJoinRegUnlessVoid(r);
+    }
+
+    // sniffConditionalControl{Cmp,Eqz} may modify the latentWhatever_ state in
+    // the BaseCompiler so that a subsequent conditional branch can be compiled
+    // optimally.  emitBranchSetup() and emitBranchPerform() will consume that
+    // state.  If the latter methods are not called because deadCode_ is true
+    // then the compiler MUST instead call resetLatentOp() to reset the state.
+
+    template<typename Cond> bool sniffConditionalControlCmp(Cond compareOp, ValType operandType);
+    bool sniffConditionalControlEqz(ValType operandType);
+    void emitBranchSetup(BranchState* b);
+    void emitBranchPerform(BranchState* b);
+
     //////////////////////////////////////////////////////////////////////
 
     MOZ_MUST_USE bool emitBody();
     MOZ_MUST_USE bool emitBlock();
     MOZ_MUST_USE bool emitLoop();
     MOZ_MUST_USE bool emitIf();
     MOZ_MUST_USE bool emitElse();
     MOZ_MUST_USE bool emitEnd();
@@ -3679,20 +3831,20 @@ class BaseCompiler
     void endBlock(ExprType type);
     void endLoop(ExprType type);
     void endIfThen();
     void endIfThenElse(ExprType type);
 
     void doReturn(ExprType returnType, bool popStack);
     void pushReturned(const FunctionCall& call, ExprType type);
 
-    void emitCompareI32(JSOp compareOp, MCompare::CompareType compareType);
-    void emitCompareI64(JSOp compareOp, MCompare::CompareType compareType);
-    void emitCompareF32(JSOp compareOp, MCompare::CompareType compareType);
-    void emitCompareF64(JSOp compareOp, MCompare::CompareType compareType);
+    void emitCompareI32(Assembler::Condition compareOp, ValType compareType);
+    void emitCompareI64(Assembler::Condition compareOp, ValType compareType);
+    void emitCompareF32(Assembler::DoubleCondition compareOp, ValType compareType);
+    void emitCompareF64(Assembler::DoubleCondition compareOp, ValType compareType);
 
     void emitAddI32();
     void emitAddI64();
     void emitAddF64();
     void emitAddF32();
     void emitSubtractI32();
     void emitSubtractI64();
     void emitSubtractF32();
@@ -4413,26 +4565,30 @@ BaseCompiler::emitRotlI64()
     masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitEqzI32()
 {
-    // TODO / OPTIMIZE: Boolean evaluation for control (Bug 1286816)
+    if (sniffConditionalControlEqz(ValType::I32))
+        return;
+
     RegI32 r0 = popI32();
     masm.cmp32Set(Assembler::Equal, r0, Imm32(0), r0);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitEqzI64()
 {
-    // TODO / OPTIMIZE: Boolean evaluation for control (Bug 1286816)
+    if (sniffConditionalControlEqz(ValType::I64))
+        return;
+
     // TODO / OPTIMIZE: Avoid the temp register (Bug 1316848)
     RegI64 r0 = popI64();
     RegI64 r1 = needI64();
     setI64(0, r1);
     RegI32 i0 = fromI64(r0);
     cmp64Set(Assembler::Equal, r0, r1, i0);
     freeI64(r1);
     freeI64Except(r0, i0);
@@ -4824,16 +4980,165 @@ BaseCompiler::emitReinterpretI64AsF64()
 {
     RegI64 r0 = popI64();
     RegF64 d0 = needF64();
     reinterpretI64AsF64(r0, d0);
     freeI64(r0);
     pushF64(d0);
 }
 
+template<typename Cond>
+bool
+BaseCompiler::sniffConditionalControlCmp(Cond compareOp, ValType operandType)
+{
+    MOZ_ASSERT(latentOp_ == LatentOp::None, "Latent comparison state not properly reset");
+
+    switch (iter_.peekOp()) {
+      case uint16_t(Op::BrIf):
+      case uint16_t(Op::Select):
+      case uint16_t(Op::If):
+        setLatentCompare(compareOp, operandType);
+        return true;
+      default:
+        return false;
+    }
+}
+
+bool
+BaseCompiler::sniffConditionalControlEqz(ValType operandType)
+{
+    MOZ_ASSERT(latentOp_ == LatentOp::None, "Latent comparison state not properly reset");
+
+    switch (iter_.peekOp()) {
+      case uint16_t(Op::BrIf):
+      case uint16_t(Op::Select):
+      case uint16_t(Op::If):
+        setLatentEqz(operandType);
+        return true;
+      default:
+        return false;
+    }
+}
+
+void
+BaseCompiler::emitBranchSetup(BranchState* b)
+{
+    // Set up fields so that emitBranchPerform() need not switch on latentOp_.
+    switch (latentOp_) {
+      case LatentOp::None: {
+        latentIntCmp_ = Assembler::NotEqual;
+        latentType_ = ValType::I32;
+        b->i32.lhs = popI32NotJoinReg(b->resultType);
+        b->i32.rhsImm = true;
+        b->i32.imm = 0;
+        break;
+      }
+      case LatentOp::Compare: {
+        switch (latentType_) {
+          case ValType::I32: {
+            if (popConstI32(b->i32.imm)) {
+                b->i32.lhs = popI32NotJoinReg(b->resultType);
+                b->i32.rhsImm = true;
+            } else {
+                maybeReserveJoinRegI(b->resultType);
+                pop2xI32(&b->i32.lhs, &b->i32.rhs);
+                maybeUnreserveJoinRegI(b->resultType);
+                b->i32.rhsImm = false;
+            }
+            break;
+          }
+          case ValType::I64: {
+            maybeReserveJoinRegI(b->resultType);
+            pop2xI64(&b->i64.lhs, &b->i64.rhs);
+            maybeUnreserveJoinRegI(b->resultType);
+            b->i64.rhsImm = false;
+            break;
+          }
+          case ValType::F32: {
+            pop2xF32(&b->f32.lhs, &b->f32.rhs);
+            break;
+          }
+          case ValType::F64: {
+            pop2xF64(&b->f64.lhs, &b->f64.rhs);
+            break;
+          }
+          default: {
+            MOZ_CRASH("Unexpected type for LatentOp::Compare");
+          }
+        }
+        break;
+      }
+      case LatentOp::Eqz: {
+        switch (latentType_) {
+          case ValType::I32: {
+            latentIntCmp_ = Assembler::Equal;
+            b->i32.lhs = popI32NotJoinReg(b->resultType);
+            b->i32.rhsImm = true;
+            b->i32.imm = 0;
+            break;
+          }
+          case ValType::I64: {
+            latentIntCmp_ = Assembler::Equal;
+            b->i64.lhs = popI64NotJoinReg(b->resultType);
+            b->i64.rhsImm = true;
+            b->i64.imm = 0;
+            break;
+          }
+          default: {
+            MOZ_CRASH("Unexpected type for LatentOp::Eqz");
+          }
+        }
+        break;
+      }
+    }
+}
+
+void
+BaseCompiler::emitBranchPerform(BranchState* b)
+{
+    switch (latentType_) {
+      case ValType::I32: {
+        if (b->i32.rhsImm) {
+            jumpConditionalWithJoinReg(b, latentIntCmp_, b->i32.lhs, Imm32(b->i32.imm));
+        } else {
+            jumpConditionalWithJoinReg(b, latentIntCmp_, b->i32.lhs, b->i32.rhs);
+            freeI32(b->i32.rhs);
+        }
+        freeI32(b->i32.lhs);
+        break;
+      }
+      case ValType::I64: {
+        if (b->i64.rhsImm) {
+            jumpConditionalWithJoinReg(b, latentIntCmp_, b->i64.lhs, Imm64(b->i64.imm));
+        } else {
+            jumpConditionalWithJoinReg(b, latentIntCmp_, b->i64.lhs, b->i64.rhs);
+            freeI64(b->i64.rhs);
+        }
+        freeI64(b->i64.lhs);
+        break;
+      }
+      case ValType::F32: {
+        jumpConditionalWithJoinReg(b, latentDoubleCmp_, b->f32.lhs, b->f32.rhs);
+        freeF32(b->f32.lhs);
+        freeF32(b->f32.rhs);
+        break;
+      }
+      case ValType::F64: {
+        jumpConditionalWithJoinReg(b, latentDoubleCmp_, b->f64.lhs, b->f64.rhs);
+        freeF64(b->f64.lhs);
+        freeF64(b->f64.rhs);
+        break;
+      }
+      default: {
+        MOZ_CRASH("Unexpected type for LatentOp::Compare");
+      }
+    }
+    resetLatentOp();
+}
+
 // For blocks and loops and ifs:
 //
 //  - Sync the value stack before going into the block in order to simplify exit
 //    from the block: all exits from the block can assume that there are no
 //    live registers except the one carrying the exit value.
 //  - The block can accumulate a number of dead values on the stacks, so when
 //    branching out of the block or falling out at the end be sure to
 //    pop the appropriate stacks back to where they were on entry, while
@@ -4956,29 +5261,29 @@ BaseCompiler::emitIf()
     UniquePooledLabel endLabel(newLabel());
     if (!endLabel)
         return false;
 
     UniquePooledLabel elseLabel(newLabel());
     if (!elseLabel)
         return false;
 
-    RegI32 rc;
+    BranchState b(elseLabel.get(), BranchState::NoPop, InvertBranch(true));
     if (!deadCode_) {
-        rc = popI32();
-        sync();                    // Simplifies branching out from the arms
+        emitBranchSetup(&b);
+        sync();
+    } else {
+        resetLatentOp();
     }
 
     if (!pushControl(&endLabel, &elseLabel))
         return false;
 
-    if (!deadCode_) {
-        masm.branch32(Assembler::Equal, rc, Imm32(0), controlItem(0).otherLabel);
-        freeI32(rc);
-    }
+    if (!deadCode_)
+        emitBranchPerform(&b);
 
     return true;
 }
 
 void
 BaseCompiler::endIfThen()
 {
     Control& ifThen = controlItem(0);
@@ -5131,48 +5436,26 @@ bool
 BaseCompiler::emitBrIf()
 {
     uint32_t relativeDepth;
     ExprType type;
     Nothing unused_value, unused_condition;
     if (!iter_.readBrIf(&relativeDepth, &type, &unused_value, &unused_condition))
         return false;
 
-    if (deadCode_)
+    if (deadCode_) {
+        resetLatentOp();
         return true;
+    }
 
     Control& target = controlItem(relativeDepth);
 
-    // TODO / OPTIMIZE (Bug 1286816): Optimize boolean evaluation for control by
-    // allowing a conditional expression to be left on the stack and reified
-    // here as part of the branch instruction.
-
-    // Don't use joinReg for rc
-    maybeReserveJoinRegI(type);
-
-    // Condition value is on top, always I32.
-    RegI32 rc = popI32();
-
-    maybeUnreserveJoinRegI(type);
-
-    // Save any value in the designated join register, where the
-    // normal block exit code will also leave it.
-    AnyReg r = popJoinRegUnlessVoid(type);
-
-    Label notTaken;
-    masm.branch32(Assembler::Equal, rc, Imm32(0), &notTaken);
-    popStackBeforeBranch(target.framePushed);
-    masm.jump(target.label);
-    masm.bind(&notTaken);
-
-    // This register is free in the remainder of the block.
-    freeI32(rc);
-
-    // br_if returns its value(s).
-    pushJoinRegUnlessVoid(r);
+    BranchState b(target.label, target.framePushed, InvertBranch(false), type);
+    emitBranchSetup(&b);
+    emitBranchPerform(&b);
 
     return true;
 }
 
 bool
 BaseCompiler::emitBrTable()
 {
     uint32_t tableLength;
@@ -6127,222 +6410,150 @@ BaseCompiler::emitSelect()
 {
     ValType type;
     Nothing unused_trueValue;
     Nothing unused_falseValue;
     Nothing unused_condition;
     if (!iter_.readSelect(&type, &unused_trueValue, &unused_falseValue, &unused_condition))
         return false;
 
-    if (deadCode_)
+    if (deadCode_) {
+        resetLatentOp();
         return true;
+    }
 
     // I32 condition on top, then false, then true.
 
-    RegI32 rc = popI32();
+    Label done;
+    BranchState b(&done);
+    emitBranchSetup(&b);
+
     switch (type) {
       case ValType::I32: {
-        Label done;
         RegI32 r0, r1;
         pop2xI32(&r0, &r1);
-        masm.branch32(Assembler::NotEqual, rc, Imm32(0), &done);
+        emitBranchPerform(&b);
         moveI32(r1, r0);
         masm.bind(&done);
         freeI32(r1);
         pushI32(r0);
         break;
       }
       case ValType::I64: {
-        Label done;
         RegI64 r0, r1;
         pop2xI64(&r0, &r1);
-        masm.branch32(Assembler::NotEqual, rc, Imm32(0), &done);
+        emitBranchPerform(&b);
         moveI64(r1, r0);
         masm.bind(&done);
         freeI64(r1);
         pushI64(r0);
         break;
       }
       case ValType::F32: {
-        Label done;
         RegF32 r0, r1;
         pop2xF32(&r0, &r1);
-        masm.branch32(Assembler::NotEqual, rc, Imm32(0), &done);
+        emitBranchPerform(&b);
         moveF32(r1, r0);
         masm.bind(&done);
         freeF32(r1);
         pushF32(r0);
         break;
       }
       case ValType::F64: {
-        Label done;
         RegF64 r0, r1;
         pop2xF64(&r0, &r1);
-        masm.branch32(Assembler::NotEqual, rc, Imm32(0), &done);
+        emitBranchPerform(&b);
         moveF64(r1, r0);
         masm.bind(&done);
         freeF64(r1);
         pushF64(r0);
         break;
       }
       default: {
         MOZ_CRASH("select type");
       }
     }
-    freeI32(rc);
 
     return true;
 }
 
 void
-BaseCompiler::emitCompareI32(JSOp compareOp, MCompare::CompareType compareType)
-{
-    // TODO / OPTIMIZE (bug 1286816): if we want to generate good code for
-    // boolean operators for control it is possible to delay generating code
-    // here by pushing a compare operation on the stack, after all it is
-    // side-effect free.  The popping code for br_if will handle it differently,
-    // but other popI32() will just force code generation.
-    //
-    // TODO / OPTIMIZE (bug 1286816): Comparisons against constants using the
-    // same popConstant pattern as for add().
-
-    MOZ_ASSERT(compareType == MCompare::Compare_Int32 || compareType == MCompare::Compare_UInt32);
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    bool u = compareType == MCompare::Compare_UInt32;
-    switch (compareOp) {
-      case JSOP_EQ:
-        masm.cmp32Set(Assembler::Equal, r0, r1, r0);
-        break;
-      case JSOP_NE:
-        masm.cmp32Set(Assembler::NotEqual, r0, r1, r0);
-        break;
-      case JSOP_LE:
-        masm.cmp32Set(u ? Assembler::BelowOrEqual : Assembler::LessThanOrEqual, r0, r1, r0);
-        break;
-      case JSOP_LT:
-        masm.cmp32Set(u ? Assembler::Below : Assembler::LessThan, r0, r1, r0);
-        break;
-      case JSOP_GE:
-        masm.cmp32Set(u ? Assembler::AboveOrEqual : Assembler::GreaterThanOrEqual, r0, r1, r0);
-        break;
-      case JSOP_GT:
-        masm.cmp32Set(u ? Assembler::Above : Assembler::GreaterThan, r0, r1, r0);
-        break;
-      default:
-        MOZ_CRASH("Compiler bug: Unexpected compare opcode");
-    }
-    freeI32(r1);
-    pushI32(r0);
+BaseCompiler::emitCompareI32(Assembler::Condition compareOp, ValType compareType)
+{
+    MOZ_ASSERT(compareType == ValType::I32);
+
+    if (sniffConditionalControlCmp(compareOp, compareType))
+        return;
+
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r0 = popI32();
+        masm.cmp32Set(compareOp, r0, Imm32(c), r0);
+        pushI32(r0);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32(&r0, &r1);
+        masm.cmp32Set(compareOp, r0, r1, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
-BaseCompiler::emitCompareI64(JSOp compareOp, MCompare::CompareType compareType)
-{
-    MOZ_ASSERT(compareType == MCompare::Compare_Int64 || compareType == MCompare::Compare_UInt64);
+BaseCompiler::emitCompareI64(Assembler::Condition compareOp, ValType compareType)
+{
+    MOZ_ASSERT(compareType == ValType::I64);
+
+    if (sniffConditionalControlCmp(compareOp, compareType))
+        return;
+
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
     RegI32 i0(fromI64(r0));
-    bool u = compareType == MCompare::Compare_UInt64;
-    switch (compareOp) {
-      case JSOP_EQ:
-        cmp64Set(Assembler::Equal, r0, r1, i0);
-        break;
-      case JSOP_NE:
-        cmp64Set(Assembler::NotEqual, r0, r1, i0);
-        break;
-      case JSOP_LE:
-        cmp64Set(u ? Assembler::BelowOrEqual : Assembler::LessThanOrEqual, r0, r1, i0);
-        break;
-      case JSOP_LT:
-        cmp64Set(u ? Assembler::Below : Assembler::LessThan, r0, r1, i0);
-        break;
-      case JSOP_GE:
-        cmp64Set(u ? Assembler::AboveOrEqual : Assembler::GreaterThanOrEqual, r0, r1, i0);
-        break;
-      case JSOP_GT:
-        cmp64Set(u ? Assembler::Above : Assembler::GreaterThan, r0, r1, i0);
-        break;
-      default:
-        MOZ_CRASH("Compiler bug: Unexpected compare opcode");
-    }
+    cmp64Set(compareOp, r0, r1, i0);
     freeI64(r1);
     freeI64Except(r0, i0);
     pushI32(i0);
 }
 
 void
-BaseCompiler::emitCompareF32(JSOp compareOp, MCompare::CompareType compareType)
-{
-    MOZ_ASSERT(compareType == MCompare::Compare_Float32);
+BaseCompiler::emitCompareF32(Assembler::DoubleCondition compareOp, ValType compareType)
+{
+    MOZ_ASSERT(compareType == ValType::F32);
+
+    if (sniffConditionalControlCmp(compareOp, compareType))
+        return;
+
     Label across;
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     RegI32 i0 = needI32();
     masm.mov(ImmWord(1), i0);
-    switch (compareOp) {
-      case JSOP_EQ:
-        masm.branchFloat(Assembler::DoubleEqual, r0, r1, &across);
-        break;
-      case JSOP_NE:
-        masm.branchFloat(Assembler::DoubleNotEqualOrUnordered, r0, r1, &across);
-        break;
-      case JSOP_LE:
-        masm.branchFloat(Assembler::DoubleLessThanOrEqual, r0, r1, &across);
-        break;
-      case JSOP_LT:
-        masm.branchFloat(Assembler::DoubleLessThan, r0, r1, &across);
-        break;
-      case JSOP_GE:
-        masm.branchFloat(Assembler::DoubleGreaterThanOrEqual, r0, r1, &across);
-        break;
-      case JSOP_GT:
-        masm.branchFloat(Assembler::DoubleGreaterThan, r0, r1, &across);
-        break;
-      default:
-        MOZ_CRASH("Compiler bug: Unexpected compare opcode");
-    }
+    masm.branchFloat(compareOp, r0, r1, &across);
     masm.mov(ImmWord(0), i0);
     masm.bind(&across);
     freeF32(r0);
     freeF32(r1);
     pushI32(i0);
 }
 
 void
-BaseCompiler::emitCompareF64(JSOp compareOp, MCompare::CompareType compareType)
-{
-    MOZ_ASSERT(compareType == MCompare::Compare_Double);
+BaseCompiler::emitCompareF64(Assembler::DoubleCondition compareOp, ValType compareType)
+{
+    MOZ_ASSERT(compareType == ValType::F64);
+
+    if (sniffConditionalControlCmp(compareOp, compareType))
+        return;
+
     Label across;
     RegF64 r0, r1;
     pop2xF64(&r0, &r1);
     RegI32 i0 = needI32();
     masm.mov(ImmWord(1), i0);
-    switch (compareOp) {
-      case JSOP_EQ:
-        masm.branchDouble(Assembler::DoubleEqual, r0, r1, &across);
-        break;
-      case JSOP_NE:
-        masm.branchDouble(Assembler::DoubleNotEqualOrUnordered, r0, r1, &across);
-        break;
-      case JSOP_LE:
-        masm.branchDouble(Assembler::DoubleLessThanOrEqual, r0, r1, &across);
-        break;
-      case JSOP_LT:
-        masm.branchDouble(Assembler::DoubleLessThan, r0, r1, &across);
-        break;
-      case JSOP_GE:
-        masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, r0, r1, &across);
-        break;
-      case JSOP_GT:
-        masm.branchDouble(Assembler::DoubleGreaterThan, r0, r1, &across);
-        break;
-      default:
-        MOZ_CRASH("Compiler bug: Unexpected compare opcode");
-    }
+    masm.branchDouble(compareOp, r0, r1, &across);
     masm.mov(ImmWord(0), i0);
     masm.bind(&across);
     freeF64(r0);
     freeF64(r1);
     pushI32(i0);
 }
 
 bool
@@ -6470,19 +6681,19 @@ BaseCompiler::emitBody()
         Nothing unused_a, unused_b;
 
 #define emitBinary(doEmit, type) \
         iter_.readBinary(type, &unused_a, &unused_b) && (deadCode_ || (doEmit(), true))
 
 #define emitUnary(doEmit, type) \
         iter_.readUnary(type, &unused_a) && (deadCode_ || (doEmit(), true))
 
-#define emitComparison(doEmit, operandType, compareOp, compareType) \
+#define emitComparison(doEmit, operandType, compareOp) \
         iter_.readComparison(operandType, &unused_a, &unused_b) && \
-            (deadCode_ || (doEmit(compareOp, compareType), true))
+            (deadCode_ || (doEmit(compareOp, operandType), true))
 
 #define emitConversion(doEmit, inType, outType) \
         iter_.readConversion(inType, outType, &unused_a) && (deadCode_ || (doEmit(), true))
 
 #define emitConversionOOM(doEmit, inType, outType) \
         iter_.readConversion(inType, outType, &unused_a) && (deadCode_ || doEmit())
 
 #define emitCalloutConversionOOM(doEmit, symbol, inType, outType) \
@@ -6957,79 +7168,79 @@ BaseCompiler::emitBody()
             CHECK_NEXT(emitBinary(emitCopysignF64, ValType::F64));
           case uint16_t(Op::F64Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntD, ValType::F64));
           case uint16_t(Op::F64Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncD, ValType::F64));
 
           // Comparisons
           case uint16_t(Op::I32Eq):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_EQ, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::Equal));
           case uint16_t(Op::I32Ne):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_NE, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::NotEqual));
           case uint16_t(Op::I32LtS):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::LessThan));
           case uint16_t(Op::I32LeS):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::LessThanOrEqual));
           case uint16_t(Op::I32GtS):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::GreaterThan));
           case uint16_t(Op::I32GeS):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_Int32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::GreaterThanOrEqual));
           case uint16_t(Op::I32LtU):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_UInt32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::Below));
           case uint16_t(Op::I32LeU):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_UInt32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::BelowOrEqual));
           case uint16_t(Op::I32GtU):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_UInt32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::Above));
           case uint16_t(Op::I32GeU):
-            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_UInt32));
+            CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, Assembler::AboveOrEqual));
           case uint16_t(Op::I64Eq):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_EQ, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::Equal));
           case uint16_t(Op::I64Ne):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_NE, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::NotEqual));
           case uint16_t(Op::I64LtS):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::LessThan));
           case uint16_t(Op::I64LeS):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::LessThanOrEqual));
           case uint16_t(Op::I64GtS):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::GreaterThan));
           case uint16_t(Op::I64GeS):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_Int64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::GreaterThanOrEqual));
           case uint16_t(Op::I64LtU):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_UInt64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::Below));
           case uint16_t(Op::I64LeU):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_UInt64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::BelowOrEqual));
           case uint16_t(Op::I64GtU):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_UInt64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::Above));
           case uint16_t(Op::I64GeU):
-            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_UInt64));
+            CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, Assembler::AboveOrEqual));
           case uint16_t(Op::F32Eq):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_EQ, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleEqual));
           case uint16_t(Op::F32Ne):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_NE, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleNotEqualOrUnordered));
           case uint16_t(Op::F32Lt):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LT, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleLessThan));
           case uint16_t(Op::F32Le):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LE, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleLessThanOrEqual));
           case uint16_t(Op::F32Gt):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GT, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleGreaterThan));
           case uint16_t(Op::F32Ge):
-            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GE, MCompare::Compare_Float32));
+            CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, Assembler::DoubleGreaterThanOrEqual));
           case uint16_t(Op::F64Eq):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_EQ, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleEqual));
           case uint16_t(Op::F64Ne):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_NE, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleNotEqualOrUnordered));
           case uint16_t(Op::F64Lt):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LT, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleLessThan));
           case uint16_t(Op::F64Le):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LE, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleLessThanOrEqual));
           case uint16_t(Op::F64Gt):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GT, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleGreaterThan));
           case uint16_t(Op::F64Ge):
-            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GE, MCompare::Compare_Double));
+            CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, Assembler::DoubleGreaterThanOrEqual));
 
           // SIMD
 #define CASE(TYPE, OP, SIGN) \
           case uint16_t(Op::TYPE##OP): \
             MOZ_CRASH("Unimplemented SIMD");
 #define I8x16CASE(OP) CASE(I8x16, OP, SimdSign::Signed)
 #define I16x8CASE(OP) CASE(I16x8, OP, SimdSign::Signed)
 #define I32x4CASE(OP) CASE(I32x4, OP, SimdSign::Signed)
@@ -7175,16 +7386,20 @@ BaseCompiler::BaseCompiler(const ModuleE
       alloc_(compileResults.alloc()),
       locals_(locals),
       localSize_(0),
       varLow_(0),
       varHigh_(0),
       maxFramePushed_(0),
       deadCode_(false),
       prologueTrapOffset_(trapOffset()),
+      latentOp_(LatentOp::None),
+      latentType_(ValType::I32),
+      latentIntCmp_(Assembler::Equal),
+      latentDoubleCmp_(Assembler::DoubleEqual),
       compileResults_(compileResults),
       masm(compileResults_.masm()),
       availGPR_(GeneralRegisterSet::All()),
       availFPU_(FloatRegisterSet::All()),
 #ifdef DEBUG
       scratchRegisterTaken_(false),
 #endif
       tlsSlot_(0),
--- a/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-003-ref.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-003-ref.html
@@ -9,18 +9,17 @@
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1218178">
   <style type="text/css">
 html,body { color:black; background-color:white; font:12px monospace; padding:0; margin:0; }
 
 .grid {
   display: grid;
   float: left;
   border: 1px solid;
-  align-items: start;
-  justify-items: start;
+  place-items: start;
   margin-bottom:1em;
 }
 
 .row { }
 .row img { min-width:0; }
 
 br { clear:both; }
 
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-002-ref.html
@@ -9,18 +9,17 @@
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1176775">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
 
 .grid {
   display: inline-grid;
   border: 1px solid;
   margin: 5px;
-  align-items: start;
-  justify-items: start;
+  place-items: start start;
 }
 .vertical-tests div { vertical-align:bottom }
   </style>
 </head>
 <body>
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="width:4px; height:48px">
--- a/layout/reftests/css-grid/grid-item-mixed-baseline-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-mixed-baseline-002-ref.html
@@ -38,18 +38,18 @@ span {
 span:nth-child(1) { font-size:32px; }
 span:nth-child(2) { font-size:12px; }
 span:nth-child(3) { font-size:10px; }
 span:nth-child(4) { font-size:24px; }
 
 .pbs { padding-block-start: 15px; margin-block-start: 5px; }
 .pbe { padding-block-end: 7px; margin-block-end: 3px; }
 
-.fb { align-self:baseline; justify-self:self-start; }
-.lb { align-self:last baseline; justify-self:self-end; }
+.fb { place-self:first baseline self-start; }
+.lb { place-self:last baseline self-end; }
 .s  { justify-self:stretch; }
 
 .sfb { align-self:baseline; }
 .slb { align-self:last baseline; align-content:self-end;}
 
 .hl { writing-mode: horizontal-tb; direction:ltr; }
 .hr { writing-mode: horizontal-tb; direction:rtl; }
 .vl { writing-mode: vertical-lr; text-orientation: sideways; }
--- a/layout/reftests/css-grid/grid-item-mixed-baseline-002.html
+++ b/layout/reftests/css-grid/grid-item-mixed-baseline-002.html
@@ -16,23 +16,21 @@ html,body {
 }
 
 .grid {
   float: left;
   display: grid;
   grid: 100px / repeat(10, auto);
   border: 2px solid;
   margin: 1px;
-  align-content: start;
-  justify-content: end;
+  place-content: start end;
 }
 .c {
   grid: repeat(4, auto) / 100px;
-  align-content: end;
-  justify-content: start;
+  place-content: end start;
 }
 .t2 { grid: 100px / repeat(3, auto);}
 
 span { 
   background: lime;
   display: inline-block;
   border: 1px solid black;
 }
@@ -40,19 +38,19 @@ span {
 span:nth-child(1) { font-size:32px; }
 span:nth-child(2) { font-size:12px; }
 span:nth-child(3) { font-size:10px; }
 span:nth-child(4) { font-size:24px; }
 
 .pbs { padding-block-start: 15px; margin-block-start: 5px; }
 .pbe { padding-block-end: 7px; margin-block-end: 3px; }
 
-.fb { align-content:baseline; align-self:self-start; justify-self:self-start; }
-.lb { align-content:last baseline; align-self:self-end; justify-self:self-end; }
-.s  { align-self:stretch; justify-self:stretch; }
+.fb { align-content:baseline; place-self:self-start; }
+.lb { align-content:last baseline; place-self:self-end; }
+.s  { place-self:stretch; }
 
 .sfb { align-self:baseline; }
 .slb { align-self:last baseline; align-content:self-end;}
 
 .hl { writing-mode: horizontal-tb; direction:ltr; }
 .hr { writing-mode: horizontal-tb; direction:rtl; }
 .vl { writing-mode: vertical-lr; text-orientation: sideways; }
 .vr { writing-mode: vertical-rl; text-orientation: sideways; }
--- a/layout/reftests/css-grid/grid-item-self-baseline-001.html
+++ b/layout/reftests/css-grid/grid-item-self-baseline-001.html
@@ -13,18 +13,17 @@
 html,body {
     color:black; background-color:white; font-size:16px; padding:0; margin:0;
 }
 
 .grid {
   float: left;
   display: grid;
   grid: auto / repeat(4, auto);
-  align-items: start;
-  justify-items: start;
+  place-items: start;
   border: 2px solid;
   padding: 1px;
   margin: 1px;
 }
 .c {
   grid: repeat(4, auto) / auto;
 }
 
--- a/layout/reftests/css-grid/grid-percent-grid-gap-001.html
+++ b/layout/reftests/css-grid/grid-percent-grid-gap-001.html
@@ -58,17 +58,17 @@ br { clear: both; }
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
 </div>
 </div>
 
 <div class="inline-grid" style="grid: auto / auto">
-<div class="grid percentgap" style="align-self:start; justify-self:start; width:160px; height:120px">
+<div class="grid percentgap" style="place-self:start/start; width:160px; height:120px">
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
 </div>
 </div>
 
 <div class="float">
@@ -76,17 +76,17 @@ br { clear: both; }
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
 </div>
 </div>
 
 <div class="inline-grid">
-<div class="grid percentgap" style="align-self:start; justify-self:start">
+<div class="grid percentgap" style="place-self:start">
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
   <span><x></x></span>
 </div>
 </div>
 
 <br>
--- a/layout/reftests/css-grid/grid-percent-intrinsic-sizing-001.html
+++ b/layout/reftests/css-grid/grid-percent-intrinsic-sizing-001.html
@@ -17,18 +17,17 @@ html,body {
 div {
   display: grid;
   float: left;
   grid-template-columns: auto auto;
   grid-template-rows: 5px;
   height: 5px;
   border: 1px solid;
   clear: left;
-  align-content: start;
-  justify-content: start;
+  place-content: start start;
 }
 
 span {
   min-width: 10px;
   background: grey;
 }
 span:nth-child(2) { background:lime; }
 x { background: blue; }
--- a/layout/reftests/css-grid/grid-placement-implicit-named-areas-001-ref.html
+++ b/layout/reftests/css-grid/grid-placement-implicit-named-areas-001-ref.html
@@ -11,20 +11,18 @@
 div {
   display: grid;
   grid-auto-columns: 3px;
   grid-auto-rows: 3px;
   border: 1px solid;
   float: left;
   width: 100px;
   margin: 2px;
-  align-items: stretch;
-  justify-items: stretch;
-  align-content: start;
-  justify-content: start;
+  place-items: stretch;
+  place-content: start;
 }
 .row-tests div {
   height: 100px;
 }
 span { background:lime; grid-column:A/B; grid-row:A/B; }
 
 .col-valid { grid-template-columns:[A] 40px [] 40px [B]; }
 .row-valid { grid-template-rows:   [A] 40px [] 40px [B]; }
--- a/layout/reftests/w3c-css/import-tests.py
+++ b/layout/reftests/w3c-css/import-tests.py
@@ -45,16 +45,19 @@ gPrefixedProperties = [
     "column-rule-color",
     "column-rule-style",
     "column-rule-width",
     "columns",
     "column-span",
     "column-width"
 ]
 
+gPrefixRegexp = re.compile(
+    r"([^-#]|^)(" + r"|".join(gPrefixedProperties) + r")\b")
+
 # Map of about:config prefs that need toggling, for a given test subdirectory.
 # Entries should look like:
 #  "$SUBDIR_NAME": "pref($PREF_NAME, $PREF_VALUE)"
 #
 # For example, when "@supports" was behind a pref, gDefaultPreferences had:
 #  "css3-conditional": "pref(layout.css.supports-rule.enabled,true)"
 gDefaultPreferences = {
 }
@@ -129,17 +132,17 @@ def copy_file(test, srcfile, destname, i
     gLog.write("Importing " + to_unix_path_sep(logname) +
                " to " + to_unix_path_sep(destname) + "\n")
     destfile = os.path.join(gDestPath, destname)
     destdir = os.path.dirname(destfile)
     if not os.path.exists(destdir):
         os.makedirs(destdir)
     if os.path.exists(destfile):
         raise StandardError("file " + destfile + " already exists")
-    copy_and_prefix(test, srcfile, destfile, gPrefixedProperties, isSupportFile)
+    copy_and_prefix(test, srcfile, destfile, isSupportFile)
 
 def copy_support_files(test, dirname):
     global gSrcPath
     if dirname in support_dirs_mapped:
         return
     support_dirs_mapped.add(dirname)
     support_dir = os.path.join(dirname, "support")
     if not os.path.exists(support_dir):
@@ -237,37 +240,35 @@ AHEM_DECL_HTML = """<style type="text/cs
 """ + AHEM_DECL_CONTENT + """
 </style>
 """
 AHEM_DECL_XML = """<style type="text/css"><![CDATA[
 """ + AHEM_DECL_CONTENT + """
 ]]></style>
 """
 
-def copy_and_prefix(test, aSourceFileName, aDestFileName, aProps, isSupportFile=False):
-    global gTestFlags
+def copy_and_prefix(test, aSourceFileName, aDestFileName, isSupportFile=False):
+    global gTestFlags, gPrefixRegexp
     newFile = open(aDestFileName, 'wb')
     unPrefixedFile = open(aSourceFileName, 'rb')
     testName = aDestFileName[len(gDestPath)+1:]
     ahemFontAdded = False
     for line in unPrefixedFile:
         replacementLine = line
         searchRegex = "\s*<style\s*"
 
         if not isSupportFile and not ahemFontAdded and 'ahem' in gTestFlags[test] and re.search(searchRegex, line):
             # First put our ahem font declation before the first <style>
             # element
             template = AHEM_DECL_HTML if is_html(aDestFileName) else AHEM_DECL_XML
             ahemPath = os.path.relpath(AHEM_FONT_PATH, os.path.dirname(aDestFileName))
             newFile.write(template.format(to_unix_path_sep(ahemPath)))
             ahemFontAdded = True
 
-        for prop in aProps:
-            replacementLine = re.sub(r"([^-#]|^)" + prop + r"\b", r"\1-moz-" + prop, replacementLine)
-
+        replacementLine = gPrefixRegexp.sub(r"\1-moz-\2", replacementLine)
         newFile.write(replacementLine)
 
     newFile.close()
     unPrefixedFile.close()
 
 def read_options():
     global gArgs, gOptions
     op = OptionParser()
@@ -344,18 +345,16 @@ def main():
         testType = test[key - 1]
         testFlags = gTestFlags[test[key]]
         # Replace the Windows separators if any. Our internal strings
         # all use the system separator, however the failure/skip lists
         # and reftest.list always use '/' so we fix the paths here.
         test[key] = to_unix_path_sep(test[key])
         test[key + 1] = to_unix_path_sep(test[key + 1])
         testKey = test[key]
-        if 'ahem' in testFlags:
-            test = ["HTTP(../../..)"] + test
         fail = []
         for pattern, failureType in gFailList:
             if pattern.match(testKey):
                 fail = failureType
         test = fail + test
         listfile.write(" ".join(test) + "\n")
     listfile.close()
 
--- a/layout/reftests/w3c-css/received/reftest.list
+++ b/layout/reftests/w3c-css/received/reftest.list
@@ -36,155 +36,155 @@
 == css-conditional-3/at-supports-032.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-033.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-034.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-035.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-036.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-037.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-038.html css-conditional-3/at-supports-001-ref.html
 == css-conditional-3/at-supports-039.html css-conditional-3/at-supports-001-ref.html
-HTTP(../../..) == css-multicol-1/multicol-basic-001.html css-multicol-1/reference/multicol-basic-ref.html
-HTTP(../../..) == css-multicol-1/multicol-basic-002.html css-multicol-1/reference/multicol-basic-ref.html
-HTTP(../../..) == css-multicol-1/multicol-basic-003.html css-multicol-1/reference/multicol-basic-ref.html
-HTTP(../../..) == css-multicol-1/multicol-basic-004.html css-multicol-1/reference/multicol-basic-ref.html
-fails HTTP(../../..) == css-multicol-1/multicol-block-clip-001.xht css-multicol-1/multicol-block-clip-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-block-clip-002.xht css-multicol-1/multicol-block-clip-002-ref.xht
+== css-multicol-1/multicol-basic-001.html css-multicol-1/reference/multicol-basic-ref.html
+== css-multicol-1/multicol-basic-002.html css-multicol-1/reference/multicol-basic-ref.html
+== css-multicol-1/multicol-basic-003.html css-multicol-1/reference/multicol-basic-ref.html
+== css-multicol-1/multicol-basic-004.html css-multicol-1/reference/multicol-basic-ref.html
+fails == css-multicol-1/multicol-block-clip-001.xht css-multicol-1/multicol-block-clip-001-ref.xht
+fails == css-multicol-1/multicol-block-clip-002.xht css-multicol-1/multicol-block-clip-002-ref.xht
 fails == css-multicol-1/multicol-br-inside-avoidcolumn-001.xht css-multicol-1/multicol-br-inside-avoidcolumn-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-break-000.xht css-multicol-1/multicol-break-000-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-break-001.xht css-multicol-1/multicol-break-001-ref.xht
-fuzzy(116,1008) HTTP(../../..) == css-multicol-1/multicol-clip-001.xht css-multicol-1/multicol-clip-001-ref.xht
-fuzzy(116,702) HTTP(../../..) == css-multicol-1/multicol-clip-002.xht css-multicol-1/multicol-clip-002-ref.xht
-fuzzy(116,467) HTTP(../../..) == css-multicol-1/multicol-collapsing-001.xht css-multicol-1/multicol-collapsing-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-001.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-002.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-003.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-004.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-005.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-006.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-columns-007.xht css-multicol-1/multicol-columns-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-columns-invalid-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-columns-invalid-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-columns-toolong-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(116,530) HTTP(../../..) == css-multicol-1/multicol-containing-001.xht css-multicol-1/multicol-containing-001-ref.xht
-fuzzy(215,241) HTTP(../../..) == css-multicol-1/multicol-containing-002.xht css-multicol-1/multicol-containing-002-ref.xht
-fuzzy(87,180) HTTP(../../..) == css-multicol-1/multicol-count-001.xht css-multicol-1/multicol-columns-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-002.xht css-multicol-1/multicol-count-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-computed-001.xht css-multicol-1/multicol-count-computed-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-computed-002.xht css-multicol-1/multicol-count-computed-2-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-computed-003.xht css-multicol-1/multicol-count-computed-003-ref.xht
-fuzzy-if(winWidget||OSX||gtkWidget,112,861) fails-if(Android) HTTP(../../..) == css-multicol-1/multicol-count-computed-004.xht css-multicol-1/multicol-count-computed-004-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-computed-005.xht css-multicol-1/multicol-count-computed-003-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-count-large-001.xht css-multicol-1/multicol-count-large-ref.xht
-fuzzy(255,132) HTTP(../../..) == css-multicol-1/multicol-count-large-002.xht css-multicol-1/multicol-count-large-2-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-count-negative-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-count-negative-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-count-non-integer-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-count-non-integer-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-count-non-integer-003.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-fill-000.xht css-multicol-1/multicol-fill-000-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-fill-001.xht css-multicol-1/multicol-fill-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-fill-auto-001.xht css-multicol-1/multicol-fill-auto-001-ref.xht
-fuzzy(116,80) HTTP(../../..) == css-multicol-1/multicol-fill-auto-002.xht css-multicol-1/multicol-fill-auto-002-ref.xht
-fuzzy(116,3270) HTTP(../../..) == css-multicol-1/multicol-fill-auto-003.xht css-multicol-1/multicol-fill-auto-003-ref.xht
+fails == css-multicol-1/multicol-break-000.xht css-multicol-1/multicol-break-000-ref.xht
+fails == css-multicol-1/multicol-break-001.xht css-multicol-1/multicol-break-001-ref.xht
+fuzzy(116,1008) == css-multicol-1/multicol-clip-001.xht css-multicol-1/multicol-clip-001-ref.xht
+fuzzy(116,702) == css-multicol-1/multicol-clip-002.xht css-multicol-1/multicol-clip-002-ref.xht
+fuzzy(116,467) == css-multicol-1/multicol-collapsing-001.xht css-multicol-1/multicol-collapsing-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-001.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-002.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-003.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-004.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-005.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-006.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-columns-007.xht css-multicol-1/multicol-columns-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-columns-invalid-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-columns-invalid-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-columns-toolong-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(116,530) == css-multicol-1/multicol-containing-001.xht css-multicol-1/multicol-containing-001-ref.xht
+fuzzy(215,241) == css-multicol-1/multicol-containing-002.xht css-multicol-1/multicol-containing-002-ref.xht
+fuzzy(87,180) == css-multicol-1/multicol-count-001.xht css-multicol-1/multicol-columns-001-ref.xht
+fails == css-multicol-1/multicol-count-002.xht css-multicol-1/multicol-count-002-ref.xht
+fails == css-multicol-1/multicol-count-computed-001.xht css-multicol-1/multicol-count-computed-ref.xht
+fails == css-multicol-1/multicol-count-computed-002.xht css-multicol-1/multicol-count-computed-2-ref.xht
+fails == css-multicol-1/multicol-count-computed-003.xht css-multicol-1/multicol-count-computed-003-ref.xht
+fuzzy-if(winWidget||OSX||gtkWidget,112,861) fails-if(Android) == css-multicol-1/multicol-count-computed-004.xht css-multicol-1/multicol-count-computed-004-ref.xht
+fails == css-multicol-1/multicol-count-computed-005.xht css-multicol-1/multicol-count-computed-003-ref.xht
+fails == css-multicol-1/multicol-count-large-001.xht css-multicol-1/multicol-count-large-ref.xht
+fuzzy(255,132) == css-multicol-1/multicol-count-large-002.xht css-multicol-1/multicol-count-large-2-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-count-negative-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-count-negative-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-count-non-integer-001.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-count-non-integer-002.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-count-non-integer-003.xht css-multicol-1/multicol-columns-invalid-001-ref.xht
+== css-multicol-1/multicol-fill-000.xht css-multicol-1/multicol-fill-000-ref.xht
+== css-multicol-1/multicol-fill-001.xht css-multicol-1/multicol-fill-001-ref.xht
+== css-multicol-1/multicol-fill-auto-001.xht css-multicol-1/multicol-fill-auto-001-ref.xht
+fuzzy(116,80) == css-multicol-1/multicol-fill-auto-002.xht css-multicol-1/multicol-fill-auto-002-ref.xht
+fuzzy(116,3270) == css-multicol-1/multicol-fill-auto-003.xht css-multicol-1/multicol-fill-auto-003-ref.xht
 fails == css-multicol-1/multicol-fill-auto-block-children-001.xht css-multicol-1/multicol-fill-auto-block-children-ref.xht
 fails == css-multicol-1/multicol-fill-auto-block-children-002.xht css-multicol-1/multicol-fill-auto-block-children-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-fill-auto.xht css-multicol-1/multicol-fill-ref.xht
-fuzzy(116,80) HTTP(../../..) == css-multicol-1/multicol-fill-balance-001.xht css-multicol-1/multicol-fill-balance-001-ref.xht
-fuzzy(116,821) HTTP(../../..) == css-multicol-1/multicol-gap-000.xht css-multicol-1/multicol-gap-000-ref.xht
-fuzzy(255,290) HTTP(../../..) == css-multicol-1/multicol-gap-001.xht css-multicol-1/multicol-gap-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-gap-002.xht css-multicol-1/multicol-gap-002-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-gap-003.xht css-multicol-1/multicol-gap-002-ref.xht
-fuzzy(107,1823) HTTP(../../..) == css-multicol-1/multicol-gap-fraction-001.xht css-multicol-1/multicol-gap-fraction-001-ref.xht
-fuzzy-if(winWidget||OSX||gtkWidget,204,1048) fuzzy-if(skiaContent,208,1048) fails-if(Android) HTTP(../../..) == css-multicol-1/multicol-gap-large-001.xht css-multicol-1/multicol-gap-large-001-ref.xht
-fuzzy(225,920) HTTP(../../..) == css-multicol-1/multicol-gap-large-002.xht css-multicol-1/multicol-gap-large-002-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-gap-negative-001.xht css-multicol-1/multicol-gap-002-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-height-001.xht css-multicol-1/multicol-height-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-height-block-child-001.xht css-multicol-1/multicol-height-block-child-001-ref.xht
-fuzzy(255,3762) HTTP(../../..) == css-multicol-1/multicol-inherit-001.xht css-multicol-1/multicol-inherit-001-ref.xht
-fuzzy(116,1893) HTTP(../../..) == css-multicol-1/multicol-inherit-002.xht css-multicol-1/multicol-inherit-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-inherit-003.xht css-multicol-1/multicol-inherit-3-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-inherit-004.xht css-multicol-1/multicol-inherit-4-ref.xht
-fuzzy(96,264) HTTP(../../..) == css-multicol-1/multicol-list-item-001.xht css-multicol-1/multicol-list-item-001-ref.xht
-fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-001.xht reference/ref-filled-green-100px-square.xht
-fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-002.xht reference/ref-filled-green-100px-square.xht
-fuzzy(243,3322) fuzzy-if(skiaContent,244,3322) HTTP(../../..) == css-multicol-1/multicol-margin-child-001.xht css-multicol-1/multicol-margin-child-001-ref.xht
-fuzzy(255,4008) HTTP(../../..) == css-multicol-1/multicol-nested-002.xht css-multicol-1/multicol-nested-002-ref.xht
-fuzzy(255,4109) HTTP(../../..) == css-multicol-1/multicol-nested-005.xht css-multicol-1/multicol-nested-005-ref.xht
-fuzzy(225,13600) HTTP(../../..) == css-multicol-1/multicol-nested-column-rule-001.xht css-multicol-1/multicol-nested-column-rule-001-ref.xht
-fuzzy(204,2463) fuzzy-if(skiaContent,208,2463) HTTP(../../..) == css-multicol-1/multicol-nested-margin-001.xht css-multicol-1/multicol-nested-margin-001-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-nested-margin-002.xht css-multicol-1/multicol-nested-margin-002-ref.xht
-fuzzy(204,2371) fuzzy-if(skiaContent,208,2371) HTTP(../../..) == css-multicol-1/multicol-nested-margin-003.xht css-multicol-1/multicol-nested-margin-003-ref.xht
-fuzzy(225,2529) HTTP(../../..) == css-multicol-1/multicol-nested-margin-004.xht css-multicol-1/multicol-nested-margin-004-ref.xht
-fuzzy(225,2529) HTTP(../../..) == css-multicol-1/multicol-nested-margin-005.xht css-multicol-1/multicol-nested-margin-004-ref.xht
-fuzzy(116,142) HTTP(../../..) == css-multicol-1/multicol-overflow-000.xht css-multicol-1/multicol-overflow-000-ref.xht
-fuzzy(204,1844) fuzzy-if(skiaContent,208,1844) HTTP(../../..) == css-multicol-1/multicol-overflowing-001.xht css-multicol-1/multicol-overflowing-001-ref.xht
-fuzzy-if(OSX,61,2) fuzzy-if(skiaContent,64,2) HTTP(../../..) == css-multicol-1/multicol-reduce-000.xht css-multicol-1/multicol-reduce-000-ref.xht
-fuzzy-if(OSX,8,20) HTTP(../../..) == css-multicol-1/multicol-rule-000.xht css-multicol-1/multicol-rule-000-ref.xht
-fuzzy(116,1584) HTTP(../../..) == css-multicol-1/multicol-rule-001.xht css-multicol-1/multicol-rule-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-rule-002.xht css-multicol-1/multicol-rule-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-rule-003.xht css-multicol-1/multicol-rule-003-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-004.xht css-multicol-1/multicol-rule-004-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-rule-color-001.xht css-multicol-1/multicol-rule-color-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-color-inherit-001.xht css-multicol-1/multicol-rule-color-inherit-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-color-inherit-002.xht css-multicol-1/multicol-rule-color-inherit-001-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-dashed-000.xht css-multicol-1/multicol-rule-dashed-000-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-dotted-000.xht css-multicol-1/multicol-rule-dotted-000-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-double-000.xht css-multicol-1/multicol-rule-double-000-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-rule-fraction-001.xht css-multicol-1/multicol-rule-fraction-001-ref.xht
-fails-if(OSX||winWidget) HTTP(../../..) == css-multicol-1/multicol-rule-fraction-002.xht css-multicol-1/multicol-rule-fraction-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-rule-fraction-003.xht css-multicol-1/multicol-rule-fraction-3-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-groove-000.xht css-multicol-1/multicol-rule-groove-000-ref.xht
-fuzzy(94,256) HTTP(../../..) == css-multicol-1/multicol-rule-hidden-000.xht css-multicol-1/multicol-rule-hidden-000-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-inset-000.xht css-multicol-1/multicol-rule-ridge-000-ref.xht
-fuzzy(255,2808) HTTP(../../..) == css-multicol-1/multicol-rule-large-001.xht css-multicol-1/multicol-rule-large-001-ref.xht
-fuzzy(94,256) HTTP(../../..) == css-multicol-1/multicol-rule-none-000.xht css-multicol-1/multicol-rule-hidden-000-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-outset-000.xht css-multicol-1/multicol-rule-groove-000-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-percent-001.xht css-multicol-1/multicol-containing-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-rule-px-001.xht css-multicol-1/multicol-rule-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-ridge-000.xht css-multicol-1/multicol-rule-ridge-000-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-samelength-001.xht css-multicol-1/multicol-rule-samelength-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-shorthand-001.xht css-multicol-1/multicol-rule-samelength-001-ref.xht
-fuzzy(106,354) HTTP(../../..) == css-multicol-1/multicol-rule-solid-000.xht css-multicol-1/multicol-rule-solid-000-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-rule-stacking-001.xht css-multicol-1/multicol-rule-stacking-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-style-groove-001.xht css-multicol-1/multicol-rule-style-groove-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-style-inset-001.xht css-multicol-1/multicol-rule-style-ridge-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-style-outset-001.xht css-multicol-1/multicol-rule-style-groove-001-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-rule-style-ridge-001.xht css-multicol-1/multicol-rule-style-ridge-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-shorthand-001.xht css-multicol-1/multicol-rule-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-000.xht css-multicol-1/multicol-span-000-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-001.xht css-multicol-1/multicol-span-all-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-002.xht css-multicol-1/multicol-span-all-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-003.xht css-multicol-1/multicol-count-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-block-sibling-003.xht css-multicol-1/multicol-span-all-block-sibling-3-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-child-001.xht css-multicol-1/multicol-span-all-child-001-ref.xht
+fails == css-multicol-1/multicol-fill-auto.xht css-multicol-1/multicol-fill-ref.xht
+fuzzy(116,80) == css-multicol-1/multicol-fill-balance-001.xht css-multicol-1/multicol-fill-balance-001-ref.xht
+fuzzy(116,821) == css-multicol-1/multicol-gap-000.xht css-multicol-1/multicol-gap-000-ref.xht
+fuzzy(255,290) == css-multicol-1/multicol-gap-001.xht css-multicol-1/multicol-gap-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-gap-002.xht css-multicol-1/multicol-gap-002-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-gap-003.xht css-multicol-1/multicol-gap-002-ref.xht
+fuzzy(107,1823) == css-multicol-1/multicol-gap-fraction-001.xht css-multicol-1/multicol-gap-fraction-001-ref.xht
+fuzzy-if(winWidget||OSX||gtkWidget,204,1048) fuzzy-if(skiaContent,208,1048) fails-if(Android) == css-multicol-1/multicol-gap-large-001.xht css-multicol-1/multicol-gap-large-001-ref.xht
+fuzzy(225,920) == css-multicol-1/multicol-gap-large-002.xht css-multicol-1/multicol-gap-large-002-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-gap-negative-001.xht css-multicol-1/multicol-gap-002-ref.xht
+== css-multicol-1/multicol-height-001.xht css-multicol-1/multicol-height-001-ref.xht
+fails == css-multicol-1/multicol-height-block-child-001.xht css-multicol-1/multicol-height-block-child-001-ref.xht
+fuzzy(255,3762) == css-multicol-1/multicol-inherit-001.xht css-multicol-1/multicol-inherit-001-ref.xht
+fuzzy(116,1893) == css-multicol-1/multicol-inherit-002.xht css-multicol-1/multicol-inherit-002-ref.xht
+fails == css-multicol-1/multicol-inherit-003.xht css-multicol-1/multicol-inherit-3-ref.xht
+fails == css-multicol-1/multicol-inherit-004.xht css-multicol-1/multicol-inherit-4-ref.xht
+fuzzy(96,264) == css-multicol-1/multicol-list-item-001.xht css-multicol-1/multicol-list-item-001-ref.xht
+fuzzy(73,1200) == css-multicol-1/multicol-margin-001.xht reference/ref-filled-green-100px-square.xht
+fuzzy(73,1200) == css-multicol-1/multicol-margin-002.xht reference/ref-filled-green-100px-square.xht
+fuzzy(243,3322) fuzzy-if(skiaContent,244,3322) == css-multicol-1/multicol-margin-child-001.xht css-multicol-1/multicol-margin-child-001-ref.xht
+fuzzy(255,4008) == css-multicol-1/multicol-nested-002.xht css-multicol-1/multicol-nested-002-ref.xht
+fuzzy(255,4109) == css-multicol-1/multicol-nested-005.xht css-multicol-1/multicol-nested-005-ref.xht
+fuzzy(225,13600) == css-multicol-1/multicol-nested-column-rule-001.xht css-multicol-1/multicol-nested-column-rule-001-ref.xht
+fuzzy(204,2463) fuzzy-if(skiaContent,208,2463) == css-multicol-1/multicol-nested-margin-001.xht css-multicol-1/multicol-nested-margin-001-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-nested-margin-002.xht css-multicol-1/multicol-nested-margin-002-ref.xht
+fuzzy(204,2371) fuzzy-if(skiaContent,208,2371) == css-multicol-1/multicol-nested-margin-003.xht css-multicol-1/multicol-nested-margin-003-ref.xht
+fuzzy(225,2529) == css-multicol-1/multicol-nested-margin-004.xht css-multicol-1/multicol-nested-margin-004-ref.xht
+fuzzy(225,2529) == css-multicol-1/multicol-nested-margin-005.xht css-multicol-1/multicol-nested-margin-004-ref.xht
+fuzzy(116,142) == css-multicol-1/multicol-overflow-000.xht css-multicol-1/multicol-overflow-000-ref.xht
+fuzzy(204,1844) fuzzy-if(skiaContent,208,1844) == css-multicol-1/multicol-overflowing-001.xht css-multicol-1/multicol-overflowing-001-ref.xht
+fuzzy-if(OSX,61,2) fuzzy-if(skiaContent,64,2) == css-multicol-1/multicol-reduce-000.xht css-multicol-1/multicol-reduce-000-ref.xht
+fuzzy-if(OSX,8,20) == css-multicol-1/multicol-rule-000.xht css-multicol-1/multicol-rule-000-ref.xht
+fuzzy(116,1584) == css-multicol-1/multicol-rule-001.xht css-multicol-1/multicol-rule-001-ref.xht
+fails == css-multicol-1/multicol-rule-002.xht css-multicol-1/multicol-rule-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-rule-003.xht css-multicol-1/multicol-rule-003-ref.xht
+== css-multicol-1/multicol-rule-004.xht css-multicol-1/multicol-rule-004-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-rule-color-001.xht css-multicol-1/multicol-rule-color-001-ref.xht
+== css-multicol-1/multicol-rule-color-inherit-001.xht css-multicol-1/multicol-rule-color-inherit-001-ref.xht
+== css-multicol-1/multicol-rule-color-inherit-002.xht css-multicol-1/multicol-rule-color-inherit-001-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-dashed-000.xht css-multicol-1/multicol-rule-dashed-000-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-dotted-000.xht css-multicol-1/multicol-rule-dotted-000-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-double-000.xht css-multicol-1/multicol-rule-double-000-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-rule-fraction-001.xht css-multicol-1/multicol-rule-fraction-001-ref.xht
+fails-if(OSX||winWidget) == css-multicol-1/multicol-rule-fraction-002.xht css-multicol-1/multicol-rule-fraction-002-ref.xht
+fails == css-multicol-1/multicol-rule-fraction-003.xht css-multicol-1/multicol-rule-fraction-3-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-groove-000.xht css-multicol-1/multicol-rule-groove-000-ref.xht
+fuzzy(94,256) == css-multicol-1/multicol-rule-hidden-000.xht css-multicol-1/multicol-rule-hidden-000-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-inset-000.xht css-multicol-1/multicol-rule-ridge-000-ref.xht
+fuzzy(255,2808) == css-multicol-1/multicol-rule-large-001.xht css-multicol-1/multicol-rule-large-001-ref.xht
+fuzzy(94,256) == css-multicol-1/multicol-rule-none-000.xht css-multicol-1/multicol-rule-hidden-000-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-outset-000.xht css-multicol-1/multicol-rule-groove-000-ref.xht
+== css-multicol-1/multicol-rule-percent-001.xht css-multicol-1/multicol-containing-002-ref.xht
+fails == css-multicol-1/multicol-rule-px-001.xht css-multicol-1/multicol-rule-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-ridge-000.xht css-multicol-1/multicol-rule-ridge-000-ref.xht
+== css-multicol-1/multicol-rule-samelength-001.xht css-multicol-1/multicol-rule-samelength-001-ref.xht
+== css-multicol-1/multicol-rule-shorthand-001.xht css-multicol-1/multicol-rule-samelength-001-ref.xht
+fuzzy(106,354) == css-multicol-1/multicol-rule-solid-000.xht css-multicol-1/multicol-rule-solid-000-ref.xht
+fails == css-multicol-1/multicol-rule-stacking-001.xht css-multicol-1/multicol-rule-stacking-ref.xht
+== css-multicol-1/multicol-rule-style-groove-001.xht css-multicol-1/multicol-rule-style-groove-001-ref.xht
+== css-multicol-1/multicol-rule-style-inset-001.xht css-multicol-1/multicol-rule-style-ridge-001-ref.xht
+== css-multicol-1/multicol-rule-style-outset-001.xht css-multicol-1/multicol-rule-style-groove-001-ref.xht
+== css-multicol-1/multicol-rule-style-ridge-001.xht css-multicol-1/multicol-rule-style-ridge-001-ref.xht
+fails == css-multicol-1/multicol-shorthand-001.xht css-multicol-1/multicol-rule-ref.xht
+fails == css-multicol-1/multicol-span-000.xht css-multicol-1/multicol-span-000-ref.xht
+fails == css-multicol-1/multicol-span-all-001.xht css-multicol-1/multicol-span-all-001-ref.xht
+fails == css-multicol-1/multicol-span-all-002.xht css-multicol-1/multicol-span-all-002-ref.xht
+fails == css-multicol-1/multicol-span-all-003.xht css-multicol-1/multicol-count-002-ref.xht
+fails == css-multicol-1/multicol-span-all-block-sibling-003.xht css-multicol-1/multicol-span-all-block-sibling-3-ref.xht
+fails == css-multicol-1/multicol-span-all-child-001.xht css-multicol-1/multicol-span-all-child-001-ref.xht
 fails-if(OSX||winWidget) == css-multicol-1/multicol-span-all-child-002.xht css-multicol-1/multicol-span-all-child-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-001.xht css-multicol-1/multicol-span-all-margin-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-002.xht css-multicol-1/multicol-span-all-margin-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-bottom-001.xht css-multicol-1/multicol-span-all-margin-bottom-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-nested-001.xht css-multicol-1/multicol-span-all-margin-nested-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-nested-002.xht css-multicol-1/multicol-span-all-margin-nested-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-nested-003.xht css-multicol-1/multicol-span-all-margin-nested-3-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-all-margin-nested-firstchild-001.xht css-multicol-1/multicol-span-all-margin-nested-firstchild-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-float-001.xht css-multicol-1/multicol-span-float-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-span-none-001.xht css-multicol-1/multicol-span-none-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-table-cell-001.xht css-multicol-1/multicol-table-cell-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-table-cell-height-001.xht css-multicol-1/multicol-table-cell-height-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-table-cell-height-002.xht css-multicol-1/multicol-table-cell-height-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-table-cell-vertical-align-001.xht css-multicol-1/multicol-table-cell-vertical-align-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-width-001.xht css-multicol-1/multicol-width-001-ref.xht
-fuzzy(204,930) fuzzy-if(skiaContent,208,930) HTTP(../../..) == css-multicol-1/multicol-width-002.xht css-multicol-1/multicol-width-002-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-width-003.xht css-multicol-1/multicol-width-002-ref.xht
-HTTP(../../..) == css-multicol-1/multicol-width-count-001.xht css-multicol-1/multicol-width-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-width-count-002.xht css-multicol-1/multicol-count-002-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-001.xht css-multicol-1/multicol-span-all-margin-001-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-002.xht css-multicol-1/multicol-span-all-margin-002-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-bottom-001.xht css-multicol-1/multicol-span-all-margin-bottom-001-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-nested-001.xht css-multicol-1/multicol-span-all-margin-nested-001-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-nested-002.xht css-multicol-1/multicol-span-all-margin-nested-001-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-nested-003.xht css-multicol-1/multicol-span-all-margin-nested-3-ref.xht
+fails == css-multicol-1/multicol-span-all-margin-nested-firstchild-001.xht css-multicol-1/multicol-span-all-margin-nested-firstchild-ref.xht
+fails == css-multicol-1/multicol-span-float-001.xht css-multicol-1/multicol-span-float-001-ref.xht
+fails == css-multicol-1/multicol-span-none-001.xht css-multicol-1/multicol-span-none-001-ref.xht
+fails == css-multicol-1/multicol-table-cell-001.xht css-multicol-1/multicol-table-cell-001-ref.xht
+fails == css-multicol-1/multicol-table-cell-height-001.xht css-multicol-1/multicol-table-cell-height-001-ref.xht
+fails == css-multicol-1/multicol-table-cell-height-002.xht css-multicol-1/multicol-table-cell-height-001-ref.xht
+fails == css-multicol-1/multicol-table-cell-vertical-align-001.xht css-multicol-1/multicol-table-cell-vertical-align-ref.xht
+== css-multicol-1/multicol-width-001.xht css-multicol-1/multicol-width-001-ref.xht
+fuzzy(204,930) fuzzy-if(skiaContent,208,930) == css-multicol-1/multicol-width-002.xht css-multicol-1/multicol-width-002-ref.xht
+== css-multicol-1/multicol-width-003.xht css-multicol-1/multicol-width-002-ref.xht
+== css-multicol-1/multicol-width-count-001.xht css-multicol-1/multicol-width-001-ref.xht
+fails == css-multicol-1/multicol-width-count-002.xht css-multicol-1/multicol-count-002-ref.xht
 fails == css-multicol-1/multicol-width-ems-001.xht css-multicol-1/multicol-width-ems-ref.xht
-fuzzy(225,1060) HTTP(../../..) == css-multicol-1/multicol-width-invalid-001.xht css-multicol-1/multicol-width-invalid-001-ref.xht
-fuzzy(225,1060) HTTP(../../..) == css-multicol-1/multicol-width-large-001.xht css-multicol-1/multicol-width-invalid-001-ref.xht
-fuzzy(225,1060) HTTP(../../..) == css-multicol-1/multicol-width-large-002.xht css-multicol-1/multicol-width-invalid-001-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-width-negative-001.xht css-multicol-1/multicol-count-002-ref.xht
-fails HTTP(../../..) == css-multicol-1/multicol-width-small-001.xht css-multicol-1/multicol-width-small-001-ref.xht
+fuzzy(225,1060) == css-multicol-1/multicol-width-invalid-001.xht css-multicol-1/multicol-width-invalid-001-ref.xht
+fuzzy(225,1060) == css-multicol-1/multicol-width-large-001.xht css-multicol-1/multicol-width-invalid-001-ref.xht
+fuzzy(225,1060) == css-multicol-1/multicol-width-large-002.xht css-multicol-1/multicol-width-invalid-001-ref.xht
+fails == css-multicol-1/multicol-width-negative-001.xht css-multicol-1/multicol-count-002-ref.xht
+fails == css-multicol-1/multicol-width-small-001.xht css-multicol-1/multicol-width-small-001-ref.xht
 fails == css-multicol-1/multicol-zero-height-001.xht css-multicol-1/multicol-zero-height-001-ref.xht
 == css-namespaces-3/prefix-001.xml css-namespaces-3/reftest/ref-lime-1.xml
 == css-namespaces-3/prefix-002.xml css-namespaces-3/reftest/ref-lime-1.xml
 == css-namespaces-3/prefix-003.xml css-namespaces-3/reftest/ref-lime-1-generic.xml
 == css-namespaces-3/prefix-004.xml css-namespaces-3/reftest/ref-lime-2-generic.xml
 == css-namespaces-3/prefix-005.xml css-namespaces-3/reftest/ref-lime-2-generic.xml
 == css-namespaces-3/prefix-006.xml css-namespaces-3/reftest/ref-lime-2.xml
 == css-namespaces-3/scope-001.xml css-namespaces-3/reftest/ref-lime-1.xml
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -1449,16 +1449,49 @@ Declaration::GetPropertyValueInternal(
           colsItem = colsItem->mNext; // skip <line-names>
         }
         aValue.AppendLiteral(" / ");
         AppendValueToString(eCSSProperty_grid_template_columns,
                             aValue, aSerialization);
       }
       break;
     }
+    case eCSSProperty_place_content:
+    case eCSSProperty_place_items:
+    case eCSSProperty_place_self: {
+      const nsCSSPropertyID* subprops =
+        nsCSSProps::SubpropertyEntryFor(aProperty);
+      MOZ_ASSERT(subprops[2] == eCSSProperty_UNKNOWN,
+                 "must have exactly two subproperties");
+      auto IsSingleValue = [] (const nsCSSValue& aValue) {
+        switch (aValue.GetUnit()) {
+          case eCSSUnit_Auto:
+          case eCSSUnit_Inherit:
+          case eCSSUnit_Initial:
+          case eCSSUnit_Unset:
+            return true;
+          case eCSSUnit_Enumerated:
+            // return false if there is a fallback value or <overflow-position>
+            return aValue.GetIntValue() <= NS_STYLE_JUSTIFY_SPACE_EVENLY;
+          default:
+            MOZ_ASSERT_UNREACHABLE("Unexpected unit for CSS Align property val");
+            return false;
+        }
+      };
+      // Each value must be a single value (i.e. no fallback value and no
+      // <overflow-position>), otherwise it can't be represented as a shorthand
+      // value. ('first|last baseline' counts as a single value)
+      const nsCSSValue* align = data->ValueFor(subprops[0]);
+      const nsCSSValue* justify = data->ValueFor(subprops[1]);
+      if (!align || !IsSingleValue(*align) ||
+          !justify || !IsSingleValue(*justify)) {
+        return; // Not serializable, bail.
+      }
+      MOZ_FALLTHROUGH;
+    }
     case eCSSProperty_grid_gap: {
       const nsCSSPropertyID* subprops =
         nsCSSProps::SubpropertyEntryFor(aProperty);
       MOZ_ASSERT(subprops[2] == eCSSProperty_UNKNOWN,
                  "must have exactly two subproperties");
 
       nsAutoString val1, val2;
       AppendValueToString(subprops[0], val1, aSerialization);
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1023,16 +1023,19 @@ protected:
   // parsing 'align/justify-items/self' from the css-align spec
   bool ParseAlignJustifyPosition(nsCSSValue& aResult,
                                  const KTableEntry aTable[]);
   bool ParseJustifyItems();
   bool ParseAlignItems();
   bool ParseAlignJustifySelf(nsCSSPropertyID aPropID);
   // parsing 'align/justify-content' from the css-align spec
   bool ParseAlignJustifyContent(nsCSSPropertyID aPropID);
+  bool ParsePlaceContent();
+  bool ParsePlaceItems();
+  bool ParsePlaceSelf();
 
   // for 'clip' and '-moz-image-region'
   bool ParseRect(nsCSSPropertyID aPropID);
   bool ParseColumns();
   bool ParseContain(nsCSSValue& aValue);
   bool ParseContent();
   bool ParseCounterData(nsCSSPropertyID aPropID);
   bool ParseCursor();
@@ -10200,16 +10203,97 @@ CSSParserImpl::ParseAlignJustifyContent(
                           eCSSUnit_Enumerated);
       }
     }
   }
   AppendValue(aPropID, value);
   return true;
 }
 
+// place-content: [ normal | <baseline-position> | <content-distribution> |
+//                  <content-position> ]{1,2}
+bool
+CSSParserImpl::ParsePlaceContent()
+{
+  nsCSSValue first;
+  if (ParseSingleTokenVariant(first, VARIANT_INHERIT, nullptr)) {
+    AppendValue(eCSSProperty_align_content, first);
+    AppendValue(eCSSProperty_justify_content, first);
+    return true;
+  }
+  if (!ParseAlignEnum(first, nsCSSProps::kAlignNormalBaseline) &&
+      !ParseEnum(first, nsCSSProps::kAlignContentDistribution) &&
+      !ParseEnum(first, nsCSSProps::kAlignContentPosition)) {
+    return false;
+  }
+  AppendValue(eCSSProperty_align_content, first);
+  nsCSSValue second;
+  if (!ParseAlignEnum(second, nsCSSProps::kAlignNormalBaseline) &&
+      !ParseEnum(second, nsCSSProps::kAlignContentDistribution) &&
+      !ParseEnum(second, nsCSSProps::kAlignContentPosition)) {
+    AppendValue(eCSSProperty_justify_content, first);
+  } else {
+    AppendValue(eCSSProperty_justify_content, second);
+  }
+  return true;
+}
+
+// place-items:  <x> [ auto | <x> ]?
+// <x> = [ normal | stretch | <baseline-position> | <self-position> ]
+bool
+CSSParserImpl::ParsePlaceItems()
+{
+  nsCSSValue first;
+  if (ParseSingleTokenVariant(first, VARIANT_INHERIT, nullptr)) {
+    AppendValue(eCSSProperty_align_items, first);
+    AppendValue(eCSSProperty_justify_items, first);
+    return true;
+  }
+  if (!ParseAlignEnum(first, nsCSSProps::kAlignNormalStretchBaseline) &&
+      !ParseEnum(first, nsCSSProps::kAlignSelfPosition)) {
+    return false;
+  }
+  AppendValue(eCSSProperty_align_items, first);
+  nsCSSValue second;
+  // Note: 'auto' is valid for justify-items, but not align-items.
+  if (!ParseAlignEnum(second, nsCSSProps::kAlignAutoNormalStretchBaseline) &&
+      !ParseEnum(second, nsCSSProps::kAlignSelfPosition)) {
+    AppendValue(eCSSProperty_justify_items, first);
+  } else {
+    AppendValue(eCSSProperty_justify_items, second);
+  }
+  return true;
+}
+
+// place-self: [ auto | normal | stretch | <baseline-position> |
+//               <self-position> ]{1,2}
+bool
+CSSParserImpl::ParsePlaceSelf()
+{
+  nsCSSValue first;
+  if (ParseSingleTokenVariant(first, VARIANT_INHERIT, nullptr)) {
+    AppendValue(eCSSProperty_align_self, first);
+    AppendValue(eCSSProperty_justify_self, first);
+    return true;
+  }
+  if (!ParseAlignEnum(first, nsCSSProps::kAlignAutoNormalStretchBaseline) &&
+      !ParseEnum(first, nsCSSProps::kAlignSelfPosition)) {
+    return false;
+  }
+  AppendValue(eCSSProperty_align_self, first);
+  nsCSSValue second;
+  if (!ParseAlignEnum(second, nsCSSProps::kAlignAutoNormalStretchBaseline) &&
+      !ParseEnum(second, nsCSSProps::kAlignSelfPosition)) {
+    AppendValue(eCSSProperty_justify_self, first);
+  } else {
+    AppendValue(eCSSProperty_justify_self, second);
+  }
+  return true;
+}
+
 // <color-stop> : <color> [ <percentage> | <length> ]?
 bool
 CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient)
 {
   nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement();
   CSSParseResult result = ParseVariant(stop->mColor, VARIANT_COLOR, nullptr);
   if (result == CSSParseResult::Error) {
     return false;
@@ -11716,16 +11800,22 @@ CSSParserImpl::ParseProperty(nsCSSProper
 
   return result;
 }
 
 bool
 CSSParserImpl::ParsePropertyByFunction(nsCSSPropertyID aPropID)
 {
   switch (aPropID) {  // handle shorthand or multiple properties
+  case eCSSProperty_place_content:
+    return ParsePlaceContent();
+  case eCSSProperty_place_items:
+    return ParsePlaceItems();
+  case eCSSProperty_place_self:
+    return ParsePlaceSelf();
   case eCSSProperty_background:
     return ParseImageLayers(nsStyleImageLayers::kBackgroundLayerTable);
   case eCSSProperty_background_repeat:
     return ParseImageLayerRepeat(eCSSProperty_background_repeat);
   case eCSSProperty_background_position:
     return ParseImageLayerPosition(nsStyleImageLayers::kBackgroundLayerTable);
   case eCSSProperty_background_position_x:
   case eCSSProperty_background_position_y:
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3452,16 +3452,34 @@ CSS_PROP_DISPLAY(
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_STORES_CALC |
         CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
     "",
     0,
     kImageLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
+CSS_PROP_SHORTHAND(
+    place-content,
+    place_content,
+    PlaceContent,
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "")
+CSS_PROP_SHORTHAND(
+    place-items,
+    place_items,
+    PlaceItems,
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "")
+CSS_PROP_SHORTHAND(
+    place-self,
+    place_self,
+    PlaceSelf,
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "")
 CSS_PROP_USERINTERFACE(
     pointer-events,
     pointer_events,
     PointerEvents,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
     "",
     VARIANT_HK,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -3001,16 +3001,34 @@ static const nsCSSPropertyID gBorderImag
 
 static const nsCSSPropertyID gMarkerSubpropTable[] = {
   eCSSProperty_marker_start,
   eCSSProperty_marker_mid,
   eCSSProperty_marker_end,
   eCSSProperty_UNKNOWN
 };
 
+static const nsCSSPropertyID gPlaceContentSubpropTable[] = {
+  eCSSProperty_align_content,
+  eCSSProperty_justify_content,
+  eCSSProperty_UNKNOWN
+};
+
+static const nsCSSPropertyID gPlaceItemsSubpropTable[] = {
+  eCSSProperty_align_items,
+  eCSSProperty_justify_items,
+  eCSSProperty_UNKNOWN
+};
+
+static const nsCSSPropertyID gPlaceSelfSubpropTable[] = {
+  eCSSProperty_align_self,
+  eCSSProperty_justify_self,
+  eCSSProperty_UNKNOWN
+};
+
 // Subproperty tables for shorthands that are just aliases with
 // different parsing rules.
 static const nsCSSPropertyID gMozTransformSubpropTable[] = {
   eCSSProperty_transform,
   eCSSProperty_UNKNOWN
 };
 
 static const nsCSSPropertyID gScrollSnapTypeSubpropTable[] = {
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -303,8 +303,9 @@ skip-if = toolkit == 'android' #TIMED_OU
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_visited_pref.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_visited_reftests.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_webkit_device_pixel_ratio.html]
 [test_webkit_flex_display.html]
 [test_asyncopen2.html]
+[test_align_shorthand_serialization.html]
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -4555,16 +4555,51 @@ var gCSSProperties = {
     initial_values: [ "auto" ],
     other_values: [ "normal", "start", "end", "flex-start", "flex-end", "self-start",
                     "self-end", "center", "left", "right", "baseline", "first baseline",
                     "last baseline", "stretch", "left unsafe", "unsafe right",
                     "safe right", "center safe" ],
     invalid_values: [ "space-between", "abc", "30px", "none", "first", "last",
                       "legacy left", "right legacy", "baseline first", "baseline last" ]
   },
+  "place-content": {
+    domProp: "placeContent",
+    inherited: false,
+    type: CSS_TYPE_TRUE_SHORTHAND,
+    subproperties: [ "align-content", "justify-content" ],
+    initial_values: [ "normal" ],
+    other_values: [ "normal start", "end baseline", "end end",
+                    "space-between flex-end", "last baseline start",
+                    "space-evenly", "flex-start", "end", "left" ],
+    invalid_values: [ "none", "center safe", "unsafe start", "right / end" ]
+  },
+  "place-items": {
+    domProp: "placeItems",
+    inherited: false,
+    type: CSS_TYPE_TRUE_SHORTHAND,
+    subproperties: [ "align-items", "justify-items" ],
+    initial_values: [ "normal" ],
+    other_values: [ "normal center", "end baseline", "end auto",
+                    "end", "right", "baseline", "start last baseline",
+                    "left flex-end", "last baseline start", "stretch" ],
+    invalid_values: [ "space-between", "start space-evenly", "none", "end/end",
+                      "center safe", "auto start", "end legacy left" ]
+  },
+  "place-self": {
+    domProp: "placeSelf",
+    inherited: false,
+    type: CSS_TYPE_TRUE_SHORTHAND,
+    subproperties: [ "align-self", "justify-self" ],
+    initial_values: [ "auto" ],
+    other_values: [ "normal start", "end first baseline", "end auto",
+                    "end", "right", "normal", "baseline", "start baseline",
+                    "left self-end", "last baseline start", "stretch" ],
+    invalid_values: [ "space-between", "start space-evenly", "none", "end safe",
+                      "auto legacy left", "legacy left", "auto/auto" ]
+  },
   "flex": {
     domProp: "flex",
     inherited: false,
     type: CSS_TYPE_TRUE_SHORTHAND,
     subproperties: [
       "flex-grow",
       "flex-shrink",
       "flex-basis"
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_align_shorthand_serialization.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset=utf-8>
+  <title>Test serialization of CSS Align shorthand properties</title>
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <link rel='stylesheet' href='/resources/testharness.css'>
+</head>
+<body>
+
+<script>
+
+var initial_values = {
+    alignContent: "normal",
+    alignItems: "normal",
+    alignSelf: "auto",
+    justifyContent: "normal",
+    justifyItems: "auto",
+    justifySelf: "auto",
+};
+
+var place_content_test_cases = [
+    {
+        alignContent: "center",
+        shorthand: "center normal",
+    },
+    {
+        alignContent: "baseline right safe",
+        shorthand: "",
+    },
+    {
+        justifyContent: "start safe",
+        shorthand: "",
+    },
+    {
+        justifyContent: "space-evenly start",
+        shorthand: "",
+    },
+    {
+        alignContent: "start",
+        justifyContent: "end",
+        shorthand: "start end",
+    },
+];
+
+var place_items_test_cases = [
+    {
+        alignItems: "center",
+        shorthand: "center auto",
+    },
+    {
+        alignItems: "baseline",
+        shorthand: "baseline auto",
+    },
+    {
+        justifyItems: "start safe",
+        shorthand: "",
+    },
+    {
+        justifyItems: "stretch",
+        shorthand: "normal stretch",
+    },
+    {
+        justifyItems: "left legacy",
+        shorthand: "",
+    },
+    {
+        alignItems: "stretch",
+        justifyItems: "end",
+        shorthand: "stretch end",
+    },
+];
+
+var place_self_test_cases = [
+    {
+        alignSelf: "right",
+        shorthand: "right auto",
+    },
+    {
+        alignSelf: "self-end safe",
+        shorthand: "",
+    },
+    {
+        justifySelf: "unsafe start",
+        shorthand: "",
+    },
+    {
+        justifySelf: "last baseline start",
+        shorthand: "",
+    },
+    {
+        alignSelf: "baseline",
+        justifySelf: "last baseline",
+        shorthand: "baseline last baseline",
+    },
+];
+
+function run_tests(test_cases, shorthand, subproperties) {
+    test_cases.forEach(function(test_case) {
+        test(function() {
+            var element = document.createElement('div');
+            document.body.appendChild(element);
+            subproperties.forEach(function(longhand) {
+                element.style[longhand] = test_case[longhand] ||
+                                          initial_values[longhand];
+            });
+            assert_equals(element.style[shorthand], test_case.shorthand);
+        }, "test shorthand serialization " + JSON.stringify(test_case));
+    });
+}
+
+run_tests(place_content_test_cases, "placeContent", [
+    "alignContent", "justifyContent"]);
+run_tests(place_items_test_cases, "placeItems", [
+    "alignItems", "justifyItems"]);
+run_tests(place_self_test_cases, "placeSelf", [
+    "alignSelf", "justifySelf"]);
+
+</script>
+</body>
+</html>
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -24,17 +24,19 @@ user_pref("extensions.systemAddon.update
 user_pref("extensions.getAddons.cache.enabled", false);
 // Disable blocklist updates so we don't have them reported as leaks
 user_pref("extensions.blocklist.enabled", false);
 // Make url-classifier updates so rare that they won't affect tests
 user_pref("urlclassifier.updateinterval", 172800);
 // Disable downscale-during-decode, since it makes reftests more difficult.
 user_pref("image.downscale-during-decode.enabled", false);
 // Checking whether two files are the same is slow on Windows.
-// Setting this pref makes tests run much faster there.
+// Setting this pref makes tests run much faster there. Reftests also
+// rely on this to load downloadable fonts (which are restricted to same
+// origin policy by default) from outside their directory.
 user_pref("security.fileuri.strict_origin_policy", false);
 // Disable the thumbnailing service
 user_pref("browser.pagethumbnails.capturing_disabled", true);
 // Since our tests are 800px wide, set the assume-designed-for width of all
 // pages to be 800px (instead of the default of 980px). This ensures that
 // in our 800px window we don't zoom out by default to try to fit the
 // assumed 980px content.
 user_pref("browser.viewport.desktopWidth", 800);
--- a/python/compare-locales/compare_locales/__init__.py
+++ b/python/compare-locales/compare_locales/__init__.py
@@ -1,1 +1,1 @@
-version = "1.2.1"
+version = "1.1"
--- a/python/compare-locales/compare_locales/commands.py
+++ b/python/compare-locales/compare_locales/commands.py
@@ -1,155 +1,154 @@
 # 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/.
 
 'Commands exposed to commandlines'
 
 import logging
-from argparse import ArgumentParser
+from optparse import OptionParser, make_option
 
-from compare_locales import version
 from compare_locales.paths import EnumerateApp
 from compare_locales.compare import compareApp, compareDirs
 from compare_locales.webapps import compare_web_app
 
 
 class BaseCommand(object):
     """Base class for compare-locales commands.
     This handles command line parsing, and general sugar for setuptools
     entry_points.
     """
+    options = [
+        make_option('-v', '--verbose', action='count', dest='v', default=0,
+                    help='Make more noise'),
+        make_option('-q', '--quiet', action='count', dest='q', default=0,
+                    help='Make less noise'),
+        make_option('-m', '--merge',
+                    help='''Use this directory to stage merged files,
+use {ab_CD} to specify a different directory for each locale'''),
+    ]
+    data_option = make_option('--data', choices=['text', 'exhibit', 'json'],
+                              default='text',
+                              help='''Choose data and format (one of text,
+exhibit, json); text: (default) Show which files miss which strings, together
+with warnings and errors. Also prints a summary; json: Serialize the internal
+tree, useful for tools. Also always succeeds; exhibit: Serialize the summary
+data in a json useful for Exhibit
+''')
 
     def __init__(self):
         self.parser = None
 
     def get_parser(self):
-        """Get an ArgumentParser, with class docstring as description.
+        """Get an OptionParser, with class docstring as usage, and
+        self.options.
         """
-        parser = ArgumentParser(description=self.__doc__)
-        parser.add_argument('--version', action='version',
-                            version='%(prog)s ' + version)
-        parser.add_argument('-v', '--verbose', action='count', dest='v',
-                            default=0, help='Make more noise')
-        parser.add_argument('-q', '--quiet', action='count', dest='q',
-                            default=0, help='Make less noise')
-        parser.add_argument('-m', '--merge',
-                            help='''Use this directory to stage merged files,
-use {ab_CD} to specify a different directory for each locale''')
+        parser = OptionParser()
+        parser.set_usage(self.__doc__)
+        for option in self.options:
+            parser.add_option(option)
         return parser
 
-    def add_data_argument(self, parser):
-        parser.add_argument('--data', choices=['text', 'exhibit', 'json'],
-                            default='text',
-                            help='''Choose data and format (one of text,
-exhibit, json); text: (default) Show which files miss which strings, together
-with warnings and errors. Also prints a summary; json: Serialize the internal
-tree, useful for tools. Also always succeeds; exhibit: Serialize the summary
-data in a json useful for Exhibit
-''')
-
     @classmethod
     def call(cls):
         """Entry_point for setuptools.
         The actual command handling is done in the handle() method of the
         subclasses.
         """
         cmd = cls()
         cmd.handle_()
 
     def handle_(self):
         """The instance part of the classmethod call."""
         self.parser = self.get_parser()
-        args = self.parser.parse_args()
+        (options, args) = self.parser.parse_args()
         # log as verbose or quiet as we want, warn by default
         logging.basicConfig()
         logging.getLogger().setLevel(logging.WARNING -
-                                     (args.v - args.q) * 10)
-        observer = self.handle(args)
-        print observer.serialize(type=args.data).encode('utf-8', 'replace')
+                                     (options.v - options.q)*10)
+        observer = self.handle(args, options)
+        print observer.serialize(type=options.data).encode('utf-8', 'replace')
 
-    def handle(self, args):
+    def handle(self, args, options):
         """Subclasses need to implement this method for the actual
         command handling.
         """
         raise NotImplementedError
 
 
 class CompareLocales(BaseCommand):
-    """Check the localization status of a gecko application.
+    """usage: %prog [options] l10n.ini l10n_base_dir [locale ...]
+
+Check the localization status of a gecko application.
 The first argument is a path to the l10n.ini file for the application,
 followed by the base directory of the localization repositories.
 Then you pass in the list of locale codes you want to compare. If there are
 not locales given, the list of locales will be taken from the all-locales file
 of the application\'s l10n.ini."""
 
-    def get_parser(self):
-        parser = super(CompareLocales, self).get_parser()
-        parser.add_argument('ini_file', metavar='l10n.ini',
-                            help='INI file for the project')
-        parser.add_argument('l10n_base_dir', metavar='l10n-base-dir',
-                            help='Parent directory of localizations')
-        parser.add_argument('locales', nargs='*', metavar='locale-code',
-                            help='Locale code and top-level directory of '
-                                 'each localization')
-        parser.add_argument('--clobber-merge', action="store_true",
-                            default=False, dest='clobber',
-                            help="""WARNING: DATALOSS.
+    options = BaseCommand.options + [
+        make_option('--clobber-merge', action="store_true", default=False,
+                    dest='clobber',
+                    help="""WARNING: DATALOSS.
 Use this option with care. If specified, the merge directory will
 be clobbered for each module. That means, the subdirectory will
 be completely removed, any files that were there are lost.
-Be careful to specify the right merge directory when using this option.""")
-        parser.add_argument('-r', '--reference', default='en-US',
-                            dest='reference',
-                            help='Explicitly set the reference '
-                            'localization. [default: en-US]')
-        self.add_data_argument(parser)
-        return parser
+Be careful to specify the right merge directory when using this option."""),
+        make_option('-r', '--reference', default='en-US', dest='reference',
+                    help='Explicitly set the reference '
+                    'localization. [default: en-US]'),
+        BaseCommand.data_option
+    ]
 
-    def handle(self, args):
-        app = EnumerateApp(args.ini_file, args.l10n_base_dir, args.locales)
-        app.reference = args.reference
+    def handle(self, args, options):
+        if len(args) < 2:
+            self.parser.error('Need to pass in list of languages')
+        inipath, l10nbase = args[:2]
+        locales = args[2:]
+        app = EnumerateApp(inipath, l10nbase, locales)
+        app.reference = options.reference
         try:
-            observer = compareApp(app, merge_stage=args.merge,
-                                  clobber=args.clobber)
+            observer = compareApp(app, merge_stage=options.merge,
+                                  clobber=options.clobber)
         except (OSError, IOError), exc:
             print "FAIL: " + str(exc)
             self.parser.exit(2)
         return observer
 
 
 class CompareDirs(BaseCommand):
-    """Check the localization status of a directory tree.
+    """usage: %prog [options] reference localization
+
+Check the localization status of a directory tree.
 The first argument is a path to the reference data,the second is the
 localization to be tested."""
 
-    def get_parser(self):
-        parser = super(CompareDirs, self).get_parser()
-        parser.add_argument('reference')
-        parser.add_argument('localization')
-        self.add_data_argument(parser)
-        return parser
+    options = BaseCommand.options + [
+        BaseCommand.data_option
+    ]
 
-    def handle(self, args):
-        observer = compareDirs(args.reference, args.localization,
-                               merge_stage=args.merge)
+    def handle(self, args, options):
+        if len(args) != 2:
+            self.parser.error('Reference and localizatino required')
+        reference, locale = args
+        observer = compareDirs(reference, locale, merge_stage=options.merge)
         return observer
 
 
 class CompareWebApp(BaseCommand):
-    """Check the localization status of a gaia-style web app.
+    """usage: %prog [options] webapp [locale locale]
+
+Check the localization status of a gaia-style web app.
 The first argument is the directory of the web app.
 Following arguments explicitly state the locales to test.
 If none are given, test all locales in manifest.webapp or files."""
 
-    def get_parser(self):
-        parser = super(CompareWebApp, self).get_parser()
-        parser.add_argument('webapp')
-        parser.add_argument('locales', nargs='*', metavar='locale-code',
-                            help='Locale code and top-level directory of '
-                                 'each localization')
-        self.add_data_argument(parser)
-        return parser
+    options = BaseCommand.options[:-1] + [
+        BaseCommand.data_option]
 
-    def handle(self, args):
-        observer = compare_web_app(args.webapp, args.locales)
+    def handle(self, args, options):
+        if len(args) < 1:
+            self.parser.error('Webapp directory required')
+        basedir = args[0]
+        locales = args[1:]
+        observer = compare_web_app(basedir, locales)
         return observer
--- a/python/compare-locales/compare_locales/compare.py
+++ b/python/compare-locales/compare_locales/compare.py
@@ -378,45 +378,45 @@ class ContentComparer:
         Results from the notify calls are ignored.
         '''
         self.other_observers.append(obs)
 
     def set_merge_stage(self, merge_stage):
         self.merge_stage = merge_stage
 
     def merge(self, ref_entities, ref_map, ref_file, l10n_file, missing,
-              skips, ctx, canMerge, encoding):
+              skips, p):
         outfile = os.path.join(self.merge_stage, l10n_file.module,
                                l10n_file.file)
         outdir = os.path.dirname(outfile)
         if not os.path.isdir(outdir):
             os.makedirs(outdir)
-        if not canMerge:
+        if not p.canMerge:
             shutil.copyfile(ref_file.fullpath, outfile)
             print "copied reference to " + outfile
             return
         if skips:
             # skips come in ordered by key name, we need them in file order
             skips.sort(key=lambda s: s.span[0])
         trailing = (['\n'] +
                     [ref_entities[ref_map[key]].all for key in missing] +
                     [ref_entities[ref_map[skip.key]].all for skip in skips
                      if not isinstance(skip, parser.Junk)])
         if skips:
             # we need to skip a few errornous blocks in the input, copy by hand
-            f = codecs.open(outfile, 'wb', encoding)
+            f = codecs.open(outfile, 'wb', p.encoding)
             offset = 0
             for skip in skips:
                 chunk = skip.span
-                f.write(ctx.contents[offset:chunk[0]])
+                f.write(p.contents[offset:chunk[0]])
                 offset = chunk[1]
-            f.write(ctx.contents[offset:])
+            f.write(p.contents[offset:])
         else:
             shutil.copyfile(l10n_file.fullpath, outfile)
-            f = codecs.open(outfile, 'ab', encoding)
+            f = codecs.open(outfile, 'ab', p.encoding)
         print "adding to " + outfile
 
         def ensureNewline(s):
             if not s.endswith('\n'):
                 return s + '\n'
             return s
 
         f.write(''.join(map(ensureNewline, trailing)))
@@ -453,20 +453,30 @@ class ContentComparer:
                 return
             self.reference[ref_file] = p.parse()
         ref = self.reference[ref_file]
         ref_list = ref[1].keys()
         ref_list.sort()
         try:
             p.readContents(l10n.getContents())
             l10n_entities, l10n_map = p.parse()
-            l10n_ctx = p.ctx
         except Exception, e:
             self.notify('error', l10n, str(e))
             return
+        lines = []
+
+        def _getLine(offset):
+            if not lines:
+                lines.append(0)
+                for m in self.nl.finditer(p.contents):
+                    lines.append(m.end())
+            for i in xrange(len(lines), 0, -1):
+                if offset >= lines[i - 1]:
+                    return (i, offset - lines[i - 1])
+            return (1, offset)
 
         l10n_list = l10n_map.keys()
         l10n_list.sort()
         ar = AddRemove()
         ar.set_left(ref_list)
         ar.set_right(l10n_list)
         report = missing = obsolete = changed = unchanged = keys = 0
         missings = []
@@ -486,20 +496,19 @@ class ContentComparer:
                 else:
                     # just report
                     report += 1
             elif action == 'add':
                 # obsolete entity or junk
                 if isinstance(l10n_entities[l10n_map[item_or_pair]],
                               parser.Junk):
                     junk = l10n_entities[l10n_map[item_or_pair]]
-                    params = (junk.val,) + junk.position() + junk.position(-1)
+                    params = (junk.val,) + junk.span
                     self.notify('error', l10n,
-                                'Unparsed content "%s" from line %d colum %d'
-                                ' to line %d column %d' % params)
+                                'Unparsed content "%s" at %d-%d' % params)
                     if self.merge_stage is not None:
                         skips.append(junk)
                 elif self.notify('obsoleteEntity', l10n,
                                  item_or_pair) != 'ignore':
                     obsolete += 1
             else:
                 # entity found in both ref and l10n, check for changed
                 entity = item_or_pair[0]
@@ -514,40 +523,37 @@ class ContentComparer:
                     else:
                         self.doChanged(ref_file, refent, l10nent)
                         changed += 1
                         # run checks:
                 if checker:
                     for tp, pos, msg, cat in checker.check(refent, l10nent):
                         # compute real src position, if first line,
                         # col needs adjustment
+                        _l, _offset = _getLine(l10nent.val_span[0])
                         if isinstance(pos, tuple):
-                            _l, col = l10nent.value_position()
                             # line, column
                             if pos[0] == 1:
-                                col = col + pos[1]
+                                col = pos[1] + _offset
                             else:
                                 col = pos[1]
-                                _l += pos[0] - 1
+                            _l += pos[0] - 1
                         else:
-                            _l, col = l10nent.value_position(pos)
-                        # skip error entities when merging
+                            _l, col = _getLine(l10nent.val_span[0] + pos)
+                            # skip error entities when merging
                         if tp == 'error' and self.merge_stage is not None:
                             skips.append(l10nent)
                         self.notify(tp, l10n,
                                     u"%s at line %d, column %d for %s" %
                                     (msg, _l, col, refent.key))
                 pass
         if missing:
             self.notify('missing', l10n, missing)
         if self.merge_stage is not None and (missings or skips):
-            self.merge(
-                ref[0], ref[1], ref_file,
-                l10n, missings, skips, l10n_ctx,
-                p.canMerge, p.encoding)
+            self.merge(ref[0], ref[1], ref_file, l10n, missings, skips, p)
         if report:
             self.notify('report', l10n, report)
         if obsolete:
             self.notify('obsolete', l10n, obsolete)
         if changed:
             self.notify('changed', l10n, changed)
         if unchanged:
             self.notify('unchanged', l10n, unchanged)
--- a/python/compare-locales/compare_locales/parser.py
+++ b/python/compare-locales/compare_locales/parser.py
@@ -1,298 +1,199 @@
 # 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 re
-import bisect
 import codecs
 import logging
+from HTMLParser import HTMLParser
 
 __constructors = []
 
 
-class EntityBase(object):
+class Entity(object):
     '''
     Abstraction layer for a localizable entity.
     Currently supported are grammars of the form:
 
     1: pre white space
-    2: entity definition
-    3: entity key (name)
-    4: entity value
-    5: post white space
+    2: pre comments
+    3: entity definition
+    4: entity key (name)
+    5: entity value
+    6: post comment (and white space) in the same line (dtd only)
                                                  <--[1]
-    <!ENTITY key "value">
+    <!-- pre comments -->                        <--[2]
+    <!ENTITY key "value"> <!-- comment -->
 
-    <-------[2]--------->
+    <-------[3]---------><------[6]------>
     '''
-    def __init__(self, ctx, pp, pre_comment,
-                 span, pre_ws_span, def_span,
+    def __init__(self, contents, pp,
+                 span, pre_ws_span, pre_comment_span, def_span,
                  key_span, val_span, post_span):
-        self.ctx = ctx
+        self.contents = contents
         self.span = span
         self.pre_ws_span = pre_ws_span
+        self.pre_comment_span = pre_comment_span
         self.def_span = def_span
         self.key_span = key_span
         self.val_span = val_span
         self.post_span = post_span
         self.pp = pp
-        self.pre_comment = pre_comment
         pass
 
-    def position(self, offset=0):
-        """Get the 1-based line and column of the character
-        with given offset into the Entity.
-
-        If offset is negative, return the end of the Entity.
-        """
-        if offset < 0:
-            pos = self.span[1]
-        else:
-            pos = self.span[0] + offset
-        return self.ctx.lines(pos)[0]
-
-    def value_position(self, offset=0):
-        """Get the 1-based line and column of the character
-        with given offset into the value.
-
-        If offset is negative, return the end of the value.
-        """
-        if offset < 0:
-            pos = self.val_span[1]
-        else:
-            pos = self.val_span[0] + offset
-        return self.ctx.lines(pos)[0]
-
     # getter helpers
 
     def get_all(self):
-        return self.ctx.contents[self.span[0]:self.span[1]]
+        return self.contents[self.span[0]:self.span[1]]
 
     def get_pre_ws(self):
-        return self.ctx.contents[self.pre_ws_span[0]:self.pre_ws_span[1]]
+        return self.contents[self.pre_ws_span[0]:self.pre_ws_span[1]]
+
+    def get_pre_comment(self):
+        return self.contents[self.pre_comment_span[0]:
+                             self.pre_comment_span[1]]
 
     def get_def(self):
-        return self.ctx.contents[self.def_span[0]:self.def_span[1]]
+        return self.contents[self.def_span[0]:self.def_span[1]]
 
     def get_key(self):
-        return self.ctx.contents[self.key_span[0]:self.key_span[1]]
+        return self.contents[self.key_span[0]:self.key_span[1]]
 
     def get_val(self):
-        return self.pp(self.ctx.contents[self.val_span[0]:self.val_span[1]])
+        return self.pp(self.contents[self.val_span[0]:self.val_span[1]])
 
     def get_raw_val(self):
-        return self.ctx.contents[self.val_span[0]:self.val_span[1]]
+        return self.contents[self.val_span[0]:self.val_span[1]]
 
     def get_post(self):
-        return self.ctx.contents[self.post_span[0]:self.post_span[1]]
+        return self.contents[self.post_span[0]:self.post_span[1]]
 
     # getters
 
     all = property(get_all)
     pre_ws = property(get_pre_ws)
+    pre_comment = property(get_pre_comment)
     definition = property(get_def)
     key = property(get_key)
     val = property(get_val)
     raw_val = property(get_raw_val)
     post = property(get_post)
 
     def __repr__(self):
         return self.key
 
 
-class Entity(EntityBase):
-    pass
-
-
-class Comment(EntityBase):
-    def __init__(self, ctx, span, pre_ws_span, def_span,
-                 post_span):
-        self.ctx = ctx
-        self.span = span
-        self.pre_ws_span = pre_ws_span
-        self.def_span = def_span
-        self.post_span = post_span
-        self.pp = lambda v: v
-
-    @property
-    def key(self):
-        return None
-
-    @property
-    def val(self):
-        return None
-
-    def __repr__(self):
-        return self.all
-
-
 class Junk(object):
     '''
     An almost-Entity, representing junk data that we didn't parse.
     This way, we can signal bad content as stuff we don't understand.
     And the either fix that, or report real bugs in localizations.
     '''
     junkid = 0
 
-    def __init__(self, ctx, span):
-        self.ctx = ctx
+    def __init__(self, contents, span):
+        self.contents = contents
         self.span = span
-        self.pre_ws = self.definition = self.post = ''
+        self.pre_ws = self.pre_comment = self.definition = self.post = ''
         self.__class__.junkid += 1
         self.key = '_junk_%d_%d-%d' % (self.__class__.junkid, span[0], span[1])
 
-    def position(self, offset=0):
-        """Get the 1-based line and column of the character
-        with given offset into the Entity.
-
-        If offset is negative, return the end of the Entity.
-        """
-        if offset < 0:
-            pos = self.span[1]
-        else:
-            pos = self.span[0] + offset
-        return self.ctx.lines(pos)[0]
-
     # getter helpers
     def get_all(self):
-        return self.ctx.contents[self.span[0]:self.span[1]]
+        return self.contents[self.span[0]:self.span[1]]
 
     # getters
     all = property(get_all)
     val = property(get_all)
 
     def __repr__(self):
         return self.key
 
 
-class Whitespace(EntityBase):
-    '''Entity-like object representing an empty file with whitespace,
-    if allowed
-    '''
-    def __init__(self, ctx, span):
-        self.ctx = ctx
-        self.key_span = self.val_span = self.span = span
-        self.def_span = self.pre_ws_span = (span[0], span[0])
-        self.post_span = (span[1], span[1])
-        self.pp = lambda v: v
-
-    def __repr__(self):
-        return self.raw_val
-
-
 class Parser:
     canMerge = True
-    tail = re.compile('\s+\Z')
-
-    class Context(object):
-        "Fixture for content and line numbers"
-        def __init__(self, contents):
-            self.contents = contents
-            self._lines = None
-
-        def lines(self, *positions):
-            # return line and column tuples, 1-based
-            if self._lines is None:
-                nl = re.compile('\n', re.M)
-                self._lines = [m.end()
-                               for m in nl.finditer(self.contents)]
-            line_nrs = [bisect.bisect(self._lines, p) for p in positions]
-            # compute columns
-            pos_ = [
-                (1 + line, 1 + p - (self._lines[line-1] if line else 0))
-                for line, p in zip(line_nrs, positions)]
-            return pos_
 
     def __init__(self):
         if not hasattr(self, 'encoding'):
             self.encoding = 'utf-8'
-        self.ctx = None
-        self.last_comment = None
+        pass
 
     def readFile(self, file):
-        with open(file, 'rU') as f:
-            try:
-                self.readContents(f.read())
-            except UnicodeDecodeError, e:
-                (logging.getLogger('locales')
-                        .error("Can't read file: " + file + '; ' + str(e)))
+        f = codecs.open(file, 'r', self.encoding)
+        try:
+            self.contents = f.read()
+        except UnicodeDecodeError, e:
+            (logging.getLogger('locales')
+                    .error("Can't read file: " + file + '; ' + str(e)))
+            self.contents = u''
+        f.close()
 
     def readContents(self, contents):
-        '''Read contents and create parsing context.
-
-        contents are in native encoding, but with normalized line endings.
-        '''
-        (contents, length) = codecs.getdecoder(self.encoding)(contents)
-        self.ctx = Parser.Context(contents)
+        (self.contents, length) = codecs.getdecoder(self.encoding)(contents)
 
     def parse(self):
         l = []
         m = {}
         for e in self:
             m[e.key] = len(l)
             l.append(e)
         return (l, m)
 
     def postProcessValue(self, val):
         return val
 
     def __iter__(self):
-        return self.walk(onlyEntities=True)
-
-    def walk(self, onlyEntities=False):
-        if not self.ctx:
-            # loading file failed, or we just didn't load anything
-            return
-        ctx = self.ctx
-        contents = ctx.contents
+        contents = self.contents
         offset = 0
-        entity, offset = self.getEntity(ctx, offset)
+        self.header, offset = self.getHeader(contents, offset)
+        self.footer = ''
+        entity, offset = self.getEntity(contents, offset)
         while entity:
-            if (not onlyEntities or
-                    type(entity) is Entity or
-                    type(entity) is Junk):
-                yield entity
-            entity, offset = self.getEntity(ctx, offset)
+            yield entity
+            entity, offset = self.getEntity(contents, offset)
+        f = self.reFooter.match(contents, offset)
+        if f:
+            self.footer = f.group()
+            offset = f.end()
         if len(contents) > offset:
-            yield Junk(ctx, (offset, len(contents)))
+            yield Junk(contents, (offset, len(contents)))
+        pass
 
-    def getEntity(self, ctx, offset):
-        m = self.reKey.match(ctx.contents, offset)
+    def getHeader(self, contents, offset):
+        header = ''
+        h = self.reHeader.match(contents)
+        if h:
+            header = h.group()
+            offset = h.end()
+        return (header, offset)
+
+    def getEntity(self, contents, offset):
+        m = self.reKey.match(contents, offset)
         if m:
             offset = m.end()
-            entity = self.createEntity(ctx, m)
+            entity = self.createEntity(contents, m)
             return (entity, offset)
-        m = self.reComment.match(ctx.contents, offset)
+        # first check if footer has a non-empty match,
+        # 'cause then we don't find junk
+        m = self.reFooter.match(contents, offset)
+        if m and m.end() > offset:
+            return (None, offset)
+        m = self.reKey.search(contents, offset)
         if m:
-            offset = m.end()
-            self.last_comment = Comment(ctx, *[m.span(i) for i in xrange(4)])
-            return (self.last_comment, offset)
-        return self.getTrailing(ctx, offset, self.reKey, self.reComment)
+            # we didn't match, but search, so there's junk between offset
+            # and start. We'll match() on the next turn
+            junkend = m.start()
+            return (Junk(contents, (offset, junkend)), junkend)
+        return (None, offset)
 
-    def getTrailing(self, ctx, offset, *expressions):
-        junkend = None
-        for exp in expressions:
-            m = exp.search(ctx.contents, offset)
-            if m:
-                junkend = min(junkend, m.start()) if junkend else m.start()
-        if junkend is None:
-            if self.tail.match(ctx.contents, offset):
-                white_end = len(ctx.contents)
-                return (Whitespace(ctx, (offset, white_end)), white_end)
-            else:
-                return (None, offset)
-        return (Junk(ctx, (offset, junkend)), junkend)
-
-    def createEntity(self, ctx, m):
-        pre_comment = unicode(self.last_comment) if self.last_comment else ''
-        self.last_comment = ''
-        return Entity(ctx, self.postProcessValue, pre_comment,
-                      *[m.span(i) for i in xrange(6)])
+    def createEntity(self, contents, m):
+        return Entity(contents, self.postProcessValue,
+                      *[m.span(i) for i in xrange(7)])
 
 
 def getParser(path):
     for item in __constructors:
         if re.search(item[0], path):
             return item[1]
     raise UserWarning("Cannot find Parser")
 
@@ -324,249 +225,297 @@ class DTDParser(Parser):
         u'\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F' + \
         u'\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD'
     # + \U00010000-\U000EFFFF seems to be unsupported in python
 
     # NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 |
     #     [#x0300-#x036F] | [#x203F-#x2040]
     NameChar = NameStartChar + ur'\-\.0-9' + u'\xB7\u0300-\u036F\u203F-\u2040'
     Name = '[' + NameStartChar + '][' + NameChar + ']*'
-    reKey = re.compile('(?:(?P<pre>\s*)(?P<entity><!ENTITY\s+(?P<key>' + Name +
+    reKey = re.compile('(?:(?P<pre>\s*)(?P<precomment>(?:' + XmlComment +
+                       '\s*)*)(?P<entity><!ENTITY\s+(?P<key>' + Name +
                        ')\s+(?P<val>\"[^\"]*\"|\'[^\']*\'?)\s*>)'
-                       '(?P<post>\s*)?)',
-                       re.DOTALL | re.M)
+                       '(?P<post>[ \t]*(?:' + XmlComment + '\s*)*\n?)?)',
+                       re.DOTALL)
     # add BOM to DTDs, details in bug 435002
-    reHeader = re.compile(u'^\ufeff')
-    reComment = re.compile('(\s*)(<!--(-?[%s])*?-->)(\s*)' % CharMinusDash,
-                           re.S)
-    rePE = re.compile(u'(?:(\s*)'
-                      u'(<!ENTITY\s+%\s+(' + Name +
-                      u')\s+SYSTEM\s+(\"[^\"]*\"|\'[^\']*\')\s*>\s*%' + Name +
-                      u';)([ \t]*(?:' + XmlComment + u'\s*)*\n?)?)')
+    reHeader = re.compile(u'^\ufeff?'
+                          u'(\s*<!--.*(http://mozilla.org/MPL/2.0/|'
+                          u'LICENSE BLOCK)([^-]+-)*[^-]+-->)?', re.S)
+    reFooter = re.compile('\s*(<!--([^-]+-)*[^-]+-->\s*)*$')
+    rePE = re.compile('(?:(\s*)((?:' + XmlComment + '\s*)*)'
+                      '(<!ENTITY\s+%\s+(' + Name +
+                      ')\s+SYSTEM\s+(\"[^\"]*\"|\'[^\']*\')\s*>\s*%' + Name +
+                      ';)([ \t]*(?:' + XmlComment + '\s*)*\n?)?)')
 
-    def getEntity(self, ctx, offset):
+    def getEntity(self, contents, offset):
         '''
         Overload Parser.getEntity to special-case ParsedEntities.
         Just check for a parsed entity if that method claims junk.
 
         <!ENTITY % foo SYSTEM "url">
         %foo;
         '''
-        if offset is 0 and self.reHeader.match(ctx.contents):
-            offset += 1
-        entity, inneroffset = Parser.getEntity(self, ctx, offset)
+        entity, inneroffset = Parser.getEntity(self, contents, offset)
         if (entity and isinstance(entity, Junk)) or entity is None:
-            m = self.rePE.match(ctx.contents, offset)
+            m = self.rePE.match(contents, offset)
             if m:
                 inneroffset = m.end()
-                self.last_comment = ''
-                entity = Entity(ctx, self.postProcessValue, '',
-                                *[m.span(i) for i in xrange(6)])
+                entity = Entity(contents, self.postProcessValue,
+                                *[m.span(i) for i in xrange(7)])
         return (entity, inneroffset)
 
-    def createEntity(self, ctx, m):
+    def createEntity(self, contents, m):
         valspan = m.span('val')
         valspan = (valspan[0]+1, valspan[1]-1)
-        pre_comment = unicode(self.last_comment) if self.last_comment else ''
-        self.last_comment = ''
-        return Entity(ctx, self.postProcessValue, pre_comment,
-                      m.span(),
-                      m.span('pre'),
+        return Entity(contents, self.postProcessValue, m.span(),
+                      m.span('pre'), m.span('precomment'),
                       m.span('entity'), m.span('key'), valspan,
                       m.span('post'))
 
 
 class PropertiesParser(Parser):
     escape = re.compile(r'\\((?P<uni>u[0-9a-fA-F]{1,4})|'
                         '(?P<nl>\n\s*)|(?P<single>.))', re.M)
     known_escapes = {'n': '\n', 'r': '\r', 't': '\t', '\\': '\\'}
 
     def __init__(self):
         self.reKey = re.compile('^(\s*)'
+                                '((?:[#!].*?\n\s*)*)'
                                 '([^#!\s\n][^=:\n]*?)\s*[:=][ \t]*', re.M)
-        self.reComment = re.compile('(\s*)(((?:[#!][^\n]*\n?)+))', re.M)
+        self.reHeader = re.compile('^\s*([#!].*\s*)+')
+        self.reFooter = re.compile('\s*([#!].*\s*)*$')
         self._escapedEnd = re.compile(r'\\+$')
-        self._trailingWS = re.compile(r'\s*(?:\n|\Z)', re.M)
+        self._trailingWS = re.compile(r'[ \t]*$')
         Parser.__init__(self)
 
-    def getEntity(self, ctx, offset):
+    def getHeader(self, contents, offset):
+        header = ''
+        h = self.reHeader.match(contents, offset)
+        if h:
+            candidate = h.group()
+            if 'http://mozilla.org/MPL/2.0/' in candidate or \
+                    'LICENSE BLOCK' in candidate:
+                header = candidate
+                offset = h.end()
+        return (header, offset)
+
+    def getEntity(self, contents, offset):
         # overwritten to parse values line by line
-        contents = ctx.contents
-        m = self.reComment.match(contents, offset)
-        if m:
-            spans = [m.span(i) for i in xrange(3)]
-            start_trailing = offset = m.end()
-            while offset < len(contents):
-                m = self._trailingWS.match(contents, offset)
-                if not m:
-                    break
-                offset = m.end()
-            spans.append((start_trailing, offset))
-            self.last_comment = Comment(ctx, *spans)
-            return (self.last_comment, offset)
         m = self.reKey.match(contents, offset)
         if m:
-            startline = offset = m.end()
+            offset = m.end()
             while True:
                 endval = nextline = contents.find('\n', offset)
                 if nextline == -1:
                     endval = offset = len(contents)
                     break
                 # is newline escaped?
                 _e = self._escapedEnd.search(contents, offset, nextline)
                 offset = nextline + 1
                 if _e is None:
                     break
                 # backslashes at end of line, if 2*n, not escaped
                 if len(_e.group()) % 2 == 0:
                     break
-                startline = offset
             # strip trailing whitespace
-            ws = self._trailingWS.search(contents, startline)
+            ws = self._trailingWS.search(contents, m.end(), offset)
             if ws:
-                endval = ws.start()
-                offset = ws.end()
-            pre_comment = (unicode(self.last_comment) if self.last_comment
-                           else '')
-            self.last_comment = ''
-            entity = Entity(ctx, self.postProcessValue, pre_comment,
+                endval -= ws.end() - ws.start()
+            entity = Entity(contents, self.postProcessValue,
                             (m.start(), offset),   # full span
                             m.span(1),  # leading whitespan
-                            (m.start(2), offset),   # entity def span
-                            m.span(2),   # key span
+                            m.span(2),  # leading comment span
+                            (m.start(3), offset),   # entity def span
+                            m.span(3),   # key span
                             (m.end(), endval),   # value span
                             (offset, offset))  # post comment span, empty
             return (entity, offset)
-        return self.getTrailing(ctx, offset, self.reKey, self.reComment)
+        m = self.reKey.search(contents, offset)
+        if m:
+            # we didn't match, but search, so there's junk between offset
+            # and start. We'll match() on the next turn
+            junkend = m.start()
+            return (Junk(contents, (offset, junkend)), junkend)
+        return (None, offset)
 
     def postProcessValue(self, val):
 
         def unescape(m):
             found = m.groupdict()
             if found['uni']:
                 return unichr(int(found['uni'][1:], 16))
             if found['nl']:
                 return ''
             return self.known_escapes.get(found['single'], found['single'])
         val = self.escape.sub(unescape, val)
         return val
 
 
-class DefinesInstruction(EntityBase):
-    '''Entity-like object representing processing instructions in inc files
-    '''
-    def __init__(self, ctx, span, pre_ws_span, def_span, val_span, post_span):
-        self.ctx = ctx
-        self.span = span
-        self.pre_ws_span = pre_ws_span
-        self.def_span = def_span
-        self.key_span = self.val_span = val_span
-        self.post_span = post_span
-        self.pp = lambda v: v
-
-    def __repr__(self):
-        return self.raw_val
-
-
 class DefinesParser(Parser):
     # can't merge, #unfilter needs to be the last item, which we don't support
     canMerge = False
-    tail = re.compile(r'(?!)')  # never match
 
     def __init__(self):
-        self.reComment = re.compile(
-            '((?:[ \t]*\n)*)'
-            '((?:^# .*?(?:\n|\Z))+)'
-            '((?:[ \t]*(?:\n|\Z))*)', re.M)
-        self.reKey = re.compile('((?:[ \t]*\n)*)'
-                                '(#define[ \t]+(\w+)(?:[ \t](.*?))?(?:\n|\Z))'
-                                '((?:[ \t]*(?:\n|\Z))*)',
+        self.reKey = re.compile('^(\s*)((?:^#(?!define\s).*\s*)*)'
+                                '(#define[ \t]+(\w+)[ \t]+(.*?))([ \t]*$\n?)',
                                 re.M)
-        self.rePI = re.compile('((?:[ \t]*\n)*)'
-                               '(#(\w+)[ \t]+(.*?)(?:\n|\Z))'
-                               '((?:[ \t]*(?:\n|\Z))*)',
-                               re.M)
+        self.reHeader = re.compile('^\s*(#(?!define\s).*\s*)*')
+        self.reFooter = re.compile('\s*(#(?!define\s).*\s*)*$', re.M)
         Parser.__init__(self)
 
-    def getEntity(self, ctx, offset):
-        contents = ctx.contents
-        m = self.reComment.match(contents, offset)
-        if m:
-            offset = m.end()
-            self.last_comment = Comment(ctx, *[m.span(i) for i in xrange(4)])
-            return (self.last_comment, offset)
-        m = self.reKey.match(contents, offset)
-        if m:
-            offset = m.end()
-            return (self.createEntity(ctx, m), offset)
-        m = self.rePI.match(contents, offset)
-        if m:
-            offset = m.end()
-            return (DefinesInstruction(ctx, *[m.span(i) for i in xrange(5)]),
-                    offset)
-        return self.getTrailing(ctx, offset,
-                                self.reComment, self.reKey, self.rePI)
-
-
-class IniSection(EntityBase):
-    '''Entity-like object representing sections in ini files
-    '''
-    def __init__(self, ctx, span, pre_ws_span, def_span, val_span, post_span):
-        self.ctx = ctx
-        self.span = span
-        self.pre_ws_span = pre_ws_span
-        self.def_span = def_span
-        self.key_span = self.val_span = val_span
-        self.post_span = post_span
-        self.pp = lambda v: v
-
-    def __repr__(self):
-        return self.raw_val
-
 
 class IniParser(Parser):
     '''
     Parse files of the form:
     # initial comment
     [cat]
     whitespace*
     #comment
     string=value
     ...
     '''
     def __init__(self):
-        self.reComment = re.compile(
-            '((?:[ \t]*\n)*)'
-            '((?:^[;#].*?(?:\n|\Z))+)'
-            '((?:[ \t]*(?:\n|\Z))*)', re.M)
-        self.reSection = re.compile(
-            '((?:[ \t]*\n)*)'
-            '(\[(.*?)\])'
-            '((?:[ \t]*(?:\n|\Z))*)', re.M)
-        self.reKey = re.compile(
-            '((?:[ \t]*\n)*)'
-            '((.+?)=(.*))'
-            '((?:[ \t]*(?:\n|\Z))*)', re.M)
+        self.reHeader = re.compile('^((?:\s*|[;#].*)\n)*\[.+?\]\n', re.M)
+        self.reKey = re.compile('(\s*)((?:[;#].*\n\s*)*)((.+?)=(.*))(\n?)')
+        self.reFooter = re.compile('\s*([;#].*\s*)*$')
         Parser.__init__(self)
 
-    def getEntity(self, ctx, offset):
-        contents = ctx.contents
-        m = self.reComment.match(contents, offset)
-        if m:
-            offset = m.end()
-            self.last_comment = Comment(ctx, *[m.span(i) for i in xrange(4)])
-            return (self.last_comment, offset)
-        m = self.reSection.match(contents, offset)
-        if m:
-            offset = m.end()
-            return (IniSection(ctx, *[m.span(i) for i in xrange(5)]), offset)
-        m = self.reKey.match(contents, offset)
-        if m:
-            offset = m.end()
-            return (self.createEntity(ctx, m), offset)
-        return self.getTrailing(ctx, offset,
-                                self.reComment, self.reSection, self.reKey)
+
+DECL, COMMENT, START, END, CONTENT = range(5)
+
+
+class BookmarksParserInner(HTMLParser):
+
+    class Token(object):
+        _type = None
+        content = ''
+
+        def __str__(self):
+            return self.content
+
+    class DeclToken(Token):
+        _type = DECL
+
+        def __init__(self, decl):
+            self.content = decl
+            pass
+
+        def __str__(self):
+            return '<!%s>' % self.content
+        pass
+
+    class CommentToken(Token):
+        _type = COMMENT
+
+        def __init__(self, comment):
+            self.content = comment
+            pass
+
+        def __str__(self):
+            return '<!--%s-->' % self.content
+        pass
+
+    class StartToken(Token):
+        _type = START
+
+        def __init__(self, tag, attrs, content):
+            self.tag = tag
+            self.attrs = dict(attrs)
+            self.content = content
+            pass
+        pass
+
+    class EndToken(Token):
+        _type = END
+
+        def __init__(self, tag):
+            self.tag = tag
+            pass
+
+        def __str__(self):
+            return '</%s>' % self.tag.upper()
+        pass
+
+    class ContentToken(Token):
+        _type = CONTENT
+
+        def __init__(self, content):
+            self.content = content
+            pass
+        pass
+
+    def __init__(self):
+        HTMLParser.__init__(self)
+        self.tokens = []
+
+    def parse(self, contents):
+        self.tokens = []
+        self.feed(contents)
+        self.close()
+        return self.tokens
+
+    # Called when we hit an end DL tag to reset the folder selections
+    def handle_decl(self, decl):
+        self.tokens.append(self.DeclToken(decl))
+
+    # Called when we hit an end DL tag to reset the folder selections
+    def handle_comment(self, comment):
+        self.tokens.append(self.CommentToken(comment))
+
+    def handle_starttag(self, tag, attrs):
+        self.tokens.append(self.StartToken(tag, attrs,
+                                           self.get_starttag_text()))
+
+    # Called when text data is encountered
+    def handle_data(self, data):
+        if self.tokens[-1]._type == CONTENT:
+            self.tokens[-1].content += data
+        else:
+            self.tokens.append(self.ContentToken(data))
+
+    def handle_charref(self, data):
+        self.handle_data('&#%s;' % data)
+
+    def handle_entityref(self, data):
+        self.handle_data('&%s;' % data)
+
+    # Called when we hit an end DL tag to reset the folder selections
+    def handle_endtag(self, tag):
+        self.tokens.append(self.EndToken(tag))
+
+
+class BookmarksParser(Parser):
+    canMerge = False
+
+    class BMEntity(object):
+        def __init__(self, key, val):
+            self.key = key
+            self.val = val
+
+    def __iter__(self):
+        p = BookmarksParserInner()
+        tks = p.parse(self.contents)
+        i = 0
+        k = []
+        for i in xrange(len(tks)):
+            t = tks[i]
+            if t._type == START:
+                k.append(t.tag)
+                keys = t.attrs.keys()
+                keys.sort()
+                for attrname in keys:
+                    yield self.BMEntity('.'.join(k) + '.@' + attrname,
+                                        t.attrs[attrname])
+                if i + 1 < len(tks) and tks[i+1]._type == CONTENT:
+                    i += 1
+                    t = tks[i]
+                    v = t.content.strip()
+                    if v:
+                        yield self.BMEntity('.'.join(k), v)
+            elif t._type == END:
+                k.pop()
 
 
 __constructors = [('\\.dtd$', DTDParser()),
                   ('\\.properties$', PropertiesParser()),
                   ('\\.ini$', IniParser()),
-                  ('\\.inc$', DefinesParser())]
+                  ('\\.inc$', DefinesParser()),
+                  ('bookmarks\\.html$', BookmarksParser())]
--- a/python/compare-locales/compare_locales/tests/__init__.py
+++ b/python/compare-locales/compare_locales/tests/__init__.py
@@ -4,28 +4,28 @@
 
 '''Mixins for parser tests.
 '''
 
 from itertools import izip_longest
 from pkg_resources import resource_string
 import re
 
-from compare_locales import parser
+from compare_locales.parser import getParser
 
 
 class ParserTestMixin():
     '''Utility methods used by the parser tests.
     '''
     filename = None
 
     def setUp(self):
         '''Create a parser for this test.
         '''
-        self.parser = parser.getParser(self.filename)
+        self.parser = getParser(self.filename)
 
     def tearDown(self):
         'tear down this test'
         del self.parser
 
     def resource(self, name):
         testcontent = resource_string(__name__, 'data/' + name)
         # fake universal line endings
@@ -33,18 +33,17 @@ class ParserTestMixin():
         return testcontent
 
     def _test(self, content, refs):
         '''Helper to test the parser.
         Compares the result of parsing content with the given list
         of reference keys and values.
         '''
         self.parser.readContents(content)
-        entities = list(self.parser.walk())
+        entities = [entity for entity in self.parser]
         for entity, ref in izip_longest(entities, refs):
-            self.assertTrue(entity, 'excess reference entity ' + unicode(ref))
-            self.assertTrue(ref, 'excess parsed entity ' + unicode(entity))
-            if isinstance(entity, parser.Entity):
+            self.assertTrue(entity, 'excess reference entity')
+            self.assertTrue(ref, 'excess parsed entity')
+            self.assertEqual(entity.val, ref[1])
+            if ref[0].startswith('_junk'):
+                self.assertTrue(re.match(ref[0], entity.key))
+            else:
                 self.assertEqual(entity.key, ref[0])
-                self.assertEqual(entity.val, ref[1])
-            else:
-                self.assertEqual(type(entity).__name__, ref[0])
-                self.assertIn(ref[1], entity.all)
--- a/python/compare-locales/compare_locales/tests/test_checks.py
+++ b/python/compare-locales/compare_locales/tests/test_checks.py
@@ -1,17 +1,17 @@
 # -*- coding: utf-8 -*-
 # 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 unittest
 
 from compare_locales.checks import getChecker
-from compare_locales.parser import getParser, Parser, Entity
+from compare_locales.parser import getParser, Entity
 from compare_locales.paths import File
 
 
 class BaseHelper(unittest.TestCase):
     file = None
     refContent = None
 
     def setUp(self):
@@ -234,26 +234,24 @@ class TestAndroid(unittest.TestCase):
     we're passing in a DTD file in the embedding/android module.
     """
     apos_msg = u"Apostrophes in Android DTDs need escaping with \\' or " + \
                u"\\u0027, or use \u2019, or put string in quotes."
     quot_msg = u"Quotes in Android DTDs need escaping with \\\" or " + \
                u"\\u0022, or put string in apostrophes."
 
     def getEntity(self, v):
-        ctx = Parser.Context(v)
-        return Entity(ctx, lambda s: s, '', (0, len(v)), (), (), (),
+        return Entity(v, lambda s: s, (0, len(v)), (), (0, 0), (), (),
                       (0, len(v)), ())
 
     def getDTDEntity(self, v):
         v = v.replace('"', '&quot;')
-        ctx = Parser.Context('<!ENTITY foo "%s">' % v)
-        return Entity(ctx,
-                      lambda s: s, '',
-                      (0, len(v) + 16), (), (), (9, 12),
+        return Entity('<!ENTITY foo "%s">' % v,
+                      lambda s: s,
+                      (0, len(v) + 16), (), (0, 0), (), (9, 12),
                       (14, len(v) + 14), ())
 
     def test_android_dtd(self):
         """Testing the actual android checks. The logic is involved,
         so this is a lot of nitty gritty detail tests.
         """
         f = File("embedding/android/strings.dtd", "strings.dtd",
                  "embedding/android")
deleted file mode 100644
--- a/python/compare-locales/compare_locales/tests/test_defines.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# -*- coding: utf-8 -*-
-# 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 unittest
-
-from compare_locales.tests import ParserTestMixin
-
-
-mpl2 = '''\
-# 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/.
-'''
-
-
-class TestDefinesParser(ParserTestMixin, unittest.TestCase):
-
-    filename = 'defines.inc'
-
-    def testBrowser(self):
-        self._test(mpl2 + '''#filter emptyLines
-
-#define MOZ_LANGPACK_CREATOR mozilla.org
-
-# If non-English locales wish to credit multiple contributors, uncomment this
-# variable definition and use the format specified.
-# #define MOZ_LANGPACK_CONTRIBUTORS <em:contributor>Joe Solon</em:contributor>
-
-#unfilter emptyLines
-
-''', (
-            ('Comment', mpl2),
-            ('DefinesInstruction', 'filter emptyLines'),
-            ('MOZ_LANGPACK_CREATOR', 'mozilla.org'),
-            ('Comment', '#define'),
-            ('DefinesInstruction', 'unfilter emptyLines')))
-
-    def testBrowserWithContributors(self):
-        self._test(mpl2 + '''#filter emptyLines
-
-#define MOZ_LANGPACK_CREATOR mozilla.org
-
-# If non-English locales wish to credit multiple contributors, uncomment this
-# variable definition and use the format specified.
-#define MOZ_LANGPACK_CONTRIBUTORS <em:contributor>Joe Solon</em:contributor>
-
-#unfilter emptyLines
-
-''', (
-            ('Comment', mpl2),
-            ('DefinesInstruction', 'filter emptyLines'),
-            ('MOZ_LANGPACK_CREATOR', 'mozilla.org'),
-            ('Comment', 'non-English'),
-            ('MOZ_LANGPACK_CONTRIBUTORS',
-             '<em:contributor>Joe Solon</em:contributor>'),
-            ('DefinesInstruction', 'unfilter emptyLines')))
-
-    def testCommentWithNonAsciiCharacters(self):
-        self._test(mpl2 + '''#filter emptyLines
-
-# e.g. #define seamonkey_l10n <DT><A HREF="http://www.mozilla.cz/produkty/seamonkey/">SeaMonkey v češtině</a>
-#define seamonkey_l10n_long
-
-#unfilter emptyLines
-
-''', (
-            ('Comment', mpl2),
-            ('DefinesInstruction', 'filter emptyLines'),
-            ('Comment', u'češtině'),
-            ('seamonkey_l10n_long', ''),
-            ('DefinesInstruction', 'unfilter emptyLines')))
-
-    def testToolkit(self):
-        self._test('''#define MOZ_LANG_TITLE English (US)
-''', (
-            ('MOZ_LANG_TITLE', 'English (US)'),))
-
-    def testToolkitEmpty(self):
-        self._test('', tuple())
-
-    def test_empty_file(self):
-        '''Test that empty files generate errors
-
-        defines.inc are interesting that way, as their
-        content is added to the generated file.
-        '''
-        self._test('\n', (('Junk', '\n'),))
-        self._test('\n\n', (('Junk', '\n\n'),))
-        self._test(' \n\n', (('Junk', ' \n\n'),))
-
-
-if __name__ == '__main__':
-    unittest.main()
--- a/python/compare-locales/compare_locales/tests/test_dtd.py
+++ b/python/compare-locales/compare_locales/tests/test_dtd.py
@@ -3,17 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 '''Tests for the DTD parser.
 '''
 
 import unittest
 import re
 
-from compare_locales import parser
+from compare_locales.parser import getParser
 from compare_locales.tests import ParserTestMixin
 
 
 class TestDTD(ParserTestMixin, unittest.TestCase):
     '''Tests for the DTD Parser.'''
     filename = 'foo.dtd'
 
     def test_one_entity(self):
@@ -25,19 +25,19 @@ class TestDTD(ParserTestMixin, unittest.
 <!ENTITY good.two "two">
 <!ENTITY bad.two "bad "quoted" word">
 <!ENTITY good.three "three">
 <!ENTITY good.four "good ' quote">
 <!ENTITY good.five "good 'quoted' word">
 '''
     quoteRef = (
         ('good.one', 'one'),
-        ('Junk', '<!ENTITY bad.one "bad " quote">'),
+        ('_junk_\\d_25-56$', '<!ENTITY bad.one "bad " quote">'),
         ('good.two', 'two'),
-        ('Junk', '<!ENTITY bad.two "bad "quoted" word">'),
+        ('_junk_\\d_82-119$', '<!ENTITY bad.two "bad "quoted" word">'),
         ('good.three', 'three'),
         ('good.four', 'good \' quote'),
         ('good.five', 'good \'quoted\' word'),)
 
     def test_quotes(self):
         self._test(self.quoteContent, self.quoteRef)
 
     def test_apos(self):
@@ -57,73 +57,30 @@ class TestDTD(ParserTestMixin, unittest.
 
     def test_trailing_comment(self):
         self._test('''<!ENTITY first "string">
 <!ENTITY second "string">
 <!--
 <!ENTITY commented "out">
 -->
 ''',
-                   (('first', 'string'), ('second', 'string'),
-                    ('Comment', 'out')))
+                   (('first', 'string'), ('second', 'string')))
 
     def test_license_header(self):
-        p = parser.getParser('foo.dtd')
+        p = getParser('foo.dtd')
         p.readContents(self.resource('triple-license.dtd'))
-        entities = list(p.walk())
-        self.assert_(isinstance(entities[0], parser.Comment))
-        self.assertIn('MPL', entities[0].all)
-        e = entities[1]
-        self.assert_(isinstance(e, parser.Entity))
-        self.assertEqual(e.key, 'foo')
-        self.assertEqual(e.val, 'value')
-        self.assertEqual(len(entities), 2)
+        for e in p:
+            self.assertEqual(e.key, 'foo')
+            self.assertEqual(e.val, 'value')
+        self.assert_('MPL' in p.header)
         p.readContents('''\
 <!-- 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/.  -->
 <!ENTITY foo "value">
 ''')
-        entities = list(p.walk())
-        self.assert_(isinstance(entities[0], parser.Comment))
-        self.assertIn('MPL', entities[0].all)
-        e = entities[1]
-        self.assert_(isinstance(e, parser.Entity))
-        self.assertEqual(e.key, 'foo')
-        self.assertEqual(e.val, 'value')
-        self.assertEqual(len(entities), 2)
-
-    def testBOM(self):
-        self._test(u'\ufeff<!ENTITY foo.label "stuff">'.encode('utf-8'),
-                   (('foo.label', 'stuff'),))
-
-    def test_trailing_whitespace(self):
-        self._test('<!ENTITY foo.label "stuff">\n  \n',
-                   (('foo.label', 'stuff'),))
-
-    def test_unicode_comment(self):
-        self._test('<!-- \xe5\x8f\x96 -->',
-                   (('Comment', u'\u53d6'),))
-
-    def test_empty_file(self):
-        self._test('', tuple())
-        self._test('\n', (('Whitespace', '\n'),))
-        self._test('\n\n', (('Whitespace', '\n\n'),))
-        self._test(' \n\n', (('Whitespace', ' \n\n'),))
-
-    def test_positions(self):
-        self.parser.readContents('''\
-<!ENTITY one  "value">
-<!ENTITY  two "other
-escaped value">
-''')
-        one, two = list(self.parser)
-        self.assertEqual(one.position(), (1, 1))
-        self.assertEqual(one.value_position(), (1, 16))
-        self.assertEqual(one.position(-1), (2, 1))
-        self.assertEqual(two.position(), (2, 1))
-        self.assertEqual(two.value_position(), (2, 16))
-        self.assertEqual(two.value_position(-1), (3, 14))
-        self.assertEqual(two.value_position(10), (3, 5))
-
+        for e in p:
+            self.assertEqual(e.key, 'foo')
+            self.assertEqual(e.val, 'value')
+        self.assert_('MPL' in p.header)
 
 if __name__ == '__main__':
     unittest.main()
--- a/python/compare-locales/compare_locales/tests/test_ini.py
+++ b/python/compare-locales/compare_locales/tests/test_ini.py
@@ -18,122 +18,98 @@ mpl2 = '''\
 class TestIniParser(ParserTestMixin, unittest.TestCase):
 
     filename = 'foo.ini'
 
     def testSimpleHeader(self):
         self._test('''; This file is in the UTF-8 encoding
 [Strings]
 TitleText=Some Title
-''', (
-            ('Comment', 'UTF-8 encoding'),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('UTF-8' in self.parser.header)
 
     def testMPL2_Space_UTF(self):
         self._test(mpl2 + '''
 ; This file is in the UTF-8 encoding
 [Strings]
 TitleText=Some Title
-''', (
-            ('Comment', mpl2),
-            ('Comment', 'UTF-8'),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('MPL' in self.parser.header)
 
     def testMPL2_Space(self):
         self._test(mpl2 + '''
 [Strings]
 TitleText=Some Title
-''', (
-            ('Comment', mpl2),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('MPL' in self.parser.header)
 
     def testMPL2_MultiSpace(self):
         self._test(mpl2 + '''\
 
 ; more comments
 
 [Strings]
 TitleText=Some Title
-''', (
-            ('Comment', mpl2),
-            ('Comment', 'more comments'),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('MPL' in self.parser.header)
 
     def testMPL2_JunkBeforeCategory(self):
         self._test(mpl2 + '''\
 Junk
 [Strings]
 TitleText=Some Title
-''', (
-            ('Comment', mpl2),
-            ('Junk', 'Junk'),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title')))
+''', (('_junk_\\d+_0-213$', mpl2 + '''\
+Junk
+[Strings]'''), ('TitleText', 'Some Title')))
+        self.assert_('MPL' not in self.parser.header)
 
     def test_TrailingComment(self):
         self._test(mpl2 + '''
 [Strings]
 TitleText=Some Title
 ;Stray trailing comment
-''', (
-            ('Comment', mpl2),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),
-            ('Comment', 'Stray trailing')))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('MPL' in self.parser.header)
 
     def test_SpacedTrailingComments(self):
         self._test(mpl2 + '''
 [Strings]
 TitleText=Some Title
 
 ;Stray trailing comment
 ;Second stray comment
 
-''', (
-            ('Comment', mpl2),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),
-            ('Comment', 'Second stray comment')))
+''', (('TitleText', 'Some Title'),))
+        self.assert_('MPL' in self.parser.header)
 
     def test_TrailingCommentsAndJunk(self):
         self._test(mpl2 + '''
 [Strings]
 TitleText=Some Title
 
 ;Stray trailing comment
 Junk
 ;Second stray comment
 
-''', (
-            ('Comment', mpl2),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),
-            ('Comment', 'Stray trailing'),
-            ('Junk', 'Junk'),
-            ('Comment', 'Second stray comment')))
+''', (('TitleText', 'Some Title'), ('_junk_\\d+_231-284$', '''\
+
+;Stray trailing comment
+Junk
+;Second stray comment
+
+''')))
+        self.assert_('MPL' in self.parser.header)
 
     def test_JunkInbetweenEntries(self):
         self._test(mpl2 + '''
 [Strings]
 TitleText=Some Title
 
 Junk
 
 Good=other string
-''', (
-            ('Comment', mpl2),
-            ('IniSection', 'Strings'),
-            ('TitleText', 'Some Title'),
-            ('Junk', 'Junk'),
-            ('Good', 'other string')))
+''', (('TitleText', 'Some Title'), ('_junk_\\d+_231-236$', '''\
 
-    def test_empty_file(self):
-        self._test('', tuple())
-        self._test('\n', (('Whitespace', '\n'),))
-        self._test('\n\n', (('Whitespace', '\n\n'),))
-        self._test(' \n\n', (('Whitespace', ' \n\n'),))
+Junk'''), ('Good', 'other string')))
+        self.assert_('MPL' in self.parser.header)
 
 if __name__ == '__main__':
     unittest.main()
--- a/python/compare-locales/compare_locales/tests/test_merge.py
+++ b/python/compare-locales/compare_locales/tests/test_merge.py
@@ -8,32 +8,32 @@ from tempfile import mkdtemp
 import shutil
 
 from compare_locales.parser import getParser
 from compare_locales.paths import File
 from compare_locales.compare import ContentComparer
 
 
 class ContentMixin(object):
+    maxDiff = None  # we got big dictionaries to compare
     extension = None  # OVERLOAD
 
     def reference(self, content):
         self.ref = os.path.join(self.tmp, "en-reference" + self.extension)
         open(self.ref, "w").write(content)
 
     def localized(self, content):
         self.l10n = os.path.join(self.tmp, "l10n" + self.extension)
         open(self.l10n, "w").write(content)
 
 
 class TestProperties(unittest.TestCase, ContentMixin):
     extension = '.properties'
 
     def setUp(self):
-        self.maxDiff = None
         self.tmp = mkdtemp()
         os.mkdir(os.path.join(self.tmp, "merge"))
 
     def tearDown(self):
         shutil.rmtree(self.tmp)
         del self.tmp
 
     def testGood(self):
@@ -93,18 +93,17 @@ eff = effVal""")
         [m, n] = p.parse()
         self.assertEqual(map(lambda e: e.key,  m), ["bar", "eff", "foo"])
 
     def testError(self):
         self.assertTrue(os.path.isdir(self.tmp))
         self.reference("""foo = fooVal
 bar = %d barVal
 eff = effVal""")
-        self.localized("""\
-bar = %S lBar
+        self.localized("""bar = %S lBar
 eff = leffVal
 """)
         cc = ContentComparer()
         cc.set_merge_stage(os.path.join(self.tmp, "merge"))
         cc.compare(File(self.ref, "en-reference.properties", ""),
                    File(self.l10n, "l10n.properties", ""))
         self.assertDictEqual(
             cc.observer.toJSON(),
@@ -112,17 +111,17 @@ eff = leffVal
                 {None: {
                     'changed': 2, 'errors': 1, 'missing': 1
                 }},
              'details': {
                  'children': [
                      ('l10n.properties',
                          {'value': {
                           'error': [u'argument 1 `S` should be `d` '
-                                    u'at line 1, column 7 for bar'],
+                                    u'at line 1, column 6 for bar'],
                           'missingEntity': [u'foo']}}
                       )
                  ]}
              }
         )
         mergefile = os.path.join(self.tmp, "merge", "l10n.properties")
         self.assertTrue(os.path.isfile(mergefile))
         p = getParser(mergefile)
@@ -156,17 +155,16 @@ eff = leffVal
              }
         )
 
 
 class TestDTD(unittest.TestCase, ContentMixin):
     extension = '.dtd'
 
     def setUp(self):
-        self.maxDiff = None
         self.tmp = mkdtemp()
         os.mkdir(os.path.join(self.tmp, "merge"))
 
     def tearDown(self):
         shutil.rmtree(self.tmp)
         del self.tmp
 
     def testGood(self):
@@ -245,19 +243,17 @@ class TestDTD(unittest.TestCase, Content
                 {None: {
                     'errors': 1, 'missing': 1, 'unchanged': 2
                 }},
              'details': {
                  'children': [
                      ('l10n.dtd',
                          {'value': {
                              'error': [u'Unparsed content "<!ENTY bar '
-                                       u'\'gimmick\'>" '
-                                       u'from line 2 colum 1 to '
-                                       u'line 2 column 22'],
+                                       u'\'gimmick\'>" at 23-44'],
                              'missingEntity': [u'bar']}}
                       )
                  ]}
              }
         )
         mergefile = os.path.join(self.tmp, "merge", "l10n.dtd")
         self.assertTrue(os.path.isfile(mergefile))
         p = getParser(mergefile)
deleted file mode 100644
--- a/python/compare-locales/compare_locales/tests/test_parser.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import unittest
-
-from compare_locales import parser
-
-
-class TestParserContext(unittest.TestCase):
-    def test_lines(self):
-        "Test that Parser.Context.lines returns 1-based tuples"
-        ctx = parser.Parser.Context('''first line
-second line
-third line
-''')
-        self.assertEqual(
-            ctx.lines(0, 1),
-            [(1, 1), (1, 2)]
-        )
-        self.assertEqual(
-            ctx.lines(len('first line')),
-            [(1, len('first line') + 1)]
-        )
-        self.assertEqual(
-            ctx.lines(len('first line') + 1),
-            [(2, 1)]
-        )
-        self.assertEqual(
-            ctx.lines(len(ctx.contents)),
-            [(4, 1)]
-        )
-
-    def test_empty_parser(self):
-        p = parser.Parser()
-        entities, _map = p.parse()
-        self.assertListEqual(
-            entities,
-            []
-        )
-        self.assertDictEqual(
-            _map,
-            {}
-        )
--- a/python/compare-locales/compare_locales/tests/test_properties.py
+++ b/python/compare-locales/compare_locales/tests/test_properties.py
@@ -19,17 +19,17 @@ of two lines
 one_line_trailing = This line ends in \\
 and has junk
 two_lines_triple = This line is one of two and ends in \\\
 and still has another line coming
 ''', (
             ('one_line', 'This is one line'),
             ('two_line', u'This is the first of two lines'),
             ('one_line_trailing', u'This line ends in \\'),
-            ('Junk', 'and has junk\n'),
+            ('_junk_\\d+_113-126$', 'and has junk\n'),
             ('two_lines_triple', 'This line is one of two and ends in \\'
              'and still has another line coming')))
 
     def testProperties(self):
         # port of netwerk/test/PropertiesTest.cpp
         self.parser.readContents(self.resource('test.properties'))
         ref = ['1', '2', '3', '4', '5', '6', '7', '8',
                'this is the first part of a continued line '
@@ -58,17 +58,18 @@ and an end''', (('bar', 'one line with a
 
     def test_license_header(self):
         self._test('''\
 # 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/.
 
 foo=value
-''', (('Comment', 'MPL'), ('foo', 'value')))
+''', (('foo', 'value'),))
+        self.assert_('MPL' in self.parser.header)
 
     def test_escapes(self):
         self.parser.readContents(r'''
 # unicode escapes
 zero = some \unicode
 one = \u0
 two = \u41
 three = \u042
@@ -82,69 +83,13 @@ seven = \n\r\t\\
             self.assertEqual(e.val, r)
 
     def test_trailing_comment(self):
         self._test('''first = string
 second = string
 
 #
 #commented out
-''', (('first', 'string'), ('second', 'string'),
-            ('Comment', 'commented out')))
-
-    def test_trailing_newlines(self):
-        self._test('''\
-foo = bar
-
-\x20\x20
-  ''', (('foo', 'bar'),))
-
-    def test_just_comments(self):
-        self._test('''\
-# 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/.
-
-# LOCALIZATION NOTE These strings are used inside the Promise debugger
-# which is available as a panel in the Debugger.
-''', (('Comment', 'MPL'), ('Comment', 'LOCALIZATION NOTE')))
-
-    def test_just_comments_without_trailing_newline(self):
-        self._test('''\
-# 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/.
+''', (('first', 'string'), ('second', 'string')))
 
-# LOCALIZATION NOTE These strings are used inside the Promise debugger
-# which is available as a panel in the Debugger.''', (
-            ('Comment', 'MPL'), ('Comment', 'LOCALIZATION NOTE')))
-
-    def test_trailing_comment_and_newlines(self):
-        self._test('''\
-# LOCALIZATION NOTE These strings are used inside the Promise debugger
-# which is available as a panel in the Debugger.
-
-
-
-''',  (('Comment', 'LOCALIZATION NOTE'),))
-
-    def test_empty_file(self):
-        self._test('', tuple())
-        self._test('\n', (('Whitespace', '\n'),))
-        self._test('\n\n', (('Whitespace', '\n\n'),))
-        self._test(' \n\n', (('Whitespace', ' \n\n'),))
-
-    def test_positions(self):
-        self.parser.readContents('''\
-one = value
-two = other \\
-escaped value
-''')
-        one, two = list(self.parser)
-        self.assertEqual(one.position(), (1, 1))
-        self.assertEqual(one.value_position(), (1, 7))
-        self.assertEqual(two.position(), (2, 1))
-        self.assertEqual(two.value_position(), (2, 7))
-        self.assertEqual(two.value_position(-1), (3, 14))
-        self.assertEqual(two.value_position(10), (3, 3))
 
 if __name__ == '__main__':
     unittest.main()
--- a/python/compare-locales/compare_locales/webapps.py
+++ b/python/compare-locales/compare_locales/webapps.py
@@ -78,17 +78,17 @@ class Manifest(object):
         return self._strings
 
     def load_and_parse(self):
         try:
             manifest = json.load(open(self.file.fullpath))
         except (ValueError, IOError), e:
             if self.watcher:
                 self.watcher.notify('error', self.file, str(e))
-            return {}
+            return False
         return self.extract_manifest_strings(manifest)
 
     def extract_manifest_strings(self, manifest_fragment):
         '''Extract localizable strings from a manifest dict.
         This method is recursive, and returns a two-level dict,
         first level being locale codes, second level being generated
         key and localized value. Keys are generated by concatenating
         each level in the json with a ".".
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1160,9 +1160,9 @@ static const TransportSecurityPreload kP
   { "za.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
   { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
 };
 
 // Pinning Preload List Length = 464;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1488637323624000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1488810073758000);
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -22,34 +22,32 @@ 25daysof.io: could not connect to host
 2859cc.com: could not connect to host
 2or3.tk: could not connect to host
 300651.ru: did not receive HSTS header
 302.nyc: could not connect to host
 360ds.co.in: could not connect to host
 360gradus.com: did not receive HSTS header
 365.or.jp: did not receive HSTS header
 3chit.cf: could not connect to host
-404.sh: could not connect to host
 420dongstorm.com: could not connect to host
 42ms.org: could not connect to host
 4455software.com: did not receive HSTS header
 4679.space: could not connect to host
 47ronin.com: did not receive HSTS header
 491mhz.net: could not connect to host
 4elements.com: did not receive HSTS header
 4eyes.ch: did not receive HSTS header
 4mm.org: could not connect to host
 4sqsu.eu: could not connect to host
 50millionablaze.org: did not receive HSTS header
 56ct.com: could not connect to host
 60ych.net: did not receive HSTS header
 7kovrikov.ru: did not receive HSTS header
 808.lv: could not connect to host
 83i.net: could not connect to host
-88.to: did not receive HSTS header
 8ack.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 911911.pw: could not connect to host
 922.be: could not connect to host
 960news.ca: could not connect to host
 9point6.com: could not connect to host
 a-plus.space: could not connect to host
 a9c.co: could not connect to host
 aaeblog.com: did not receive HSTS header
@@ -103,21 +101,21 @@ adver.top: could not connect to host
 adviespuntklokkenluiders.nl: did not receive HSTS header
 aemoria.com: could not connect to host
 aerialmediapro.net: could not connect to host
 aes256.ru: did not receive HSTS header
 aether.pw: could not connect to host
 aevpn.net: could not connect to host
 affinitysync.com: could not connect to host
 aficionados.com.br: did not receive HSTS header
+aficotroceni.ro: could not connect to host
 afp548.tk: could not connect to host
 afrodigital.uk: could not connect to host
 agalaxyfarfaraway.co.uk: could not connect to host
 agbremen.de: did not receive HSTS header
-ageg.ca: could not connect to host
 agevio.com: could not connect to host
 agilebits.net: could not connect to host
 agrimap.com: did not receive HSTS header
 agrios.de: did not receive HSTS header
 agro-id.gov.ua: could not connect to host
 ahabingo.com: did not receive HSTS header
 ahri.ovh: could not connect to host
 aidanwoods.com: did not receive HSTS header
@@ -141,16 +139,17 @@ alanlee.net: could not connect to host
 alanrickmanflipstable.com: could not connect to host
 alariel.de: did not receive HSTS header
 alarmsystemreviews.com: did not receive HSTS header
 albertopimienta.com: did not receive HSTS header
 alcazaar.com: could not connect to host
 alecvannoten.be: did not receive HSTS header
 alenan.org: could not connect to host
 alessandro.pw: did not receive HSTS header
+alessandroz.pro: could not connect to host
 alethearose.com: did not receive HSTS header
 alexandre.sh: did not receive HSTS header
 alexhaydock.co.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 alexisabarca.com: did not receive HSTS header
 alexismeza.com: could not connect to host
 alexismeza.com.mx: could not connect to host
 alexismeza.dk: could not connect to host
 alfredxing.com: did not receive HSTS header
@@ -200,18 +199,19 @@ animeday.ml: could not connect to host
 animesfusion.com.br: could not connect to host
 animesharp.com: could not connect to host
 animurecs.com: could not connect to host
 aniplus.cf: could not connect to host
 aniplus.gq: could not connect to host
 aniplus.ml: could not connect to host
 ankakaak.com: could not connect to host
 ankaraprofesyonelnakliyat.com: did not receive HSTS header
+ankaraprofesyonelnakliyat.com.tr: did not receive HSTS header
 annabellaw.com: max-age too low: 0
-anomaly.ws: did not receive HSTS header
+anomaly.ws: could not connect to host
 anonboards.com: did not receive HSTS header
 anook.com: max-age too low: 0
 ant.land: could not connect to host
 anthenor.co.uk: could not connect to host
 antimine.kr: could not connect to host
 antocom.com: did not receive HSTS header
 antoniomarques.eu: did not receive HSTS header
 antoniorequena.com.ve: could not connect to host
@@ -234,16 +234,17 @@ appart.ninja: could not connect to host
 appengine.google.com: did not receive HSTS header (error ignored - included regardless)
 applez.xyz: could not connect to host
 applic8.com: did not receive HSTS header
 appraisal-comps.com: could not connect to host
 appreciationkards.com: could not connect to host
 approlys.fr: did not receive HSTS header
 apps-for-fishing.com: could not connect to host
 appseccalifornia.org: did not receive HSTS header
+appson.co.uk: could not connect to host
 arabdigitalexpression.org: did not receive HSTS header
 aradulconteaza.ro: could not connect to host
 aran.me.uk: did not receive HSTS header
 arboineuropa.nl: did not receive HSTS header
 arbu.eu: max-age too low: 2419200
 argh.io: could not connect to host
 arlen.se: could not connect to host
 armory.consulting: could not connect to host
@@ -255,85 +256,89 @@ ars-design.net: could not connect to hos
 ars.toscana.it: max-age too low: 0
 artistnetwork.nl: did not receive HSTS header
 arturkohut.com: could not connect to host
 as.se: could not connect to host
 asasuou.pw: could not connect to host
 asc16.com: could not connect to host
 asdpress.cn: could not connect to host
 aserver.co: could not connect to host
+ashleymedway.com: could not connect to host
+asianodor.com: could not connect to host
+askfit.cz: did not receive HSTS header
 asmui.ga: could not connect to host
+asmui.ml: could not connect to host
 asrob.eu: could not connect to host
 ass.org.au: did not receive HSTS header
 assdecoeur.org: could not connect to host
 asset-alive.com: did not receive HSTS header
 asset-alive.net: did not receive HSTS header
 astrath.net: could not connect to host
 astrolpost.com: could not connect to host
 astromelody.com: could not connect to host
 atavio.at: could not connect to host
 atavio.ch: could not connect to host
 atavio.de: did not receive HSTS header
 atbeckett.com: did not receive HSTS header
 athaliasoft.com: did not receive HSTS header
 athenelive.com: could not connect to host
 athul.xyz: did not receive HSTS header
-atlantischild.hu: could not connect to host
 atlex.nl: did not receive HSTS header
 atomik.pro: could not connect to host
 atop.io: could not connect to host
-attilagyorffy.com: could not connect to host
 attimidesigns.com: did not receive HSTS header
 au.search.yahoo.com: max-age too low: 172800
 aubiosales.com: did not receive HSTS header
 aufmerksamkeitsstudie.com: could not connect to host
 aujapan.ru: could not connect to host
 aurainfosec.com.au: could not connect to host
 ausnah.me: could not connect to host
 ausoptic.com.au: max-age too low: 2592000
 auszeit.bio: did not receive HSTS header
 auth.mail.ru: did not receive HSTS header
 authentication.io: could not connect to host
-autimatisering.nl: could not connect to host
 auto-serwis.zgorzelec.pl: did not receive HSTS header
 auto4trade.nl: could not connect to host
 autojuhos.sk: did not receive HSTS header
 autokovrik-diskont.ru: did not receive HSTS header
 autotsum.com: could not connect to host
 autumnwindsagility.com: could not connect to host
 auverbox.ovh: did not receive HSTS header
-auxiliumincrementum.co.uk: could not connect to host
+auxiliumincrementum.co.uk: did not receive HSTS header
 av.de: did not receive HSTS header
 avec-ou-sans-ordonnance.fr: could not connect to host
 avinet.com: max-age too low: 0
 awg-mode.de: did not receive HSTS header
 axado.com.br: did not receive HSTS header
 axeny.com: did not receive HSTS header
 az.search.yahoo.com: did not receive HSTS header
 azprep.us: could not connect to host
 b3orion.com: max-age too low: 0
 babak.de: did not receive HSTS header
 baby-click.de: did not receive HSTS header
 babybic.hu: did not receive HSTS header
 babyhouse.xyz: could not connect to host
 babysaying.me: could not connect to host
 back-bone.nl: did not receive HSTS header
+backschues.net: could not connect to host
 badcronjob.com: could not connect to host
 baff.lu: did not receive HSTS header
 baiduaccount.com: could not connect to host
 baka.network: could not connect to host
+bakaweb.fr: could not connect to host
 bakkerdesignandbuild.com: did not receive HSTS header
 balcan-underground.net: could not connect to host
 baldwinkoo.com: could not connect to host
 bandb.xyz: could not connect to host
 bannisbierblog.de: could not connect to host
 banqingdiao.com: could not connect to host
 barely.sexy: did not receive HSTS header
 bashcode.ninja: could not connect to host
 basicsolutionsus.com: did not receive HSTS header
+basilisk.io: could not connect to host
 bassh.net: did not receive HSTS header
 baumstark.ca: did not receive HSTS header
 bazarstupava.sk: did not receive HSTS header
 bcbsmagentprofile.com: could not connect to host
 bccx.com: could not connect to host
 bckp.de: could not connect to host
 bcm.com.au: max-age too low: 0
 bcnx.de: max-age too low: 0
@@ -388,16 +393,17 @@ bigshinylock.minazo.net: could not conne
 bildiri.ci: did not receive HSTS header
 bildschirmflackern.de: did not receive HSTS header
 billin.net: could not connect to host
 billkiss.com: max-age too low: 300
 billninja.com: could not connect to host
 binderapp.net: could not connect to host
 biofam.ru: did not receive HSTS header
 biophysik-ssl.de: did not receive HSTS header
+bioshome.de: could not connect to host
 birkhoff.me: could not connect to host
 birkman.com: did not receive HSTS header
 bismarck.moe: did not receive HSTS header
 bitchan.it: could not connect to host
 bitcoinworld.me: could not connect to host
 bitf.ly: could not connect to host
 bitfactory.ws: could not connect to host
 bitfarm-archiv.com: did not receive HSTS header
@@ -420,31 +426,30 @@ bl4ckb0x.org: did not receive HSTS heade
 black-armada.com.pl: could not connect to host
 black-armada.pl: could not connect to host
 blackburn.link: did not receive HSTS header
 blacklane.com: did not receive HSTS header
 blackly.uk: could not connect to host
 blackpayment.ru: could not connect to host
 blackunicorn.wtf: could not connect to host
 blantik.net: could not connect to host
-blaudev.es: could not connect to host
 blenheimchalcot.com: did not receive HSTS header
 blha303.com.au: could not connect to host
 blindsexdate.nl: could not connect to host
 blocksatz-medien.de: did not receive HSTS header
 blog.cyveillance.com: did not receive HSTS header
 blog.lookout.com: did not receive HSTS header
 blubbablasen.de: could not connect to host
 blucas.org: did not receive HSTS header
 blueliv.com: did not receive HSTS header
 bluetenmeer.com: did not receive HSTS header
 bm-trading.nl: did not receive HSTS header
 bngsecure.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 bobiji.com: did not receive HSTS header
-bodyblog.nl: did not receive HSTS header
+bodyblog.nl: could not connect to host
 bodybuilding-legends.com: could not connect to host
 bodyweightsolution.com: did not receive HSTS header
 boensou.com: did not receive HSTS header
 bogosity.se: could not connect to host
 bohan.life: did not receive HSTS header
 boltdata.io: did not receive HSTS header
 bonapp.restaurant: could not connect to host
 bonfi.net: did not receive HSTS header
@@ -453,16 +458,17 @@ bonitabrazilian.co.nz: did not receive H
 bookcelerator.com: did not receive HSTS header
 booked.holiday: did not receive HSTS header
 boomerang.com: could not connect to host
 boosterlearnpro.com: did not receive HSTS header
 bootjp.me: did not receive HSTS header
 boringsecurity.net: could not connect to host
 boris.one: did not receive HSTS header
 botox.bz: did not receive HSTS header
+bougeret.fr: could not connect to host
 bouwbedrijfpurmerend.nl: did not receive HSTS header
 bowlroll.net: max-age too low: 0
 boxcryptor.com: did not receive HSTS header
 br3in.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 brain-e.co: could not connect to host
 braineet.com: did not receive HSTS header
 brainfork.ml: could not connect to host
 braintreegateway.com: did not receive HSTS header
@@ -470,29 +476,29 @@ braintreepayments.com: did not receive H
 brainvation.de: did not receive HSTS header
 bran.cc: could not connect to host
 branchtrack.com: did not receive HSTS header
 branchzero.com: did not receive HSTS header
 brandnewdays.nl: could not connect to host
 brandon.so: could not connect to host
 brandonwalker.me: could not connect to host
 brandred.net: did not receive HSTS header
+brandspray.com: did not receive HSTS header
 brianmwaters.net: could not connect to host
 brickoo.com: could not connect to host
 brideandgroomdirect.ie: did not receive HSTS header
 brks.xyz: could not connect to host
 broken-oak.com: could not connect to host
 brokenhands.io: did not receive HSTS header
 brookechase.com: did not receive HSTS header
 browserid.org: did not receive HSTS header
 brunix.net: did not receive HSTS header
 bsagan.fr: could not connect to host
 bsdtips.com: could not connect to host
 btcdlc.com: could not connect to host
-buch-cuber.de: could not connect to host
 buchheld.at: did not receive HSTS header
 budgetthostels.nl: did not receive HSTS header
 budskap.eu: could not connect to host
 bugtrack.io: did not receive HSTS header
 buhler.pro: did not receive HSTS header
 buildsaver.co.za: did not receive HSTS header
 built.by: did not receive HSTS header
 bulletpoint.cz: did not receive HSTS header
@@ -505,59 +511,59 @@ business.lookout.com: could not connect 
 businesshosting.nl: did not receive HSTS header
 busold.ws: could not connect to host
 bustimes.org: could not connect to host
 butchersworkshop.com: did not receive HSTS header
 buttercoin.com: could not connect to host
 buybaby.eu: did not receive HSTS header
 buyfox.de: did not receive HSTS header
 bvalle.com: did not receive HSTS header
-bwilkinson.co.uk: could not connect to host
 by4cqb.cn: could not connect to host
 bydisk.com: could not connect to host
 bypassed.press: could not connect to host
 bypro.xyz: could not connect to host
 bysymphony.com: max-age too low: 0
 bytepark.de: did not receive HSTS header
 c1yd3i.me: could not connect to host
 c3b.info: could not connect to host
 cabarave.com: could not connect to host
 cabusar.fr: could not connect to host
 caconnect.org: could not connect to host
 cadao.me: did not receive HSTS header
+cadmail.nl: could not connect to host
 cadusilva.com: did not receive HSTS header
 cafe-scientifique.org.ec: could not connect to host
 caim.cz: did not receive HSTS header
 cajapopcorn.com: did not receive HSTS header
 cake.care: could not connect to host
 calgaryconstructionjobs.com: could not connect to host
 calix.com: max-age too low: 0
 call.me: did not receive HSTS header
 calltrackingreports.com: could not connect to host
 calvin.me: max-age too low: 2592000
 calvinallen.net: could not connect to host
 calyxinstitute.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 camolist.com: could not connect to host
+campbellsoftware.co.uk: could not connect to host
 canadiangamblingchoice.com: did not receive HSTS header
 cancelmyprofile.com: did not receive HSTS header
 candicontrols.com: did not receive HSTS header
 candratech.com: could not connect to host
 candylion.rocks: could not connect to host
 cannyfoxx.me: could not connect to host
 canyonshoa.com: did not receive HSTS header
 capecycles.co.za: did not receive HSTS header
 captchatheprize.com: could not connect to host
 car-navi.ph: did not receive HSTS header
 carano-service.de: did not receive HSTS header
 caraudio69.cz: could not connect to host
 cardoni.net: did not receive HSTS header
 cardstream.com: did not receive HSTS header
 cardurl.com: did not receive HSTS header
 cargobay.net: could not connect to host
-carlgo11.com: could not connect to host
 carlolly.co.uk: could not connect to host
 carlosalves.info: could not connect to host
 carsforbackpackers.com: could not connect to host
 casa-due-pur.com: could not connect to host
 casedi.org: max-age too low: 0
 casinostest.com: did not receive HSTS header
 casioshop.eu: could not connect to host
 casovi.cf: could not connect to host
@@ -598,31 +604,33 @@ chaoslab.org: could not connect to host
 chargejuice.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 charnleyhouse.co.uk: max-age too low: 604800
 chartpen.com: did not receive HSTS header
 chartstoffarm.de: max-age too low: 10
 chatbot.me: did not receive HSTS header
 chateauconstellation.ch: did not receive HSTS header
 chatup.cf: could not connect to host
 chaulootz.com: could not connect to host
+chcemvediet.sk: max-age too low: 1555200
 chebedara.com: could not connect to host
 checkout.google.com: did not receive HSTS header (error ignored - included regardless)
 cheerflow.com: could not connect to host
 cheesetart.my: could not connect to host
 chejianer.cn: did not receive HSTS header
 cherysunzhang.com: max-age too low: 7776000
 chic-leather.com: could not connect to host
 chihiro.xyz: could not connect to host
 chijiokeindustries.co.uk: did not receive HSTS header
 childcaresolutionscny.org: did not receive HSTS header
 chirgui.eu: could not connect to host
 chm.vn: did not receive HSTS header
 chontalpa.pw: could not connect to host
 chotu.net: could not connect to host
 chris-web.info: could not connect to host
+chrisandsarahinasia.com: did not receive HSTS header
 chriskyrouac.com: could not connect to host
 christiaandruif.nl: could not connect to host
 christianbro.gq: could not connect to host
 christophheich.me: did not receive HSTS header
 chrisupjohn.com: could not connect to host
 chrome-devtools-frontend.appspot.com: did not receive HSTS header (error ignored - included regardless)
 chrome.google.com: did not receive HSTS header (error ignored - included regardless)
 chroniclesofgeorge.com: did not receive HSTS header
@@ -636,17 +644,16 @@ citiagent.cz: could not connect to host
 cityoflaurel.org: did not receive HSTS header
 clara-baumert.de: could not connect to host
 classicsandexotics.com: did not receive HSTS header
 classicspublishing.com: could not connect to host
 clcleaningco.com: could not connect to host
 cleaningsquad.ca: max-age too low: 0
 clerkendweller.uk: could not connect to host
 clickandgo.com: did not receive HSTS header
-clickphish.com: could not connect to host
 clint.id.au: max-age too low: 0
 clintonbloodworth.com: could not connect to host
 clintonbloodworth.io: could not connect to host
 clintwilson.technology: max-age too low: 2592000
 cloud.wtf: could not connect to host
 cloudapi.vc: could not connect to host
 cloudcert.org: did not receive HSTS header
 cloudcy.net: could not connect to host
@@ -668,24 +675,24 @@ cmlancy.ch: did not receive HSTS header
 cmlignon.ch: did not receive HSTS header
 cmplainpalais.ch: did not receive HSTS header
 cmsbattle.com: could not connect to host
 cmscafe.ru: did not receive HSTS header
 cn.search.yahoo.com: did not receive HSTS header
 co50.com: did not receive HSTS header
 coam.co: did not receive HSTS header
 cocaine-import.agency: could not connect to host
-cocoaheads.at: could not connect to host
 codabix.com: did not receive HSTS header
 codabix.de: could not connect to host
 codabix.net: could not connect to host
 code.google.com: did not receive HSTS header (error ignored - included regardless)
 codeco.pw: could not connect to host
 codeforce.io: did not receive HSTS header
 codeforhakodate.org: could not connect to host
+codepult.com: could not connect to host
 codepx.com: did not receive HSTS header
 codiva.io: max-age too low: 2592000
 coffeeetc.co.uk: did not receive HSTS header
 coffeestrategies.com: max-age too low: 2592000
 coiffeurschnittstelle.ch: did not receive HSTS header
 coindam.com: could not connect to host
 coldlostsick.net: could not connect to host
 colisfrais.com: did not receive HSTS header
@@ -700,16 +707,17 @@ comfortticket.de: did not receive HSTS h
 comicspines.com: could not connect to host
 compalytics.com: could not connect to host
 comparejewelleryprices.co.uk: could not connect to host
 completionist.audio: could not connect to host
 computeremergency.com.au: did not receive HSTS header
 concord-group.co.jp: did not receive HSTS header
 condesaelectronics.com: max-age too low: 0
 confirm365.com: could not connect to host
+confiwall.de: could not connect to host
 conformal.com: could not connect to host
 conrad-kostecki.de: did not receive HSTS header
 consciousandglamorous.com: could not connect to host
 console.python.org: did not receive HSTS header
 constructionjobs.com: did not receive HSTS header
 content-api-dev.azurewebsites.net: could not connect to host
 continuumgaming.com: could not connect to host
 controlcenter.gigahost.dk: did not receive HSTS header
@@ -771,24 +779,24 @@ crysadm.com: max-age too low: 1
 crystalclassics.co.uk: did not receive HSTS header
 csapak.com: max-age too low: 0
 csawctf.poly.edu: could not connect to host
 csfs.org.uk: could not connect to host
 csgodicegame.com: did not receive HSTS header
 csgoelemental.com: could not connect to host
 csgokings.eu: could not connect to host
 csohack.tk: could not connect to host
+csokolade.hu: could not connect to host
 cspbuilder.info: could not connect to host
 ct.search.yahoo.com: did not receive HSTS header
 cthulhuden.com: could not connect to host
 cubeserver.eu: could not connect to host
 cubewano.com: could not connect to host
 cujanovic.com: did not receive HSTS header
 cumshots-video.ru: could not connect to host
-cupi.co: did not receive HSTS header
 cupidmentor.com: did not receive HSTS header
 curroapp.com: could not connect to host
 custe.rs: could not connect to host
 cuvva.insure: did not receive HSTS header
 cyanogenmod.xxx: could not connect to host
 cybershambles.com: could not connect to host
 cycleluxembourg.lu: did not receive HSTS header
 cydia-search.io: could not connect to host
@@ -811,17 +819,16 @@ daolerp.xyz: could not connect to host
 dargasia.is: could not connect to host
 dario.im: could not connect to host
 dark-x.cf: could not connect to host
 darkag.ovh: could not connect to host
 darkengine.io: could not connect to host
 darkhole.cn: could not connect to host
 darknebula.space: could not connect to host
 darkpony.ru: could not connect to host
-darrenellis.xyz: did not receive HSTS header
 dashburst.com: did not receive HSTS header
 dashnimorad.com: did not receive HSTS header
 data-abundance.com: could not connect to host
 databionix.com: could not connect to host
 databutlr.com: could not connect to host
 databutlr.net: could not connect to host
 datahove.no: did not receive HSTS header
 datarank.com: max-age too low: 0
@@ -832,26 +839,26 @@ dateno1.com: max-age too low: 2592000
 datenreiter.cf: could not connect to host
 datenreiter.gq: could not connect to host
 datenreiter.ml: could not connect to host
 datenreiter.tk: could not connect to host
 datewon.net: did not receive HSTS header
 david-schiffmann.de: did not receive HSTS header
 davidglidden.eu: could not connect to host
 davidhunter.scot: did not receive HSTS header
+davidmessenger.co.uk: could not connect to host
 davidreinhardt.de: could not connect to host
 davidscherzer.at: could not connect to host
 daylightcompany.com: did not receive HSTS header
 db.gy: did not receive HSTS header
 dbx.ovh: did not receive HSTS header
 dccode.gov: could not connect to host
 dcurt.is: did not receive HSTS header
 ddatsh.com: did not receive HSTS header
 dden.ca: could not connect to host
-deamuseum.org: did not receive HSTS header
 debank.tv: did not receive HSTS header
 debatch.se: could not connect to host
 debtkit.co.uk: did not receive HSTS header
 decafu.co: could not connect to host
 decibelios.li: could not connect to host
 deco.me: could not connect to host
 dedicatutiempo.es: could not connect to host
 deepcovelabs.net: could not connect to host
@@ -864,22 +871,24 @@ deliverance.co.uk: could not connect to 
 deltaconcepts.de: did not receive HSTS header
 deltanet-production.de: did not receive HSTS header
 demilitarized.ninja: could not connect to host
 democracychronicles.com: did not receive HSTS header
 denh.am: did not receive HSTS header
 denisjean.fr: could not connect to host
 dentaldomain.org: did not receive HSTS header
 dentaldomain.ph: did not receive HSTS header
+depeche-mode.moscow: max-age too low: 7200
 depijl-mz.nl: did not receive HSTS header
 depixion.agency: could not connect to host
 dequehablamos.es: could not connect to host
 derevtsov.com: did not receive HSTS header
 derwolfe.net: did not receive HSTS header
 desiccantpackets.com: did not receive HSTS header
+designpilot.ch: did not receive HSTS header
 destinationbijoux.fr: could not connect to host
 detector.exposed: could not connect to host
 deux.solutions: could not connect to host
 deuxsol.com: could not connect to host
 deuxsolutions.com: could not connect to host
 devcu.net: did not receive HSTS header
 devh.de: did not receive HSTS header
 devincrow.me: could not connect to host
@@ -890,16 +899,17 @@ devuan.org: did not receive HSTS header
 diablotine.rocks: could not connect to host
 diarbag.us: did not receive HSTS header
 diasp.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 diedrich.co: could not connect to host
 digitaldaddy.net: could not connect to host
 digitalriver.tk: could not connect to host
 digitalskillswap.com: could not connect to host
 dinamoelektrik.com: max-age too low: 0
+dinepont.fr: could not connect to host
 dinkum.online: could not connect to host
 dirk-weise.de: could not connect to host
 discoveringdocker.com: did not receive HSTS header
 discovery.lookout.com: did not receive HSTS header
 dislocated.de: did not receive HSTS header
 dissimulo.me: could not connect to host
 dittvertshus.no: could not connect to host
 dizihocasi.com: did not receive HSTS header
@@ -924,16 +934,17 @@ dollywiki.co.uk: could not connect to ho
 dolphin-cloud.com: could not connect to host
 dolphincorp.co.uk: could not connect to host
 domaris.de: did not receive HSTS header
 dominique-mueller.de: did not receive HSTS header
 donttrustrobots.nl: could not connect to host
 donzelot.co.uk: max-age too low: 3600
 doomleika.com: could not connect to host
 dopost.it: could not connect to host
+dorianmuthig.com: could not connect to host
 doridian.com: could not connect to host
 doridian.de: could not connect to host
 doridian.net: did not receive HSTS header
 doridian.org: could not connect to host
 dossplumbing.co.za: did not receive HSTS header
 dotadata.me: could not connect to host
 dougferris.id.au: could not connect to host
 download.jitsi.org: did not receive HSTS header
@@ -956,24 +967,25 @@ driving-lessons.co.uk: did not receive H
 droidboss.com: could not connect to host
 dropcam.com: did not receive HSTS header
 drtroyhendrickson.com: could not connect to host
 drumbandesperanto.nl: could not connect to host
 dshiv.io: could not connect to host
 dubrovskiy.net: could not connect to host
 dubrovskiy.pro: could not connect to host
 duch.cloud: could not connect to host
+duckasylum.com: could not connect to host
 duesee.org: could not connect to host
-dullsir.com: could not connect to host
+dullsir.com: did not receive HSTS header
 duria.de: max-age too low: 3600
 dwhd.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
-dworzak.ch: could not connect to host
 dycontrol.de: could not connect to host
 dylanscott.com.au: did not receive HSTS header
 dymersion.com: did not receive HSTS header
+dynamicsnetwork.net: could not connect to host
 dynamize.solutions: could not connect to host
 dzimejl.sk: did not receive HSTS header
 dzlibs.io: could not connect to host
 e-aut.net: could not connect to host
 e-deca2.org: did not receive HSTS header
 e3amn2l.com: could not connect to host
 earga.sm: could not connect to host
 earlybirdsnacks.com: could not connect to host
@@ -1009,17 +1021,19 @@ ego-world.org: could not connect to host
 ehrenamt-skpfcw.de: could not connect to host
 eicfood.com: could not connect to host
 eidolonhost.com: could not connect to host
 ekbanden.nl: could not connect to host
 ekostecki.de: did not receive HSTS header
 el-soul.com: did not receive HSTS header
 elaintehtaat.fi: did not receive HSTS header
 elanguest.pl: could not connect to host
+elars.de: could not connect to host
 elbetech.net: could not connect to host
+eldinhadzic.com: could not connect to host
 electricianforum.co.uk: could not connect to host
 electromc.com: could not connect to host
 elemprendedor.com.ve: could not connect to host
 elenag.ga: could not connect to host
 elenoon.ir: did not receive HSTS header
 elgacien.de: could not connect to host
 elimdengelen.com: did not receive HSTS header
 elisabeth-kostecki.de: did not receive HSTS header
@@ -1040,16 +1054,17 @@ enargia.jp: max-age too low: 0
 encode.space: did not receive HSTS header
 encoder.pw: could not connect to host
 encrypted.google.com: did not receive HSTS header (error ignored - included regardless)
 endohaus.ca: could not connect to host
 endohaus.com: could not connect to host
 endohaus.eu: could not connect to host
 endohaus.us: could not connect to host
 endzeit-architekten.com: did not receive HSTS header
+energydrinkblog.de: could not connect to host
 engelwerbung.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 englishforums.com: could not connect to host
 enigmacpt.com: did not receive HSTS header
 enigmail.net: did not receive HSTS header
 enteente.club: could not connect to host
 enteente.space: could not connect to host
 enteente.xyz: could not connect to host
 enterdev.co: did not receive HSTS header
@@ -1098,17 +1113,16 @@ euanbaines.com: did not receive HSTS hea
 eucl3d.com: did not receive HSTS header
 euph.eu: could not connect to host
 euren.se: could not connect to host
 euroshop24.net: could not connect to host
 evantage.org: could not connect to host
 evdenevenakliyatankara.pw: did not receive HSTS header
 everybooks.com: max-age too low: 60
 everylab.org: could not connect to host
-evi.be: did not receive HSTS header
 evin.ml: could not connect to host
 evomon.com: could not connect to host
 evossd.tk: could not connect to host
 exceltobarcode.com: did not receive HSTS header
 exfiles.cz: did not receive HSTS header
 exgravitus.com: could not connect to host
 exitus.jp: max-age too low: 0
 exno.co: could not connect to host
@@ -1136,16 +1150,17 @@ fail4free.de: did not receive HSTS heade
 fairlyoddtreasures.com: did not receive HSTS header
 faizan.net: did not receive HSTS header
 faizan.xyz: could not connect to host
 fakeletters.org: did not receive HSTS header
 falconfrag.com: could not connect to host
 falkena.net: max-age too low: 5184000
 falkp.no: did not receive HSTS header
 familie-zimmermann.at: could not connect to host
+fanjoe.be: could not connect to host
 fanyl.cn: could not connect to host
 fashioncare.cz: did not receive HSTS header
 fasset.jp: could not connect to host
 fastopen.ml: could not connect to host
 fatgeekflix.net: could not connect to host
 fatherhood.gov: did not receive HSTS header
 fatlossguide.xyz: could not connect to host
 fatox.de: could not connect to host
@@ -1190,16 +1205,17 @@ fivestarsitters.com: did not receive HST
 fixate.ru: did not receive HSTS header
 fixatom.com: did not receive HSTS header
 fixingdns.com: did not receive HSTS header
 fizz.buzz: could not connect to host
 fj.search.yahoo.com: did not receive HSTS header
 flags.ninja: could not connect to host
 flamewall.net: could not connect to host
 flawcheck.com: did not receive HSTS header
+fleximus.org: could not connect to host
 fliexer.com: did not receive HSTS header
 floless.co.uk: did not receive HSTS header
 florian-lillpopp.de: max-age too low: 10
 florianlillpopp.de: max-age too low: 10
 floridaescapes.co.uk: did not receive HSTS header
 flouartistique.ch: could not connect to host
 flow.pe: could not connect to host
 flow.su: could not connect to host
@@ -1217,17 +1233,16 @@ foraje-profesionale.ro: did not receive 
 forbook.net: could not connect to host
 foreignexchangeresource.com: did not receive HSTS header
 foreveralone.io: could not connect to host
 forex-dan.com: did not receive HSTS header
 formbetter.com: could not connect to host
 formini.dz: did not receive HSTS header
 formula.cf: could not connect to host
 forodeespanol.com: could not connect to host
-fortesanshop.it: could not connect to host
 fotiu.com: could not connect to host
 fotm.net: did not receive HSTS header
 fotocerita.net: could not connect to host
 fotografosexpertos.com: did not receive HSTS header
 fotopasja.info: could not connect to host
 foxdev.io: could not connect to host
 foxelbox.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 foxtrot.pw: could not connect to host
@@ -1275,60 +1290,62 @@ fysiohaenraets.nl: did not receive HSTS 
 fzn.io: could not connect to host
 g2a.co: did not receive HSTS header
 g2g.com: did not receive HSTS header
 g4w.co: did not receive HSTS header (error ignored - included regardless)
 gabber.scot: could not connect to host
 gaelleetarnaud.com: did not receive HSTS header
 gaestehaus-monika.com: could not connect to host
 gafachi.com: could not connect to host
-gaichon.com: could not connect to host
 gakkainavi4.com: could not connect to host
 galardi.org: did not receive HSTS header
 galenskap.eu: could not connect to host
 gallery44.org: did not receive HSTS header
 galoisvpn.xyz: could not connect to host
+game.yt: could not connect to host
 gamecave.de: could not connect to host
 gamechasm.com: could not connect to host
 gamehacks.me: could not connect to host
 gameink.net: max-age too low: 0
 gamenected.com: could not connect to host
 gamenected.de: could not connect to host
 gameparade.de: could not connect to host
 gamepiece.com: could not connect to host
+gamers-life.fr: could not connect to host
 gamerslair.org: did not receive HSTS header
 gamesdepartment.co.uk: max-age too low: 0
 gamingmedia.eu: did not receive HSTS header
 gampenhof.de: did not receive HSTS header
 gaptek.id: did not receive HSTS header
 garciamartin.me: could not connect to host
 gatilagata.com.br: did not receive HSTS header
+gchq.wtf: could not connect to host
 gdpventure.com: max-age too low: 0
 gedankenbude.info: did not receive HSTS header
 geekbundle.org: did not receive HSTS header
 geekcast.co.uk: did not receive HSTS header
 geli-graphics.com: did not receive HSTS header
 gem-indonesia.net: could not connect to host
 genuu.com: could not connect to host
 genuxation.com: could not connect to host
-genuxtsg.com: could not connect to host
 genyaa.com: could not connect to host
 gerencianet.com.br: did not receive HSTS header
 get.zenpayroll.com: did not receive HSTS header
 getable.com: did not receive HSTS header
 getblys.com.au: did not receive HSTS header
 getbooks.co.il: did not receive HSTS header
 getcarefirst.com: did not receive HSTS header
 getcolor.com: did not receive HSTS header
 getinternet.de: max-age too low: 0
 getlantern.org: did not receive HSTS header
 getlifti.com: did not receive HSTS header
 getlolaccount.com: could not connect to host
 getmassage.com.ng: did not receive HSTS header
 getsello.com: did not receive HSTS header
+getspire.com: could not connect to host
 getwashdaddy.com: did not receive HSTS header
 gfhgiro.nl: max-age too low: 604800
 gfm.tech: could not connect to host
 gfournier.ca: could not connect to host
 gfwsb.ml: could not connect to host
 gh16.com.ar: could not connect to host
 gheorghesarcov.ga: could not connect to host
 gheorghesarcov.tk: could not connect to host
@@ -1369,25 +1386,24 @@ goben.ch: could not connect to host
 goerner.me: did not receive HSTS header
 goge.site: could not connect to host
 gogenenglish.com: could not connect to host
 gogetssl.com: did not receive HSTS header
 gogold-g.com: could not connect to host
 gold24.in: did not receive HSTS header
 goldendata.io: could not connect to host
 goldminer.ga: could not connect to host
-goldpros.com: did not receive HSTS header
 golocal-media.de: did not receive HSTS header
 gonzalosanchez.mx: did not receive HSTS header
 goodenough.nz: did not receive HSTS header
 goodwin43.ru: did not receive HSTS header
 google: could not connect to host (error ignored - included regardless)
 googlemail.com: did not receive HSTS header (error ignored - included regardless)
 googleplex.com: did not receive HSTS header (error ignored - included regardless)
-goolok.com: could not connect to host
+goolok.com: did not receive HSTS header
 gorilla-gym.site: could not connect to host
 goto.google.com: did not receive HSTS header (error ignored - included regardless)
 gottcode.org: did not receive HSTS header
 govillemo.ca: did not receive HSTS header
 gowe.wang: could not connect to host
 gparent.org: did not receive HSTS header
 gpsfix.cz: could not connect to host
 gpstuner.com: did not receive HSTS header
@@ -1413,18 +1429,16 @@ gryffin.ga: could not connect to host
 gryffin.ml: could not connect to host
 gryffin.tk: could not connect to host
 gsm-map.com: could not connect to host
 gtanda.tk: could not connect to host
 gtlfsonlinepay.com: did not receive HSTS header
 gtraxapp.com: could not connect to host
 guava.studio: did not receive HSTS header
 guilde-vindicta.fr: did not receive HSTS header
-gunnaro.com: could not connect to host
-guoqiang.info: could not connect to host
 gurusupe.com: could not connect to host
 gussi.is: could not connect to host
 gvt2.com: could not connect to host (error ignored - included regardless)
 gvt3.com: could not connect to host (error ignored - included regardless)
 gwijaya.com: could not connect to host
 gwtest.us: could not connect to host
 gxlrx.net: could not connect to host
 gyboche.com: could not connect to host
@@ -1457,17 +1471,16 @@ hancc.net: did not receive HSTS header
 hanfu.la: could not connect to host
 hang333.pw: could not connect to host
 hannover-banditen.de: did not receive HSTS header
 hao2taiwan.com: max-age too low: 0
 haozi.me: could not connect to host
 happyfabric.me: did not receive HSTS header
 happygadget.me: could not connect to host
 harabuhouse.com: did not receive HSTS header
-harbor-light.net: did not receive HSTS header
 harmonycosmetic.com: max-age too low: 300
 harristony.com: could not connect to host
 hartmancpa.com: did not receive HSTS header
 harvestapp.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 harvestrenewal.org: did not receive HSTS header
 harz.cloud: could not connect to host
 has.vision: could not connect to host
 hash-list.com: could not connect to host
@@ -1481,21 +1494,21 @@ haurumcraft.net: could not connect to ho
 haveeruexaminer.com: could not connect to host
 havellab.de: could not connect to host
 haydenhill.us: could not connect to host
 hazcod.com: could not connect to host
 hcie.pl: could not connect to host
 hdm.io: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 hduin.xyz: did not receive HSTS header
 hdwallpapers.net: did not receive HSTS header
-healtious.com: did not receive HSTS header
+healtious.com: could not connect to host
 heart.ge: did not receive HSTS header
 heartlandrentals.com: did not receive HSTS header
 heftkaufen.de: did not receive HSTS header
-hellenicaward.com: did not receive HSTS header
+hellenicaward.com: could not connect to host
 helloworldhost.com: did not receive HSTS header
 helpadmin.net: could not connect to host
 helpium.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 helpmebuild.com: did not receive HSTS header
 hemdal.se: could not connect to host
 hencagon.com: could not connect to host
 henriknoerr.com: could not connect to host
 hepteract.us: did not receive HSTS header
@@ -1526,17 +1539,17 @@ holymoly.lu: did not receive HSTS header
 homa.website: could not connect to host
 honeytracks.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 hongzhaxiaofendui.com: could not connect to host
 honoo.com: could not connect to host
 hookandloom.com: did not receive HSTS header
 horosho.in: could not connect to host
 horseboners.xxx: did not receive HSTS header
 hortifarm.ro: did not receive HSTS header
-hosted-service.com: did not receive HSTS header
+hosted-service.com: could not connect to host
 hostedtalkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
 hostgarou.com: did not receive HSTS header
 hostinaus.com.au: could not connect to host
 hostisan.com: did not receive HSTS header
 hotchillibox.com: max-age too low: 0
 hotchoc.io: did not receive HSTS header
 hotting.nl: could not connect to host
 houkago-step.com: did not receive HSTS header
@@ -1551,16 +1564,17 @@ http418.xyz: could not connect to host
 httpstatuscode418.xyz: could not connect to host
 hu.search.yahoo.com: did not receive HSTS header
 huarongdao.com: did not receive HSTS header
 hugosleep.com.au: did not receive HSTS header
 humblefinances.com: could not connect to host
 humeurs.net: could not connect to host
 humpteedumptee.in: did not receive HSTS header
 huntshomeinspections.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
+hupp.se: could not connect to host
 hurricanelabs.com: did not receive HSTS header
 hydra.ws: could not connect to host
 hyper69.com: did not receive HSTS header
 hzsh.xyz: max-age too low: 0
 i-jp.net: could not connect to host
 i-partners.sk: did not receive HSTS header
 iamokay.nl: did not receive HSTS header
 iamveto.com: could not connect to host
@@ -1573,17 +1587,17 @@ icreative.nl: did not receive HSTS heade
 ictual.com: max-age too low: 0
 icusignature.com: did not receive HSTS header
 id-co.in: could not connect to host
 id-conf.com: could not connect to host
 idacmedia.com: max-age too low: 5184000
 ideadozz.hu: did not receive HSTS header
 ideal-envelopes.co.uk: did not receive HSTS header
 ideasmeetingpoint.com: could not connect to host
-ideation-inc.co.jp: could not connect to host
+ideation-inc.co.jp: did not receive HSTS header
 identitylabs.uk: did not receive HSTS header
 idgsupply.com: could not connect to host
 idlekernel.com: could not connect to host
 ie.search.yahoo.com: did not receive HSTS header
 ies-italia.it: did not receive HSTS header
 ies.id.lv: could not connect to host
 ifad.org: did not receive HSTS header
 ifleurs.com: could not connect to host
@@ -1665,16 +1679,17 @@ inverselink-user-content.com: could not 
 inverselink.com: could not connect to host
 inwesttitle.com: max-age too low: 0
 iomstamps.com: could not connect to host
 ionx.co.uk: did not receive HSTS header
 iop.intuit.com: max-age too low: 86400
 iosmods.com: could not connect to host
 iostips.ru: could not connect to host
 iotsms.io: could not connect to host
+ip-life.net: could not connect to host
 ip6.im: did not receive HSTS header
 ipmimagazine.com: did not receive HSTS header
 iptel.by: max-age too low: 0
 iptel.ro: could not connect to host
 ipv6cloud.club: could not connect to host
 iqcn.co: max-age too low: 2592000
 iqualtech.com: did not receive HSTS header
 iranianlawschool.com: could not connect to host
@@ -1710,16 +1725,17 @@ izoox.com: did not receive HSTS header
 izzzorgconcerten.nl: could not connect to host
 ja-publications.com: did not receive HSTS header
 jaba.hosting: max-age too low: 0
 jabbari.io: did not receive HSTS header
 jackalworks.com: could not connect to host
 jacobparry.ca: did not receive HSTS header
 jahliveradio.com: could not connect to host
 jakenbake.com: did not receive HSTS header
+jaksi.io: could not connect to host
 jakubtopic.cz: could not connect to host
 jamesbradach.com: did not receive HSTS header
 jamesburton.london: could not connect to host
 jamesbywater.me: could not connect to host
 jamesbywater.me.uk: could not connect to host
 jamesconroyfinn.com: did not receive HSTS header
 jamesdoell.com: could not connect to host
 jamesdoylephoto.com: did not receive HSTS header
@@ -1779,34 +1795,33 @@ jimmycai.org: max-age too low: 10368000
 jinbo123.com: did not receive HSTS header
 jkb.pics: could not connect to host
 jkbuster.com: could not connect to host
 jmdekker.it: could not connect to host
 joakimalgroy.com: could not connect to host
 jobmedic.com: did not receive HSTS header
 joedavison.me: could not connect to host
 jogi-server.de: did not receive HSTS header
-johnbrownphotography.ch: did not receive HSTS header
 johners.me: could not connect to host
 johners.tech: did not receive HSTS header
 johnhgaunt.com: did not receive HSTS header
 johnrom.com: did not receive HSTS header
 jonas-keidel.de: did not receive HSTS header
 jonasgroth.se: max-age too low: 2592000
 jonathan.ir: could not connect to host
 jonathancarter.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 jonn.me: could not connect to host
+jonnichols.info: could not connect to host
 joostbovee.nl: did not receive HSTS header
 jordanhamilton.me: could not connect to host
 joretapo.fr: could not connect to host
 josahrens.me: could not connect to host
 joshstroup.me: could not connect to host
 jottit.com: could not connect to host
 jpbike.cz: could not connect to host
-jpeaches.xyz: could not connect to host
 jrc9.ca: did not receive HSTS header
 jrgold.me: could not connect to host
 jrvar.com: did not receive HSTS header
 jsanders.us: did not receive HSTS header
 jualautoclave.com: did not receive HSTS header
 jualssh.com: could not connect to host
 juliamweber.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 julian-kipka.de: did not receive HSTS header
@@ -1825,43 +1840,43 @@ jxm.in: could not connect to host
 k-dev.de: could not connect to host
 ka-clan.com: could not connect to host
 kabuabc.com: did not receive HSTS header
 kadioglumakina.com.tr: did not receive HSTS header
 kahopoon.net: could not connect to host
 kaisers.de: did not receive HSTS header
 kalami.nl: did not receive HSTS header
 kamikano.com: could not connect to host
+kamikatse.net: could not connect to host
 kaplatz.is: could not connect to host
 kapucini.si: max-age too low: 0
 karaoketonight.com: could not connect to host
-kasilag.me: could not connect to host
 katiaetdavid.fr: could not connect to host
 katproxy.online: could not connect to host
 katproxy.site: could not connect to host
 katproxy.tech: could not connect to host
 kaufkraftkiel.de: could not connect to host
 kausch.at: could not connect to host
 kawaii.io: could not connect to host
 kawaiiku.com: could not connect to host
 kawaiiku.de: could not connect to host
 kayon.cf: could not connect to host
 kdata.it: did not receive HSTS header
 kdm-online.de: did not receive HSTS header
 keeley.gq: could not connect to host
 keeley.ml: could not connect to host
 keeleysam.me: could not connect to host
 keepclean.me: could not connect to host
-kenderbeton-magyarorszag.hu: did not receive HSTS header
 kerangalam.com: did not receive HSTS header
 kerksanders.nl: did not receive HSTS header
 kermadec.net: could not connect to host
 kernl.us: did not receive HSTS header
 kevinapease.com: could not connect to host
 keymaster.lookout.com: did not receive HSTS header
+kfz-hantschel.de: did not receive HSTS header
 kg-rating.com: did not receive HSTS header
 kgxtech.com: max-age too low: 2592000
 kickass.al: could not connect to host
 kid-dachau.de: did not receive HSTS header
 kiel-media.de: did not receive HSTS header
 kimpost.org: could not connect to host
 kinderwagen-test24.de: could not connect to host
 kingmanhall.org: could not connect to host
@@ -1871,16 +1886,17 @@ kionetworks.com: did not receive HSTS he
 kipira.com: could not connect to host
 kirkforcongress.com: could not connect to host
 kirkforsenate.com: did not receive HSTS header
 kirkpatrickdavis.com: could not connect to host
 kisa.io: could not connect to host
 kisalt.im: did not receive HSTS header
 kissart.net: could not connect to host
 kissflow.com: did not receive HSTS header
+kisun.co.jp: could not connect to host
 kitakemon.com: could not connect to host
 kitchenpunx.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 kitk.at: could not connect to host
 kitsta.com: could not connect to host
 kiwiirc.com: max-age too low: 5256000
 kizil.net: could not connect to host
 kjaermaxi.me: did not receive HSTS header
 klauwd.com: did not receive HSTS header
@@ -1892,20 +1908,21 @@ kletterkater.com: did not receive HSTS h
 klicktojob.de: could not connect to host
 kmartin.io: did not receive HSTS header
 knccloud.com: could not connect to host
 kodokushi.fr: could not connect to host
 kolaykaydet.com: did not receive HSTS header
 kollabria.com: max-age too low: 0
 komikito.com: could not connect to host
 kompetenzwerft.de: did not receive HSTS header
+konata.us: could not connect to host
 kontaxis.network: could not connect to host
 kontorhaus-schlachte.de: could not connect to host
 koop-bremen.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
-koophetlokaal.nl: did not receive HSTS header
+koophetlokaal.nl: max-age too low: 300
 koordinate.net: could not connect to host
 korni22.org: did not receive HSTS header
 korsanparti.org: could not connect to host
 kotonehoko.net: could not connect to host
 kotovstyle.ru: could not connect to host
 kr.search.yahoo.com: did not receive HSTS header
 kraynik.com: could not connect to host
 kredite.sale: could not connect to host
@@ -1950,16 +1967,17 @@ langhun.me: did not receive HSTS header
 laozhu.me: did not receive HSTS header
 laserfuchs.de: did not receive HSTS header
 lashstuff.com: did not receive HSTS header
 lask.in: did not receive HSTS header
 latus.xyz: could not connect to host
 lauftrainer-ausbildung.com: did not receive HSTS header
 lavabit.no: could not connect to host
 lavval.com: could not connect to host
+lawformt.com: could not connect to host
 laxatus.com: did not receive HSTS header
 laxiongames.es: could not connect to host
 lbrt.xyz: could not connect to host
 ldarby.me.uk: could not connect to host
 leadership9.com: could not connect to host
 leardev.de: did not receive HSTS header
 learnfrenchfluently.com: did not receive HSTS header
 learningorder.com: could not connect to host
@@ -1975,17 +1993,17 @@ lemp.io: did not receive HSTS header
 lenovogaming.com: did not receive HSTS header
 lentri.com: did not receive HSTS header
 leolana.com: could not connect to host
 leon-jaekel.com: could not connect to host
 leopold.email: could not connect to host
 leopoldina.net: did not receive HSTS header
 leopotamgroup.com: could not connect to host
 leovanna.co.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
-lerasenglish.com: did not receive HSTS header
+leppis-it.de: could not connect to host
 lerner.moscow: did not receive HSTS header
 les-corsaires.net: could not connect to host
 lesdouceursdeliyana.com: could not connect to host
 letras.mus.br: did not receive HSTS header
 letsmultiplayerplay.com: did not receive HSTS header
 letustravel.tk: could not connect to host
 lfullerdesign.com: did not receive HSTS header
 lgiswa.com.au: did not receive HSTS header
@@ -2019,36 +2037,38 @@ limalama.eu: max-age too low: 1
 limiteddata.co.uk: could not connect to host
 limpido.it: could not connect to host
 lindberg.io: did not receive HSTS header
 lingros-test.tk: could not connect to host
 linguaquote.com: did not receive HSTS header
 linkages.org: could not connect to host
 linmi.cc: did not receive HSTS header
 linorman1997.me: could not connect to host
+linux.fi: could not connect to host
 linuxeyecandy.com: could not connect to host
 linuxfixed.it: could not connect to host
 linuxgeek.ro: could not connect to host
 liquorsanthe.in: could not connect to host
 listafirmelor.com: could not connect to host
 litespeed.io: could not connect to host
-liud.im: could not connect to host
 livedemo.io: could not connect to host
 livej.am: could not connect to host
 livi.co: did not receive HSTS header
 lmerza.com: could not connect to host
+loadingdeck.com: did not receive HSTS header
 loafbox.com: could not connect to host
 locktheirphone.com: could not connect to host
 locomotive.ca: did not receive HSTS header
 login.corp.google.com: max-age too low: 7776000 (error ignored - included regardless)
 login.gov: could not connect to host
 loginseite.com: could not connect to host
 loli.bz: could not connect to host
 lolicore.ch: could not connect to host
 lonal.com: could not connect to host
+londonlanguageexchange.com: could not connect to host
 lookastic.co.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.es: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.fr: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.mx: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookastic.ru: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 lookout.com: did not receive HSTS header
@@ -2098,16 +2118,17 @@ m.nu: did not receive HSTS header
 m3-gmbh.de: did not receive HSTS header
 m82labs.com: did not receive HSTS header
 maarten.nyc: did not receive HSTS header
 maartenvandekamp.nl: did not receive HSTS header
 macbolo.com: could not connect to host
 macchaberrycream.com: could not connect to host
 macchedil.com: did not receive HSTS header
 macgeneral.de: did not receive HSTS header
+machon.biz: could not connect to host
 madars.org: did not receive HSTS header
 maddin.ga: could not connect to host
 madebymagnitude.com: did not receive HSTS header
 maderwin.com: did not receive HSTS header
 madusecurity.com: could not connect to host
 mafamane.com: could not connect to host
 mafiareturns.com: max-age too low: 2592000
 magenx.com: did not receive HSTS header
@@ -2139,16 +2160,17 @@ market.android.com: did not receive HSTS
 markrego.com: could not connect to host
 markus-dev.com: did not receive HSTS header
 markusweimar.de: did not receive HSTS header
 marleyresort.com: did not receive HSTS header
 marshut.net: could not connect to host
 martiert.com: could not connect to host
 martijnvhoof.nl: could not connect to host
 martinsfamilyappliance.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
+marumagic.com: did not receive HSTS header
 masjidtawheed.net: did not receive HSTS header
 massotherapeutique.com: did not receive HSTS header
 matatall.com: did not receive HSTS header
 matchneedle.com: could not connect to host
 matrip.de: could not connect to host
 matrix.ac: did not receive HSTS header
 matsuz.com: could not connect to host
 mattberryman.com: did not receive HSTS header
@@ -2203,16 +2225,17 @@ mesmoque.com: did not receive HSTS heade
 metagrader.com: could not connect to host
 metebalci.com: could not connect to host
 meteosherbrooke.com: could not connect to host
 meteosky.net: could not connect to host
 metin2blog.de: did not receive HSTS header
 metis.pw: could not connect to host
 meuemail.pro: could not connect to host
 mexbt.com: could not connect to host
+meyercloud.de: could not connect to host
 mfcatalin.com: could not connect to host
 mhealthdemocamp.com: could not connect to host
 mhict.nl: max-age too low: 0
 mia.to: could not connect to host
 michaelfitzpatrickruth.com: could not connect to host
 michal-kral.cz: could not connect to host
 michalborka.cz: could not connect to host
 micro-dv.ru: could not connect to host
@@ -2223,41 +2246,41 @@ midwestwomenworkers.org: did not receive
 mightydicks.io: could not connect to host
 mightydicks.tech: could not connect to host
 mightysounds.cz: max-age too low: 0
 mijcorijneveld.nl: did not receive HSTS header
 mijn-email.org: could not connect to host
 mikaelemilsson.net: did not receive HSTS header
 mikeburns.com: could not connect to host
 mikeg.de: did not receive HSTS header
-mikek.work: did not receive HSTS header
 mikeology.org: could not connect to host
 mikonmaa.fi: could not connect to host
 miku.be: could not connect to host
 miku.hatsune.my: max-age too low: 5184000
 milesgeek.com: did not receive HSTS header
+mind-moves.es: could not connect to host
 mindoktor.se: did not receive HSTS header
 minecraftserverz.com: could not connect to host
 minecraftvoter.com: could not connect to host
 minikneet.nl: did not receive HSTS header
 minnesotadata.com: could not connect to host
 mirindadomo.ru: did not receive HSTS header
+mirodasilva.be: could not connect to host
 mironized.com: did not receive HSTS header
 mirrorx.com: did not receive HSTS header
 misskey.xyz: could not connect to host
 missrain.tw: could not connect to host
 mister.hosting: could not connect to host
 mitchellrenouf.ca: could not connect to host
 mittenhacks.com: could not connect to host
 mivcon.net: could not connect to host
 miyoshi-kikaku.co.jp: did not receive HSTS header
 miyoshi-kikaku.com: did not receive HSTS header
 mizd.at: could not connect to host
 mizi.name: did not receive HSTS header
-mlcdn.co: could not connect to host
 mlpepilepsy.org: could not connect to host
 mmgazhomeloans.com: did not receive HSTS header
 mnemotiv.com: could not connect to host
 mnetworkingsolutions.co.uk: did not receive HSTS header
 mobifinans.ru: did not receive HSTS header
 mobilekey.co: could not connect to host
 mobilemedics.com: did not receive HSTS header
 mobilethreat.net: could not connect to host
@@ -2363,17 +2386,17 @@ nargileh.nl: could not connect to host
 natalia.io: could not connect to host
 natalt.org: did not receive HSTS header
 nathanmfarrugia.com: did not receive HSTS header
 naturesystems.cz: max-age too low: 0
 natuurbehangnederland.nl: could not connect to host
 nauck.org: did not receive HSTS header
 nav.jobs: could not connect to host
 naval.tf: could not connect to host
-navenlle.com: could not connect to host
+navenlle.com: did not receive HSTS header
 navigate-it-services.de: max-age too low: 0
 navjobs.com: did not receive HSTS header
 nbb.io: could not connect to host
 nbg-ha.de: could not connect to host
 ncc60205.info: could not connect to host
 ncpc.gov: could not connect to host
 nct.org.uk: max-age too low: 1
 nctx.co.uk: did not receive HSTS header
@@ -2391,19 +2414,19 @@ nellafw.org: could not connect to host
 nemno.de: could not connect to host
 nemovement.org: did not receive HSTS header
 neonisi.com: could not connect to host
 nepustil.net: did not receive HSTS header
 neris.io: could not connect to host
 nerven.se: could not connect to host
 nestedquotes.ca: could not connect to host
 netbox.cc: could not connect to host
-netfxharmonics.com: did not receive HSTS header
 netherwind.eu: did not receive HSTS header
 netlilo.com: did not receive HSTS header
+netmagik.com: did not receive HSTS header
 netsight.org: could not connect to host
 netzbit.de: could not connect to host
 netzpolitik.org: did not receive HSTS header
 netztest.at: did not receive HSTS header
 neueonlinecasino2016.com: could not connect to host
 neuralgic.net: could not connect to host
 neutralox.com: max-age too low: 3600
 neveta.com: could not connect to host
@@ -2419,32 +2442,32 @@ ng-security.com: could not connect to ho
 ngine.ch: did not receive HSTS header
 nginxnudes.com: could not connect to host
 ni.search.yahoo.com: did not receive HSTS header
 nibiisclaim.com: could not connect to host
 nicestresser.fr: could not connect to host
 nicky.io: did not receive HSTS header
 nicolasbettag.me: could not connect to host
 niconiconi.xyz: could not connect to host
-niconode.com: did not receive HSTS header
+niconode.com: could not connect to host
 nien.chat: could not connect to host
 nightx.uk: could not connect to host
 niho.jp: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 nikomo.fi: could not connect to host
 nilrem.org: could not connect to host
 ninchisho-online.com: did not receive HSTS header
 ninhs.org: could not connect to host
 nippler.org: did not receive HSTS header
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
-nixien.fr: could not connect to host
 nkinka.de: did not receive HSTS header
 nmctest.net: could not connect to host
 nnya.cat: did not receive HSTS header
 no17sifangjie.cc: could not connect to host
+nobly.de: could not connect to host
 nocallaghan.com: could not connect to host
 nocs.cn: did not receive HSTS header
 noctinus.tk: could not connect to host
 nodari.com.ar: did not receive HSTS header
 nodebrewery.com: could not connect to host
 nodetemple.com: could not connect to host
 noexpect.org: could not connect to host
 noima.com: did not receive HSTS header
@@ -2575,22 +2598,24 @@ orbitcom.de: max-age too low: 0
 orbograph-hrcm.com: did not receive HSTS header
 orionfcu.com: did not receive HSTS header
 orleika.ml: could not connect to host
 osaiyuwu.com: could not connect to host
 oslfoundation.org: could not connect to host
 ossan-kobe-gourmet.com: did not receive HSTS header
 ossbinaries.com: could not connect to host
 osteammate.com: did not receive HSTS header
+osticketawesome.com: did not receive HSTS header
 otakuworld.de: could not connect to host
 othercode.nl: could not connect to host
 othermedia.cc: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 otherstuff.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 otichi.com: did not receive HSTS header
 ottospora.nl: could not connect to host
+otvaracie-hodiny.sk: could not connect to host
 ourbank.com: did not receive HSTS header
 outdoorproducts.com: did not receive HSTS header
 outetc.com: could not connect to host
 outreachbuddy.com: could not connect to host
 outsider.im: could not connect to host
 ouvirmusica.com.br: did not receive HSTS header
 ovenapp.io: did not receive HSTS header
 overclockers.ge: could not connect to host
@@ -2607,44 +2632,41 @@ packlane.com: did not receive HSTS heade
 pader-deko.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 paestbin.com: could not connect to host
 pagerate.io: did not receive HSTS header
 pagetoimage.com: could not connect to host
 paisaone.com: did not receive HSTS header
 paku.me: could not connect to host
 pamsoft.pl: max-age too low: 0
 panaceallc.net: could not connect to host
-panelomix.net: could not connect to host
 pants-off.xyz: could not connect to host
 pantsu.cat: did not receive HSTS header
 papeda.net: could not connect to host
 papercard.co.uk: did not receive HSTS header
 papierniak.net: could not connect to host
 parent5446.us: could not connect to host
 parentmail.co.uk: did not receive HSTS header
 parodybit.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 parpaing-paillette.net: could not connect to host
 particonpsplus.it: could not connect to host
 partijtjevoordevrijheid.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
-partirkyoto.jp: did not receive HSTS header
 partyvan.it: could not connect to host
 partyvan.moe: could not connect to host
 partyvan.nl: could not connect to host
 partyvan.se: could not connect to host
 passwordbox.com: did not receive HSTS header
 passwordrevelator.net: did not receive HSTS header
 passwords.google.com: did not receive HSTS header (error ignored - included regardless)
 pastaf.com: could not connect to host
 paste.fedoraproject.org: did not receive HSTS header
 paste.linode.com: could not connect to host
 pastebin.linode.com: could not connect to host
 pastenib.com: could not connect to host
 paster.li: did not receive HSTS header
 patientinsight.net: could not connect to host
-patrz.eu: could not connect to host
 patt.us: did not receive HSTS header
 patterson.mp: could not connect to host
 paulchen.at: did not receive HSTS header
 paulyang.cn: did not receive HSTS header
 paxwinkel.nl: did not receive HSTS header
 pay.gigahost.dk: did not receive HSTS header
 payments.google.com: did not receive HSTS header (error ignored - included regardless)
 payroll.ch: did not receive HSTS header
@@ -2654,36 +2676,37 @@ pc-nf.de: could not connect to host
 pcfun.net: did not receive HSTS header
 pchax.net: did not receive HSTS header
 peissen.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 pekkapikkarainen.fi: could not connect to host
 pekkarik.ru: could not connect to host
 penguinclientsystem.com: did not receive HSTS header
 pensacolawinterfest.org: could not connect to host
 pentagram.me: could not connect to host
+pepchid.com: did not receive HSTS header
 pepperhead.com: could not connect to host
 pepperworldhotshop.de: did not receive HSTS header
 perfectionis.me: could not connect to host
 performous.org: could not connect to host
 perlwork.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 perplex.nl: did not receive HSTS header
 perroud.pro: max-age too low: 2592000
 personaldatabasen.no: could not connect to host
 personalinjurylist.com: did not receive HSTS header
+persson.im: could not connect to host
 perthdevicelab.com: did not receive HSTS header
 pet-nsk.ru: could not connect to host
 petchart.net: could not connect to host
 petplum.com: did not receive HSTS header
 petrachuk.ru: did not receive HSTS header
 petravdbos.nl: did not receive HSTS header
 petrolplus.ru: did not receive HSTS header
 pettsy.com: could not connect to host
 pewboards.com: could not connect to host
 pgpm.io: could not connect to host
-phantasie.cc: could not connect to host
 phillprice.com: could not connect to host
 phonenumberinfo.co.uk: could not connect to host
 phongmay24h.com: could not connect to host
 phurl.de: could not connect to host
 pickr.co: could not connect to host
 picotronic.biz: could not connect to host
 picscare.co.uk: did not receive HSTS header
 pijuice.com: could not connect to host
@@ -2705,22 +2728,22 @@ pixel.google.com: did not receive HSTS h
 pixelcode.com.au: max-age too low: 0
 pixelhero.co.uk: did not receive HSTS header
 pixi.me: could not connect to host
 pj83.duckdns.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 pk.search.yahoo.com: did not receive HSTS header
 placefade.com: could not connect to host
 placollection.org: could not connect to host
 plaettliaktion.ch: did not receive HSTS header
-plaintech.net.au: could not connect to host
 platform.lookout.com: could not connect to host
 play.google.com: did not receive HSTS header (error ignored - included regardless)
 playkh.com: did not receive HSTS header
 playmaker.io: could not connect to host
 playnation.io: did not receive HSTS header
+playsoundevents.be: could not connect to host
 plixer.com: did not receive HSTS header
 plogable.co: could not connect to host
 plothost.com: did not receive HSTS header
 ploup.net: could not connect to host
 pmnts.io: could not connect to host
 po.gl: did not receive HSTS header
 poiema.com.sg: did not receive HSTS header
 pol.in.th: could not connect to host
@@ -2741,19 +2764,20 @@ postcodewise.co.uk: did not receive HSTS
 posterspy.com: did not receive HSTS header
 postscheduler.org: could not connect to host
 posylka.de: did not receive HSTS header
 potatofrom.space: could not connect to host
 poussinooz.fr: could not connect to host
 povitria.net: could not connect to host
 power-of-interest.com: did not receive HSTS header
 power99press.com: did not receive HSTS header
-powerplannerapp.com: could not connect to host
+powerplannerapp.com: did not receive HSTS header
 powerxequality.com: could not connect to host
 ppr-truby.ru: could not connect to host
+ppy3.com: did not receive HSTS header
 pr.search.yahoo.com: did not receive HSTS header
 prefontaine.name: could not connect to host
 prego-shop.de: did not receive HSTS header
 preissler.co.uk: could not connect to host
 prelist.org: did not receive HSTS header
 pressfreedomfoundation.org: did not receive HSTS header
 preworkout.me: could not connect to host
 prezola.com: did not receive HSTS header
@@ -2776,17 +2800,16 @@ prontolight.com: did not receive HSTS he
 prosocialmachines.com: could not connect to host
 prosoft.sk: max-age too low: 0
 prosperident.com: did not receive HSTS header
 prowhisky.de: did not receive HSTS header
 proximato.com: could not connect to host
 proxybay.al: could not connect to host
 proxybay.club: could not connect to host
 proxybay.info: did not receive HSTS header
-prxio.date: could not connect to host
 prxio.site: did not receive HSTS header
 prytkov.com: did not receive HSTS header
 psw.academy: did not receive HSTS header
 psw.consulting: did not receive HSTS header
 ptn.moscow: could not connect to host
 ptonet.com: did not receive HSTS header
 pubkey.is: could not connect to host
 puiterwijk.org: could not connect to host
@@ -2813,27 +2836,28 @@ qrlending.com: did not receive HSTS head
 quail.solutions: could not connect to host
 quantacloud.ch: could not connect to host
 quantenteranik.eu: could not connect to host
 quantumcourse.org: did not receive HSTS header
 queercoders.com: did not receive HSTS header
 quemmeliga.com: could not connect to host
 questsandrewards.com: could not connect to host
 quranserver.net: could not connect to host
-qvi.st: did not receive HSTS header
+qvi.st: could not connect to host
 qwaser.fr: could not connect to host
 qwilink.me: did not receive HSTS header
 r10n.com: did not receive HSTS header
 r15.me: could not connect to host
 r3bl.me: did not receive HSTS header
 raajheshkannaa.com: could not connect to host
 radicaleducation.net: could not connect to host
 radiormi.com: did not receive HSTS header
 rafaelcz.de: could not connect to host
 rainbowbarracuda.com: could not connect to host
+raissarobles.com: could not connect to host
 ramonj.nl: could not connect to host
 randomcage.com: did not receive HSTS header
 rankthespot.com: did not receive HSTS header
 rapidresearch.me: could not connect to host
 rapidthunder.io: could not connect to host
 rasing.me: did not receive HSTS header
 ratajczak.fr: could not connect to host
 raulfraile.net: could not connect to host
@@ -2848,16 +2872,17 @@ re-customer.net: could not connect to ho
 readr.pw: could not connect to host
 realmic.net: could not connect to host
 realmofespionage.com: could not connect to host
 reardenporn.com: could not connect to host
 recommended.reviews: could not connect to host
 redar.xyz: did not receive HSTS header
 reddiseals.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 reddit.com: did not receive HSTS header
+rede.ca: did not receive HSTS header
 redicabo.de: could not connect to host
 redlatam.org: did not receive HSTS header
 redmbk.com: could not connect to host
 regaloaks.com: did not receive HSTS header
 regalpalms.com: did not receive HSTS header
 regenbogenwald.de: did not receive HSTS header
 regenerescence.com: did not receive HSTS header
 reggae-cdmx.com: did not receive HSTS header
@@ -2906,35 +2931,35 @@ rippleunion.com: could not connect to ho
 riskmgt.com.au: could not connect to host
 rj.gg: could not connect to host
 rk6.cz: could not connect to host
 rkmantpur.org: did not receive HSTS header
 rme.li: did not receive HSTS header
 roan24.pl: did not receive HSTS header
 robertglastra.com: could not connect to host
 robigalia.org: did not receive HSTS header
-robin.info: could not connect to host
-robjager-fotografie.nl: could not connect to host
 robtex.net: did not receive HSTS header
 robtex.org: did not receive HSTS header
 rochman.id: could not connect to host
 rocksberg.net: did not receive HSTS header
 roddis.net: did not receive HSTS header
 rodney.id.au: did not receive HSTS header
 rodosto.com: did not receive HSTS header
 roeper.party: could not connect to host
 romans-place.me.uk: did not receive HSTS header
 ronvandordt.info: did not receive HSTS header
 ronwo.de: max-age too low: 1
 room-checkin24.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 rootforum.org: did not receive HSTS header
+roots-example-project.com: could not connect to host
 rootservice.org: did not receive HSTS header
 rootwpn.com: could not connect to host
 rotterdamjazz.info: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 roundtheme.com: did not receive HSTS header
+rous.se: could not connect to host
 rout0r.org: did not receive HSTS header
 rouvray.org: could not connect to host
 rr.in.th: could not connect to host
 rrke.cc: did not receive HSTS header
 rsajeey.info: could not connect to host
 rsauget.fr: could not connect to host
 rsf.io: could not connect to host
 rsmaps.org: could not connect to host
@@ -2977,23 +3002,21 @@ salud.top: did not receive HSTS header
 saml2.com: could not connect to host
 sampoznay.ru: did not receive HSTS header
 samraskauskas.com: could not connect to host
 samsen.club: did not receive HSTS header
 sandviks.com: did not receive HSTS header
 sansemea.com: could not connect to host
 sapk.fr: could not connect to host
 sarah-beckett-harpist.com: did not receive HSTS header
-sarahsweetlife.com: could not connect to host
 sarisonproductions.com: did not receive HSTS header
 saruwebshop.co.za: did not receive HSTS header
 satmep.com: did not receive HSTS header
 satriyowibowo.my.id: did not receive HSTS header
 satsukii.moe: did not receive HSTS header
-saturne.tk: could not connect to host
 saturngames.co.uk: did not receive HSTS header
 saucyfox.net: did not receive HSTS header
 saunasandstuff.ca: did not receive HSTS header
 saunasandstuff.com: did not receive HSTS header
 save.gov: could not connect to host
 saveaward.gov: could not connect to host
 saveyour.biz: did not receive HSTS header
 sawamura-rental.com: did not receive HSTS header
@@ -3007,27 +3030,29 @@ schreiber-netzwerk.eu: did not receive H
 schrodinger.io: could not connect to host
 scienceathome.org: did not receive HSTS header
 scooshonline.co.uk: did not receive HSTS header
 scotbirchfield.com: did not receive HSTS header
 scrambl.is: could not connect to host
 scrambler.in: could not connect to host
 scrapings.net: could not connect to host
 screencaster.io: did not receive HSTS header
+screenlight.tv: did not receive HSTS header
 screenresolution.space: could not connect to host
 scribe.systems: could not connect to host
 script.google.com: did not receive HSTS header (error ignored - included regardless)
 scriptict.nl: could not connect to host
 sdmoscow.ru: could not connect to host
 sdrobs.com: did not receive HSTS header
 sdsl-speedtest.de: could not connect to host
 search-one.de: did not receive HSTS header
 sebastian-lutsch.de: could not connect to host
 sebster.com: did not receive HSTS header
 secandtech.com: could not connect to host
+secpatrol.de: could not connect to host
 sectia22.ro: could not connect to host
 sectun.com: did not receive HSTS header
 secure-games.us: could not connect to host
 secureradio.net: could not connect to host
 securesuisse.ch: could not connect to host
 security-carpet.com: could not connect to host
 security.google.com: did not receive HSTS header (error ignored - included regardless)
 securityinet.biz: did not receive HSTS header
@@ -3059,31 +3084,32 @@ seon.me: did not receive HSTS header
 seowarp.net: did not receive HSTS header
 seq.tf: did not receive HSTS header
 serfdom.io: did not receive HSTS header
 serized.pw: could not connect to host
 servercode.ca: did not receive HSTS header
 serverdensity.io: did not receive HSTS header
 servergno.me: did not receive HSTS header
 seryo.moe: could not connect to host
-sesha.co.za: could not connect to host
+seryovpn.com: could not connect to host
 setphaserstostun.org: could not connect to host
 setuid.de: could not connect to host
 setuid.io: did not receive HSTS header
 seyahatsagliksigortalari.com: could not connect to host
 shadoom.com: did not receive HSTS header
 shadowmorph.info: did not receive HSTS header
 shadowsocks.net: could not connect to host
 shakepeers.org: did not receive HSTS header
 shakespearesolutions.com.au: did not receive HSTS header
 shanesage.com: could not connect to host
 shanewadleigh.com: could not connect to host
 shaobin.wang: could not connect to host
 sharepass.pw: could not connect to host
 sharescope.co.uk: max-age too low: 14400
+sharevari.com: did not receive HSTS header
 shareworx.net: could not connect to host
 shauncrowley.co.uk: could not connect to host
 shaunwheelhou.se: could not connect to host
 shawnh.net: could not connect to host
 shellsec.pw: did not receive HSTS header
 shibe.club: could not connect to host
 shiftins.com: did not receive HSTS header
 shiinko.com: could not connect to host
@@ -3156,42 +3182,43 @@ smusg.com: did not receive HSTS header
 snailing.org: could not connect to host
 snapappointments.com: did not receive HSTS header
 snapappts.com: could not connect to host
 snapworks.net: did not receive HSTS header
 sneberger.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 snel4u.nl: could not connect to host
 snelwerk.be: did not receive HSTS header
 sng.my: could not connect to host
+sniderman.eu.org: could not connect to host
 snoqualmiefiber.org: did not receive HSTS header
 sobabox.ru: could not connect to host
 sobie.ch: could not connect to host
 sobotkama.eu: did not receive HSTS header
 soccergif.com: could not connect to host
 soci.ml: did not receive HSTS header
 socialbillboard.com: could not connect to host
-socialdevelop.biz: did not receive HSTS header
+socialdevelop.biz: could not connect to host
 socialhams.net: did not receive HSTS header
 socialhead.io: could not connect to host
 socialspirit.com.br: did not receive HSTS header
 sockeye.cc: could not connect to host
 socomponents.co.uk: did not receive HSTS header
-sodiao.cc: could not connect to host
 sogeek.me: did not receive HSTS header
 solidfuelappliancespares.co.uk: did not receive HSTS header
 solinter.com.br: did not receive HSTS header
 soll-i.ch: did not receive HSTS header
 solsystems.ru: could not connect to host
 someshit.xyz: could not connect to host
 somethingnew.xyz: did not receive HSTS header
 songzhuolun.com: did not receive HSTS header
 sonic.sk: max-age too low: 0
 sonicrainboom.rocks: did not receive HSTS header
+sosaka.ml: could not connect to host
 sotar.us: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
-sotiran.com: could not connect to host
+sotiran.com: did not receive HSTS header
 sotor.de: did not receive HSTS header
 soulboy.io: did not receive HSTS header
 soulema.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 soulfulglamour.uk: could not connect to host
 sourcelair.com: did not receive HSTS header
 sourceway.de: could not connect to host
 southside-crew.club: could not connect to host
 southworcestershiregpservices.co.uk: could not connect to host
@@ -3236,16 +3263,17 @@ srevilak.net: did not receive HSTS heade
 srna.sk: could not connect to host
 srrr.ca: could not connect to host
 ss.wtf: did not receive HSTS header
 ssersay.com: max-age too low: 0
 ssl.panoramio.com: did not receive HSTS header
 ssl.rip: could not connect to host
 ssmato.me: could not connect to host
 ssnc.org: max-age too low: 300
+sss3s.com: did not receive HSTS header
 stabletoken.com: could not connect to host
 stadjerspasonline.nl: could not connect to host
 stahl.xyz: could not connect to host
 stateofexception.io: could not connect to host
 static.or.at: did not receive HSTS header
 staticanime.net: could not connect to host
 stationaryjourney.com: did not receive HSTS header
 stationnementdenuit.ca: did not receive HSTS header
@@ -3283,25 +3311,25 @@ stuartbaxter.co: could not connect to ho
 student-scientist.org: did not receive HSTS header
 studentresearcher.org: did not receive HSTS header
 studentrightsadvocate.org: could not connect to host
 studentskydenik.cz: could not connect to host
 studenttravel.cz: did not receive HSTS header
 studybay.com: did not receive HSTS header
 studydrive.net: did not receive HSTS header
 stugb.de: did not receive HSTS header
-stupendous.net: could not connect to host
+sturbock.me: could not connect to host
 stw-group.at: could not connect to host
 subbing.work: could not connect to host
 subdimension.org: did not receive HSTS header
 subrosa.io: could not connect to host
 subtitle.rip: could not connect to host
 sudo.li: did not receive HSTS header
+suian.or.jp: max-age too low: 0
 suite73.org: could not connect to host
-suki.moe: could not connect to host
 suksit.com: could not connect to host
 sumoatm.com: did not receive HSTS header
 sumoscout.de: did not receive HSTS header
 suncountrymarine.com: did not receive HSTS header
 sunflyer.cn: did not receive HSTS header
 sunshinepress.org: could not connect to host
 superbabysitting.ch: could not connect to host
 supereight.net: did not receive HSTS header
@@ -3326,35 +3354,32 @@ sylvanorder.com: could not connect to ho
 synackr.com: could not connect to host
 syncer.jp: did not receive HSTS header
 syncserve.net: did not receive HSTS header
 syneic.com: did not receive HSTS header
 syno.gq: could not connect to host
 sysadmin.xyz: could not connect to host
 syso.name: could not connect to host
 szaszm.tk: max-age too low: 0
-t-point.eu: could not connect to host
 t.facebook.com: did not receive HSTS header
-taabe.xyz: did not receive HSTS header
+taabe.xyz: could not connect to host
 tablet.facebook.com: did not receive HSTS header
-tacomafia.net: could not connect to host
+tacomafia.net: did not receive HSTS header
 tadigitalstore.com: could not connect to host
 tafoma.com: did not receive HSTS header
 tageau.com: could not connect to host
 taglondon.org: did not receive HSTS header
-tails.com.ar: could not connect to host
 talk.google.com: did not receive HSTS header (error ignored - included regardless)
 talktwincities.com: could not connect to host
 tallr.se: could not connect to host
 tallshoe.com: could not connect to host
 tandarts-haarlem.nl: did not receive HSTS header
 tanzhijun.com: did not receive HSTS header
 tapfinder.ca: could not connect to host
 tapka.cz: did not receive HSTS header
-taranis.re: could not connect to host
 taravancil.com: did not receive HSTS header
 tarhauskielto.fi: did not receive HSTS header
 tartaros.fi: could not connect to host
 taskstats.com: could not connect to host
 taskulu.ir: could not connect to host
 tasmansecurity.com: could not connect to host
 tastyyy.co: could not connect to host
 tauchkater.de: could not connect to host
@@ -3480,19 +3505,19 @@ tobiasofficial.at: could not connect to 
 todo.is: did not receive HSTS header
 todobazar.es: could not connect to host
 tokyopopline.com: did not receive HSTS header
 tollmanz.com: did not receive HSTS header
 tomberek.info: could not connect to host
 tomeara.net: could not connect to host
 tomharling.co.uk: max-age too low: 86400
 tomharling.uk: max-age too low: 86400
+tomharris.tech: could not connect to host
 tomlankhorst.nl: did not receive HSTS header
 tommsy.com: did not receive HSTS header
-tommyads.com: could not connect to host
 tonburi.jp: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 tonyfantjr.com: could not connect to host
 toomanypillows.com: could not connect to host
 topbargains.com.au: did not receive HSTS header
 topdevbox.net: could not connect to host
 topmarine.se: could not connect to host
 topnewstoday.org: could not connect to host
 topshelfguild.com: could not connect to host
@@ -3514,25 +3539,27 @@ traeningsprojekt.dk: did not receive HST
 traindb.nl: could not connect to host
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 transportal.sk: did not receive HSTS header
 treeby.net: could not connect to host
 trendberry.ru: could not connect to host
 trinityaffirmations.com: max-age too low: 0
 trinitycore.org: max-age too low: 2592000
 tripdelta.com: did not receive HSTS header
+triple-mmm.de: could not connect to host
 trixies-wish.nz: could not connect to host
 trusitio.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 trustmeimfancy.com: could not connect to host
 trybind.com: could not connect to host
 ts2.se: did not receive HSTS header
 tsecy.com: did not receive HSTS header
 tsgoc.com: did not receive HSTS header
 tssouthernpower.com: max-age too low: 0
 tuingereedschappen.net: could not connect to host
+tunai.id: could not connect to host
 tuningblog.eu: did not receive HSTS header
 turnik-67.ru: could not connect to host
 tuturulianda.com: could not connect to host
 tuvalie.com: could not connect to host
 tuxcall.de: could not connect to host
 tv.search.yahoo.com: could not connect to host
 tvtubeflix.com: did not receive HSTS header
 tvz-materijali.com: could not connect to host
@@ -3556,33 +3583,33 @@ tyrelius.com: did not receive HSTS heade
 tyroproducts.eu: did not receive HSTS header
 tzappa.net: could not connect to host
 u-blox.com: did not receive HSTS header
 ua.search.yahoo.com: did not receive HSTS header
 ubicloud.de: could not connect to host
 ublox.com: did not receive HSTS header
 ubuntuhot.com: did not receive HSTS header
 uega.net: did not receive HSTS header
+ueu.me: could not connect to host
 ufgaming.com: did not receive HSTS header
 ufotable.uk: could not connect to host
 ui8.net: max-age too low: 86400
 ukas.com: did not receive HSTS header
 ukdropshipment.co.uk: did not receive HSTS header
 ukdropshipment.com: did not receive HSTS header
 ukrgadget.com: could not connect to host
 ulmo.dk: could not connect to host
 ultros.io: did not receive HSTS header
 umidev.com: could not connect to host
 umie.cc: did not receive HSTS header
 unbanthe.net: could not connect to host
 unblocked.host: could not connect to host
 unblocked.win: could not connect to host
 unccdesign.club: could not connect to host
 undernet.uy: did not receive HSTS header
-underskatten.tk: could not connect to host
 unfiltered.nyc: did not receive HSTS header
 uni-games.com: could not connect to host
 unicooo.com: did not receive HSTS header
 unison.com: could not connect to host
 unitedcyberdevelopment.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 unitel2000.de: could not connect to host
 university4industry.com: did not receive HSTS header
 univz.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
@@ -3600,16 +3627,17 @@ upldr.pw: could not connect to host
 upr.com.ua: could not connect to host
 uprotect.it: could not connect to host
 upstats.eu: could not connect to host
 urandom.eu.org: did not receive HSTS header
 url.rw: could not connect to host
 urphp.com: could not connect to host
 us-immigration.com: did not receive HSTS header
 usaa.com: did not receive HSTS header
+usaab.org: could not connect to host
 uscitizenship.info: did not receive HSTS header
 used-in.jp: did not receive HSTS header
 usercare.com: did not receive HSTS header
 userify.com: did not receive HSTS header
 ustr.gov: max-age too low: 86400
 utumno.ch: could not connect to host
 uvarov.pw: did not receive HSTS header
 uy.search.yahoo.com: did not receive HSTS header
@@ -3639,47 +3667,47 @@ vcr.re: could not connect to host
 veblen.com: could not connect to host
 vechkasov.ru: did not receive HSTS header
 vemokin.net: could not connect to host
 venixplays-stream.ml: could not connect to host
 verifikatorindonesia.com: could not connect to host
 vermontcareergateway.org: could not connect to host
 versia.ru: did not receive HSTS header
 veryhax.de: could not connect to host
-vestacp.top: could not connect to host
 vetmgmt.com: could not connect to host
 vfree.org: could not connect to host
 vglimg.com: could not connect to host
 vhost.co.id: could not connect to host
 viadeux.com: could not connect to host
 videnskabsklubben.dk: did not receive HSTS header
 videomuz.com: did not receive HSTS header
 vidz.ga: could not connect to host
 vieaw.com: could not connect to host
+viewsea.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 viktorsvantesson.net: did not receive HSTS header
 villenvinkit.com: could not connect to host
 vincentkooijman.at: did not receive HSTS header
 vincentkooijman.nl: did not receive HSTS header
 vintageheartcoffee.com: did not receive HSTS header
 vio.no: did not receive HSTS header
 viperdns.com: could not connect to host
 vipmusic.ga: could not connect to host
 vipnettikasinoklubi.com: could not connect to host
+visiontree-beta.eu: could not connect to host
 visitbroadstairs.com: could not connect to host
 vissanum.com: did not receive HSTS header
 vistarait.com: did not receive HSTS header
 vitalorange.com: did not receive HSTS header
 viva-french.com: did not receive HSTS header
 vlastimilburian.cz: did not receive HSTS header
 vlora.city: could not connect to host
 vm0.eu: did not receive HSTS header
 vmrdev.com: could not connect to host
 voceinveste.com: did not receive HSTS header
 voicesuk.co.uk: did not receive HSTS header
-voidi.ca: could not connect to host
 volcrado.com: could not connect to host
 voliere-info.nl: did not receive HSTS header
 vortexhobbies.com: did not receive HSTS header
 votocek.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 votockova.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 vox.vg: did not receive HSTS header
 vpl.me: did not receive HSTS header
 vpn-byen.dk: did not receive HSTS header
@@ -3688,32 +3716,32 @@ vrtak-cz.net: could not connect to host
 vvl.me: could not connect to host
 vxstream-sandbox.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 vyncke.org: max-age too low: 2678400
 vyskocil.eu: did not receive HSTS header
 vzk.io: could not connect to host
 w4a.fr: max-age too low: 0
 w4xzr.top: could not connect to host
 w4xzr.xyz: could not connect to host
-wait.jp: could not connect to host
 wait.moe: could not connect to host
-waixingrenfuli.vip: did not receive HSTS header
 wakapp.de: could not connect to host
 walkeryoung.ca: could not connect to host
 wallet.google.com: did not receive HSTS header (error ignored - included regardless)
 wallsblog.dk: could not connect to host
 walnutgaming.co.uk: could not connect to host
+wan.pp.ua: could not connect to host
 wanban.io: could not connect to host
 wangqiliang.xn--fiqs8s: could not connect to host
 wangzuan168.cc: did not receive HSTS header
 wapjt.cn: could not connect to host
 warandpeace.xyz: could not connect to host
 warhistoryonline.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 warmlyyours.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 warped.com: did not receive HSTS header
+waschpark-hantschel.de: did not receive HSTS header
 watchium.com: did not receive HSTS header
 watsonhall.uk: could not connect to host
 wave.is: could not connect to host
 wavefrontsystemstech.com: could not connect to host
 wealthfactory.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 wear2work.nl: did not receive HSTS header
 wearandcare.net: could not connect to host
 weaverhairextensions.nl: did not receive HSTS header
@@ -3736,16 +3764,17 @@ webwork.pw: could not connect to host
 weddingenvelopes.co.uk: did not receive HSTS header
 weddingibiza.nl: could not connect to host
 weekly.fyi: could not connect to host
 wegenaer.nl: could not connect to host
 wellsolveit.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 weltmeisterschaft.net: could not connect to host
 weme.eu: could not connect to host
 wendalyncheng.com: could not connect to host
+wer-kommt-her.de: could not connect to host
 werdeeintimo.de: did not receive HSTS header
 werkenbijkfc.nl: did not receive HSTS header
 werkplaatsoost.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 werkruimtebottendaal.nl: did not receive HSTS header
 wesleyharris.ca: did not receive HSTS header
 westendzone.com: max-age too low: 0
 westerhoud.nl: did not receive HSTS header
 wettbuero.de: did not receive HSTS header
@@ -3851,16 +3880,17 @@ xellos.ml: could not connect to host
 xendo.net: did not receive HSTS header
 xenesisziarovky.sk: could not connect to host
 xett.com: did not receive HSTS header
 xf-liam.com: could not connect to host
 xfive.de: did not receive HSTS header
 xiaody.me: could not connect to host
 xiaolvmu.me: could not connect to host
 xiaoxiao.im: could not connect to host
+ximens.me: did not receive HSTS header
 xisa.it: could not connect to host
 xiyu.moe: could not connect to host
 xn--3lqp21gwna.xn--fiqs8s: could not connect to host
 xn--3lqp21gwna.xn--fiqz9s: could not connect to host
 xn--3lqt7ir4md4tzwa.xn--fiqs8s: could not connect to host
 xn--4dbjwf8c.cf: could not connect to host
 xn--4dbjwf8c.ga: could not connect to host
 xn--4dbjwf8c.gq: could not connect to host
@@ -3873,16 +3903,17 @@ xn--lgb3a8bcpn.cf: could not connect to 
 xn--lgb3a8bcpn.ga: could not connect to host
 xn--lgb3a8bcpn.gq: could not connect to host
 xn--lgb3a8bcpn.ml: could not connect to host
 xn--ls8hi7a.tk: could not connect to host
 xn--maraa-rta.org: could not connect to host
 xn--mgbbh2a9fub.xn--ngbc5azd: did not receive HSTS header
 xn--neb-tma3u8u.xyz: could not connect to host
 xng.io: did not receive HSTS header
+xobox.me: could not connect to host
 xombra.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 xpi.fr: could not connect to host
 xplore-dna.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 xsmobile.de: could not connect to host
 xtream-hosting.com: could not connect to host
 xtream-hosting.de: could not connect to host
 xtream-hosting.eu: could not connect to host
 xtreamhosting.eu: could not connect to host
@@ -3915,16 +3946,17 @@ ynsn.nl: did not receive HSTS header
 yokeepo.com: max-age too low: 0
 yoloboatrentals.com: did not receive HSTS header
 yoloprod.fr: could not connect to host
 yoloseo.com: could not connect to host
 youcontrol.ru: could not connect to host
 youngandunited.nl: did not receive HSTS header
 yourstrongbox.com: could not connect to host
 yout.com: max-age too low: 60000
+ys-shop.biz: could not connect to host
 yu.gg: did not receive HSTS header
 yuan.ga: did not receive HSTS header
 yuhen.ru: did not receive HSTS header
 yuko.moe: could not connect to host
 yukontec.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 yunzhu.li: did not receive HSTS header
 yunzhu.org: could not connect to host
 yux.io: did not receive HSTS header
@@ -3940,38 +3972,39 @@ zarooba.com: did not receive HSTS header
 zary.me: could not connect to host
 zbigniewgalucki.eu: did not receive HSTS header
 zbp.at: did not receive HSTS header
 zebrababy.cn: did not receive HSTS header
 zebry.nl: could not connect to host
 zefiris.org: did not receive HSTS header
 zefu.ca: could not connect to host
 zeitpunkt-kulturmagazin.de: did not receive HSTS header
-zeitzer-turngala.de: could not connect to host
 zelezny.uk: did not receive HSTS header
 zelfstandigemakelaars.net: did not receive HSTS header
 zenlogic.com: could not connect to host
 zenpayroll.com: did not receive HSTS header
 zentraler-kreditausschuss.de: did not receive HSTS header
 zentralwolke.de: did not receive HSTS header
 zera.com.au: could not connect to host
 zett4.me: could not connect to host
 zeytin.pro: could not connect to host
 zh.search.yahoo.com: did not receive HSTS header
 zhaojin97.cn: did not receive HSTS header
 zhendingresources.com: max-age too low: 0
 zigcore.com.br: could not connect to host
 zirtue.io: could not connect to host
+ziyuanabc.xyz: could not connect to host
 zking.ga: could not connect to host
 zocken.com: could not connect to host
 zomerschoen.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121"  data: no]
 zoneminder.com: did not receive HSTS header
 zoo24.de: did not receive HSTS header
 zoomingin.net: max-age too low: 2592000
+zorgclustertool.nl: could not connect to host
 zortium.report: could not connect to host
 zoznamrealit.sk: did not receive HSTS header
 zqhong.com: could not connect to host
 zrn.in: did not receive HSTS header
 ztan.tk: could not connect to host
 zten.org: could not connect to host
-zulu7.com: could not connect to host
 zvncloud.com: did not receive HSTS header
+zwy.me: did not receive HSTS header
 zyf.pw: could not connect to host
--- a/security/manager/ssl/nsSTSPreloadList.inc
+++ b/security/manager/ssl/nsSTSPreloadList.inc
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsSiteSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include <stdint.h>
-const PRTime gPreloadListExpirationTime = INT64_C(1491056514003000);
+const PRTime gPreloadListExpirationTime = INT64_C(1491229264259000);
 
 static const char kSTSHostTable[] = {
   /* "007-preisvergleich.de", true */ '0', '0', '7', '-', 'p', 'r', 'e', 'i', 's', 'v', 'e', 'r', 'g', 'l', 'e', 'i', 'c', 'h', '.', 'd', 'e', '\0',
   /* "007sascha.de", true */ '0', '0', '7', 's', 'a', 's', 'c', 'h', 'a', '.', 'd', 'e', '\0',
   /* "00f.net", true */ '0', '0', 'f', '.', 'n', 'e', 't', '\0',
   /* "01electronica.com.ar", true */ '0', '1', 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 'a', '.', 'c', 'o', 'm', '.', 'a', 'r', '\0',
   /* "01seguridad.com.ar", true */ '0', '1', 's', 'e', 'g', 'u', 'r', 'i', 'd', 'a', 'd', '.', 'c', 'o', 'm', '.', 'a', 'r', '\0',
   /* "050media.nl", true */ '0', '5', '0', 'm', 'e', 'd', 'i', 'a', '.', 'n', 'l', '\0',
@@ -150,16 +150,17 @@ static const char kSTSHostTable[] = {
   /* "3r.org.uk", true */ '3', 'r', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0',
   /* "3s-hosting.de", true */ '3', 's', '-', 'h', 'o', 's', 't', 'i', 'n', 'g', '.', 'd', 'e', '\0',
   /* "3sreporting.com", true */ '3', 's', 'r', 'e', 'p', 'o', 'r', 't', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
   /* "3timegear.com", true */ '3', 't', 'i', 'm', 'e', 'g', 'e', 'a', 'r', '.', 'c', 'o', 'm', '\0',
   /* "3yearloans.com", true */ '3', 'y', 'e', 'a', 'r', 'l', 'o', 'a', 'n', 's', '.', 'c', 'o', 'm', '\0',
   /* "4-1-where.com", true */ '4', '-', '1', '-', 'w', 'h', 'e', 'r', 'e', '.', 'c', 'o', 'm', '\0',
   /* "4-it.de", true */ '4', '-', 'i', 't', '.', 'd', 'e', '\0',
   /* "403.ch", true */ '4', '0', '3', '.', 'c', 'h', '\0',
+  /* "404.sh", true */ '4', '0', '4', '.', 's', 'h', '\0',
   /* "404404.info", true */ '4', '0', '4', '4', '0', '4', '.', 'i', 'n', 'f', 'o', '\0',
   /* "4096bit.de", true */ '4', '0', '9', '6', 'b', 'i', 't', '.', 'd', 'e', '\0',
   /* "41-where.com", true */ '4', '1', '-', 'w', 'h', 'e', 'r', 'e', '.', 'c', 'o', 'm', '\0',
   /* "41844.de", true */ '4', '1', '8', '4', '4', '.', 'd', 'e', '\0',
   /* "41where.com", true */ '4', '1', 'w', 'h', 'e', 'r', 'e', '.', 'c', 'o', 'm', '\0',
   /* "4500.co.il", true */ '4', '5', '0', '0', '.', 'c', 'o', '.', 'i', 'l', '\0',
   /* "4azino777.ru", true */ '4', 'a', 'z', 'i', 'n', 'o', '7', '7', '7', '.', 'r', 'u', '\0',
   /* "4cclothing.com", true */ '4', 'c', 'c', 'l', 'o', 't', 'h', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
@@ -190,16 +191,17 @@ static const char kSTSHostTable[] = {
   /* "700.az", true */ '7', '0', '0', '.', 'a', 'z', '\0',
   /* "7183.org", true */ '7', '1', '8', '3', '.', 'o', 'r', 'g', '\0',
   /* "777coin.com", true */ '7', '7', '7', 'c', 'o', 'i', 'n', '.', 'c', 'o', 'm', '\0',
   /* "7sons.de", true */ '7', 's', 'o', 'n', 's', '.', 'd', 'e', '\0',
   /* "7thcircledesigns.com", true */ '7', 't', 'h', 'c', 'i', 'r', 'c', 'l', 'e', 'd', 'e', 's', 'i', 'g', 'n', 's', '.', 'c', 'o', 'm', '\0',
   /* "7thheavenrestaurant.com", true */ '7', 't', 'h', 'h', 'e', 'a', 'v', 'e', 'n', 'r', 'e', 's', 't', 'a', 'u', 'r', 'a', 'n', 't', '.', 'c', 'o', 'm', '\0',
   /* "7x24servis.com", true */ '7', 'x', '2', '4', 's', 'e', 'r', 'v', 'i', 's', '.', 'c', 'o', 'm', '\0',
   /* "86metro.ru", true */ '8', '6', 'm', 'e', 't', 'r', 'o', '.', 'r', 'u', '\0',
+  /* "88.to", true */ '8', '8', '.', 't', 'o', '\0',
   /* "888azino.com", true */ '8', '8', '8', 'a', 'z', 'i', 'n', 'o', '.', 'c', 'o', 'm', '\0',
   /* "888sport.dk", true */ '8', '8', '8', 's', 'p', 'o', 'r', 't', '.', 'd', 'k', '\0',
   /* "888sport.it", true */ '8', '8', '8', 's', 'p', 'o', 'r', 't', '.', 'i', 't', '\0',
   /* "8mpay.com", true */ '8', 'm', 'p', 'a', 'y', '.', 'c', 'o', 'm', '\0',
   /* "8pecxstudios.com", true */ '8', 'p', 'e', 'c', 'x', 's', 't', 'u', 'd', 'i', 'o', 's', '.', 'c', 'o', 'm', '\0',
   /* "8t8.eu", true */ '8', 't', '8', '.', 'e', 'u', '\0',
   /* "8t88.biz", true */ '8', 't', '8', '8', '.', 'b', 'i', 'z', '\0',
   /* "8thportsmouth.org.uk", true */ '8', 't', 'h', 'p', 'o', 'r', 't', 's', 'm', 'o', 'u', 't', 'h', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0',
@@ -387,26 +389,26 @@ static const char kSTSHostTable[] = {
   /* "aerelon.de", true */ 'a', 'e', 'r', 'e', 'l', 'o', 'n', '.', 'd', 'e', '\0',
   /* "aerolog.co", true */ 'a', 'e', 'r', 'o', 'l', 'o', 'g', '.', 'c', 'o', '\0',
   /* "aeyoun.com", true */ 'a', 'e', 'y', 'o', 'u', 'n', '.', 'c', 'o', 'm', '\0',
   /* "afb24.de", true */ 'a', 'f', 'b', '2', '4', '.', 'd', 'e', '\0',
   /* "affiliateroyale.com", true */ 'a', 'f', 'f', 'i', 'l', 'i', 'a', 't', 'e', 'r', 'o', 'y', 'a', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* "affilie.de", true */ 'a', 'f', 'f', 'i', 'l', 'i', 'e', '.', 'd', 'e', '\0',
   /* "affordableazdivorce.com", true */ 'a', 'f', 'f', 'o', 'r', 'd', 'a', 'b', 'l', 'e', 'a', 'z', 'd', 'i', 'v', 'o', 'r', 'c', 'e', '.', 'c', 'o', 'm', '\0',
   /* "afghan.dating", true */ 'a', 'f', 'g', 'h', 'a', 'n', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0',
-  /* "aficotroceni.ro", true */ 'a', 'f', 'i', 'c', 'o', 't', 'r', 'o', 'c', 'e', 'n', 'i', '.', 'r', 'o', '\0',
   /* "aflattr.com", true */ 'a', 'f', 'l', 'a', 't', 't', 'r', '.', 'c', 'o', 'm', '\0',
   /* "afmchandler.com", true */ 'a', 'f', 'm', 'c', 'h', 'a', 'n', 'd', 'l', 'e', 'r', '.', 'c', 'o', 'm', '\0',
   /* "afp548.com", true */ 'a', 'f', 'p', '5', '4', '8', '.', 'c', 'o', 'm', '\0',
   /* "africa.dating", true */ 'a', 'f', 'r', 'i', 'c', 'a', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0',
   /* "africatravel.de", true */ 'a', 'f', 'r', 'i', 'c', 'a', 't', 'r', 'a', 'v', 'e', 'l', '.', 'd', 'e', '\0',
   /* "afuh.de", true */ 'a', 'f', 'u', 'h', '.', 'd', 'e', '\0',
   /* "afvallendoeje.nu", true */ 'a', 'f', 'v', 'a', 'l', 'l', 'e', 'n', 'd', 'o', 'e', 'j', 'e', '.', 'n', 'u', '\0',
   /* "afyou.co.kr", true */ 'a', 'f', 'y', 'o', 'u', '.', 'c', 'o', '.', 'k', 'r', '\0',
   /* "agdalieso.com.ba", true */ 'a', 'g', 'd', 'a', 'l', 'i', 'e', 's', 'o', '.', 'c', 'o', 'm', '.', 'b', 'a', '\0',
+  /* "ageg.ca", true */ 'a', 'g', 'e', 'g', '.', 'c', 'a', '\0',
   /* "agenda-loto.net", false */ 'a', 'g', 'e', 'n', 'd', 'a', '-', 'l', 'o', 't', 'o', '.', 'n', 'e', 't', '\0',
   /* "aggr.pw", true */ 'a', 'g', 'g', 'r', '.', 'p', 'w', '\0',
   /* "agilebits.com", true */ 'a', 'g', 'i', 'l', 'e', 'b', 'i', 't', 's', '.', 'c', 'o', 'm', '\0',
   /* "agileui.com", true */ 'a', 'g', 'i', 'l', 'e', 'u', 'i', '.', 'c', 'o', 'm', '\0',
   /* "agonswim.com", false */ 'a', 'g', 'o', 'n', 's', 'w', 'i', 'm', '.', 'c', 'o', 'm', '\0',
   /* "agotnes.com", true */ 'a', 'g', 'o', 't', 'n', 'e', 's', '.', 'c', 'o', 'm', '\0',
   /* "agowa338.de", true */ 'a', 'g', 'o', 'w', 'a', '3', '3', '8', '.', 'd', 'e', '\0',
   /* "agrias.com.br", true */ 'a', 'g', 'r', 'i', 'a', 's', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0',
@@ -487,17 +489,16 @@ static const char kSTSHostTable[] = {
   /* "aleax.me", true */ 'a', 'l', 'e', 'a', 'x', '.', 'm', 'e', '\0',
   /* "alecpap.com", true */ 'a', 'l', 'e', 'c', 'p', 'a', 'p', '.', 'c', 'o', 'm', '\0',
   /* "alecpapierniak.com", true */ 'a', 'l', 'e', 'c', 'p', 'a', 'p', 'i', 'e', 'r', 'n', 'i', 'a', 'k', '.', 'c', 'o', 'm', '\0',
   /* "alecrust.com", true */ 'a', 'l', 'e', 'c', 'r', 'u', 's', 't', '.', 'c', 'o', 'm', '\0',
   /* "aleksib.fi", true */ 'a', 'l', 'e', 'k', 's', 'i', 'b', '.', 'f', 'i', '\0',
   /* "alela.fr", true */ 'a', 'l', 'e', 'l', 'a', '.', 'f', 'r', '\0',
   /* "alertboxx.com", true */ 'a', 'l', 'e', 'r', 't', 'b', 'o', 'x', 'x', '.', 'c', 'o', 'm', '\0',
   /* "alertwire.com", true */ 'a', 'l', 'e', 'r', 't', 'w', 'i', 'r', 'e', '.', 'c', 'o', 'm', '\0',
-  /* "alessandroz.pro", true */ 'a', 'l', 'e', 's', 's', 'a', 'n', 'd', 'r', 'o', 'z', '.', 'p', 'r', 'o', '\0',
   /* "alex-ross.co.uk", true */ 'a', 'l', 'e', 'x', '-', 'r', 'o', 's', 's', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "alexanderschimpf.de", true */ 'a', 'l', 'e', 'x', 'a', 'n', 'd', 'e', 'r', 's', 'c', 'h', 'i', 'm', 'p', 'f', '.', 'd', 'e', '\0',
   /* "alexandra-schulze.de", true */ 'a', 'l', 'e', 'x', 'a', 'n', 'd', 'r', 'a', '-', 's', 'c', 'h', 'u', 'l', 'z', 'e', '.', 'd', 'e', '\0',
   /* "alexbaker.org", true */ 'a', 'l', 'e', 'x', 'b', 'a', 'k', 'e', 'r', '.', 'o', 'r', 'g', '\0',
   /* "alexberts.ch", true */ 'a', 'l', 'e', 'x', 'b', 'e', 'r', 't', 's', '.', 'c', 'h', '\0',
   /* "alexei.su", true */ 'a', 'l', 'e', 'x', 'e', 'i', '.', 's', 'u', '\0',
   /* "alexgaynor.net", true */ 'a', 'l', 'e', 'x', 'g', 'a', 'y', 'n', 'o', 'r', '.', 'n', 'e', 't', '\0',
   /* "alexhd.de", true */ 'a', 'l', 'e', 'x', 'h', 'd', '.', 'd', 'e', '\0',
@@ -675,17 +676,16 @@ static const char kSTSHostTable[] = {
   /* "angristan.fr", true */ 'a', 'n', 'g', 'r', 'i', 's', 't', 'a', 'n', '.', 'f', 'r', '\0',
   /* "angularjs.org", true */ 'a', 'n', 'g', 'u', 'l', 'a', 'r', 'j', 's', '.', 'o', 'r', 'g', '\0',
   /* "animalnet.de", false */ 'a', 'n', 'i', 'm', 'a', 'l', 'n', 'e', 't', '.', 'd', 'e', '\0',
   /* "anime.my", false */ 'a', 'n', 'i', 'm', 'e', '.', 'm', 'y', '\0',
   /* "anitaalbersen.nl", true */ 'a', 'n', 'i', 't', 'a', 'a', 'l', 'b', 'e', 'r', 's', 'e', 'n', '.', 'n', 'l', '\0',
   /* "anitube-nocookie.ch", true */ 'a', 'n', 'i', 't', 'u', 'b', 'e', '-', 'n', 'o', 'c', 'o', 'o', 'k', 'i', 'e', '.', 'c', 'h', '\0',
   /* "anitube.ch", true */ 'a', 'n', 'i', 't', 'u', 'b', 'e', '.', 'c', 'h', '\0',
   /* "ankarakart.com.tr", true */ 'a', 'n', 'k', 'a', 'r', 'a', 'k', 'a', 'r', 't', '.', 'c', 'o', 'm', '.', 't', 'r', '\0',
-  /* "ankaraprofesyonelnakliyat.com.tr", false */ 'a', 'n', 'k', 'a', 'r', 'a', 'p', 'r', 'o', 'f', 'e', 's', 'y', 'o', 'n', 'e', 'l', 'n', 'a', 'k', 'l', 'i', 'y', 'a', 't', '.', 'c', 'o', 'm', '.', 't', 'r', '\0',
   /* "ankaraprofesyonelwebtasarim.com", true */ 'a', 'n', 'k', 'a', 'r', 'a', 'p', 'r', 'o', 'f', 'e', 's', 'y', 'o', 'n', 'e', 'l', 'w', 'e', 'b', 't', 'a', 's', 'a', 'r', 'i', 'm', '.', 'c', 'o', 'm', '\0',
   /* "ankarauzmanlarnakliyat.com", true */ 'a', 'n', 'k', 'a', 'r', 'a', 'u', 'z', 'm', 'a', 'n', 'l', 'a', 'r', 'n', 'a', 'k', 'l', 'i', 'y', 'a', 't', '.', 'c', 'o', 'm', '\0',
   /* "anna.info", true */ 'a', 'n', 'n', 'a', '.', 'i', 'n', 'f', 'o', '\0',
   /* "annahmeschluss.de", true */ 'a', 'n', 'n', 'a', 'h', 'm', 'e', 's', 'c', 'h', 'l', 'u', 's', 's', '.', 'd', 'e', '\0',
   /* "annarokina.com", true */ 'a', 'n', 'n', 'a', 'r', 'o', 'k', 'i', 'n', 'a', '.', 'c', 'o', 'm', '\0',
   /* "annejan.com", true */ 'a', 'n', 'n', 'e', 'j', 'a', 'n', '.', 'c', 'o', 'm', '\0',
   /* "annetta.com", true */ 'a', 'n', 'n', 'e', 't', 't', 'a', '.', 'c', 'o', 'm', '\0',
   /* "annevankesteren.com", true */ 'a', 'n', 'n', 'e', 'v', 'a', 'n', 'k', 'e', 's', 't', 'e', 'r', 'e', 'n', '.', 'c', 'o', 'm', '\0',
@@ -776,17 +776,16 @@ static const char kSTSHostTable[] = {
   /* "appmobile.io", true */ 'a', 'p', 'p', 'm', 'o', 'b', 'i', 'l', 'e', '.', 'i', 'o', '\0',
   /* "appointed.at", true */ 'a', 'p', 'p', 'o', 'i', 'n', 't', 'e', 'd', '.', 'a', 't', '\0',
   /* "approbo.com", true */ 'a', 'p', 'p', 'r', 'o', 'b', 'o', '.', 'c', 'o', 'm', '\0',
   /* "apps.facebook.com", false */ 'a', 'p', 'p', 's', '.', 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k', '.', 'c', 'o', 'm', '\0',
   /* "apps.fedoraproject.org", true */ 'a', 'p', 'p', 's', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
   /* "apps.stg.fedoraproject.org", true */ 'a', 'p', 'p', 's', '.', 's', 't', 'g', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
   /* "appsbystudio.co.uk", true */ 'a', 'p', 'p', 's', 'b', 'y', 's', 't', 'u', 'd', 'i', 'o', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "appsdash.io", true */ 'a', 'p', 'p', 's', 'd', 'a', 's', 'h', '.', 'i', 'o', '\0',
-  /* "appson.co.uk", true */ 'a', 'p', 'p', 's', 'o', 'n', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "appui-de-fenetre.fr", true */ 'a', 'p', 'p', 'u', 'i', '-', 'd', 'e', '-', 'f', 'e', 'n', 'e', 't', 'r', 'e', '.', 'f', 'r', '\0',
   /* "appuro.com", true */ 'a', 'p', 'p', 'u', 'r', 'o', '.', 'c', 'o', 'm', '\0',
   /* "aprovpn.com", true */ 'a', 'p', 'r', 'o', 'v', 'p', 'n', '.', 'c', 'o', 'm', '\0',
   /* "aprsdroid.org", true */ 'a', 'p', 'r', 's', 'd', 'r', 'o', 'i', 'd', '.', 'o', 'r', 'g', '\0',
   /* "aprz.de", true */ 'a', 'p', 'r', 'z', '.', 'd', 'e', '\0',
   /* "apstudynotes.org", true */ 'a', 'p', 's', 't', 'u', 'd', 'y', 'n', 'o', 't', 'e', 's', '.', 'o', 'r', 'g', '\0',
   /* "aptive.co.uk", true */ 'a', 'p', 't', 'i', 'v', 'e', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "aqqrate.com", true */ 'a', 'q', 'q', 'r', 'a', 't', 'e', '.', 'c', 'o', 'm', '\0',
@@ -882,29 +881,25 @@ static const char kSTSHostTable[] = {
   /* "asahikoji.net", true */ 'a', 's', 'a', 'h', 'i', 'k', 'o', 'j', 'i', '.', 'n', 'e', 't', '\0',
   /* "asandu.eu", true */ 'a', 's', 'a', 'n', 'd', 'u', '.', 'e', 'u', '\0',
   /* "asato-jewelry.com", true */ 'a', 's', 'a', 't', 'o', '-', 'j', 'e', 'w', 'e', 'l', 'r', 'y', '.', 'c', 'o', 'm', '\0',
   /* "asbito.de", true */ 'a', 's', 'b', 'i', 't', 'o', '.', 'd', 'e', '\0',
   /* "ascamso.com", true */ 'a', 's', 'c', 'a', 'm', 's', 'o', '.', 'c', 'o', 'm', '\0',
   /* "ascension.run", true */ 'a', 's', 'c', 'e', 'n', 's', 'i', 'o', 'n', '.', 'r', 'u', 'n', '\0',
   /* "ascii.moe", true */ 'a', 's', 'c', 'i', 'i', '.', 'm', 'o', 'e', '\0',
   /* "asciitable.tips", true */ 'a', 's', 'c', 'i', 'i', 't', 'a', 'b', 'l', 'e', '.', 't', 'i', 'p', 's', '\0',
-  /* "ashleymedway.com", true */ 'a', 's', 'h', 'l', 'e', 'y', 'm', 'e', 'd', 'w', 'a', 'y', '.', 'c', 'o', 'm', '\0',
   /* "ashutoshmishra.org", true */ 'a', 's', 'h', 'u', 't', 'o', 's', 'h', 'm', 'i', 's', 'h', 'r', 'a', '.', 'o', 'r', 'g', '\0',
-  /* "asianodor.com", true */ 'a', 's', 'i', 'a', 'n', 'o', 'd', 'o', 'r', '.', 'c', 'o', 'm', '\0',
   /* "ask.fedoraproject.org", true */ 'a', 's', 'k', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
   /* "ask.stg.fedoraproject.org", true */ 'a', 's', 'k', '.', 's', 't', 'g', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
-  /* "askfit.cz", true */ 'a', 's', 'k', 'f', 'i', 't', '.', 'c', 'z', '\0',
   /* "askizzy.org.au", true */ 'a', 's', 'k', 'i', 'z', 'z', 'y', '.', 'o', 'r', 'g', '.', 'a', 'u', '\0',
   /* "askmagicconch.com", true */ 'a', 's', 'k', 'm', 'a', 'g', 'i', 'c', 'c', 'o', 'n', 'c', 'h', '.', 'c', 'o', 'm', '\0',
   /* "askme24.de", true */ 'a', 's', 'k', 'm', 'e', '2', '4', '.', 'd', 'e', '\0',
   /* "askwhy.cz", true */ 'a', 's', 'k', 'w', 'h', 'y', '.', 'c', 'z', '\0',
   /* "askwhy.eu", true */ 'a', 's', 'k', 'w', 'h', 'y', '.', 'e', 'u', '\0',
   /* "asm-x.com", true */ 'a', 's', 'm', '-', 'x', '.', 'c', 'o', 'm', '\0',
-  /* "asmui.ml", true */ 'a', 's', 'm', 'u', 'i', '.', 'm', 'l', '\0',
   /* "aspargesgaarden.no", true */ 'a', 's', 'p', 'a', 'r', 'g', 'e', 's', 'g', 'a', 'a', 'r', 'd', 'e', 'n', '.', 'n', 'o', '\0',
   /* "asphaltfruehling.de", true */ 'a', 's', 'p', 'h', 'a', 'l', 't', 'f', 'r', 'u', 'e', 'h', 'l', 'i', 'n', 'g', '.', 'd', 'e', '\0',
   /* "asphyxia.su", true */ 'a', 's', 'p', 'h', 'y', 'x', 'i', 'a', '.', 's', 'u', '\0',
   /* "aspires.co.jp", true */ 'a', 's', 'p', 'i', 'r', 'e', 's', '.', 'c', 'o', '.', 'j', 'p', '\0',
   /* "asr.li", true */ 'a', 's', 'r', '.', 'l', 'i', '\0',
   /* "asr.rocks", true */ 'a', 's', 'r', '.', 'r', 'o', 'c', 'k', 's', '\0',
   /* "assekuranzjobs.de", true */ 'a', 's', 's', 'e', 'k', 'u', 'r', 'a', 'n', 'z', 'j', 'o', 'b', 's', '.', 'd', 'e', '\0',
   /* "assemble-together.org", true */ 'a', 's', 's', 'e', 'm', 'b', 'l', 'e', '-', 't', 'o', 'g', 'e', 't', 'h', 'e', 'r', '.', 'o', 'r', 'g', '\0',
@@ -933,26 +928,28 @@ static const char kSTSHostTable[] = {
   /* "atishchenko.com", true */ 'a', 't', 'i', 's', 'h', 'c', 'h', 'e', 'n', 'k', 'o', '.', 'c', 'o', 'm', '\0',
   /* "atisoft.biz", true */ 'a', 't', 'i', 's', 'o', 'f', 't', '.', 'b', 'i', 'z', '\0',
   /* "atisoft.com.tr", true */ 'a', 't', 'i', 's', 'o', 'f', 't', '.', 'c', 'o', 'm', '.', 't', 'r', '\0',
   /* "atisoft.net", true */ 'a', 't', 'i', 's', 'o', 'f', 't', '.', 'n', 'e', 't', '\0',
   /* "atisoft.net.tr", true */ 'a', 't', 'i', 's', 'o', 'f', 't', '.', 'n', 'e', 't', '.', 't', 'r', '\0',
   /* "atisoft.web.tr", true */ 'a', 't', 'i', 's', 'o', 'f', 't', '.', 'w', 'e', 'b', '.', 't', 'r', '\0',
   /* "atitude.com", true */ 'a', 't', 'i', 't', 'u', 'd', 'e', '.', 'c', 'o', 'm', '\0',
   /* "atlantichomes.com.au", true */ 'a', 't', 'l', 'a', 'n', 't', 'i', 'c', 'h', 'o', 'm', 'e', 's', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0',
+  /* "atlantischild.hu", true */ 'a', 't', 'l', 'a', 'n', 't', 'i', 's', 'c', 'h', 'i', 'l', 'd', '.', 'h', 'u', '\0',
   /* "atlassian.net", true */ 'a', 't', 'l', 'a', 's', 's', 'i', 'a', 'n', '.', 'n', 'e', 't', '\0',
   /* "atletika.hu", true */ 'a', 't', 'l', 'e', 't', 'i', 'k', 'a', '.', 'h', 'u', '\0',
   /* "atnis.com", true */ 'a', 't', 'n', 'i', 's', '.', 'c', 'o', 'm', '\0',
   /* "atolm.net", true */ 'a', 't', 'o', 'l', 'm', '.', 'n', 'e', 't', '\0',
   /* "atom-china.org", true */ 'a', 't', 'o', 'm', '-', 'c', 'h', 'i', 'n', 'a', '.', 'o', 'r', 'g', '\0',
   /* "atom.solutions", true */ 'a', 't', 'o', 'm', '.', 's', 'o', 'l', 'u', 't', 'i', 'o', 'n', 's', '\0',
   /* "atombase.org", true */ 'a', 't', 'o', 'm', 'b', 'a', 's', 'e', '.', 'o', 'r', 'g', '\0',
   /* "atrinik.org", true */ 'a', 't', 'r', 'i', 'n', 'i', 'k', '.', 'o', 'r', 'g', '\0',
   /* "atte.fi", true */ 'a', 't', 't', 'e', '.', 'f', 'i', '\0',
   /* "attic118.com", true */ 'a', 't', 't', 'i', 'c', '1', '1', '8', '.', 'c', 'o', 'm', '\0',
+  /* "attilagyorffy.com", true */ 'a', 't', 't', 'i', 'l', 'a', 'g', 'y', 'o', 'r', 'f', 'f', 'y', '.', 'c', 'o', 'm', '\0',
   /* "attogproductions.com", true */ 'a', 't', 't', 'o', 'g', 'p', 'r', 'o', 'd', 'u', 'c', 't', 'i', 'o', 'n', 's', '.', 'c', 'o', 'm', '\0',
   /* "attogtech.com", true */ 'a', 't', 't', 'o', 'g', 't', 'e', 'c', 'h', '.', 'c', 'o', 'm', '\0',
   /* "attorney.org.il", true */ 'a', 't', 't', 'o', 'r', 'n', 'e', 'y', '.', 'o', 'r', 'g', '.', 'i', 'l', '\0',
   /* "au2pb.net", true */ 'a', 'u', '2', 'p', 'b', '.', 'n', 'e', 't', '\0',
   /* "aucubin.moe", true */ 'a', 'u', 'c', 'u', 'b', 'i', 'n', '.', 'm', 'o', 'e', '\0',
   /* "audiense.com", true */ 'a', 'u', 'd', 'i', 'e', 'n', 's', 'e', '.', 'c', 'o', 'm', '\0',
   /* "audio-detector.com", true */ 'a', 'u', 'd', 'i', 'o', '-', 'd', 'e', 't', 'e', 'c', 't', 'o', 'r', '.', 'c', 'o', 'm', '\0',
   /* "audiovisualdevices.com.au", true */ 'a', 'u', 'd', 'i', 'o', 'v', 'i', 's', 'u', 'a', 'l', 'd', 'e', 'v', 'i', 'c', 'e', 's', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0',
@@ -978,16 +975,17 @@ static const char kSTSHostTable[] = {
   /* "ausschreibungen-suedtirol.it", true */ 'a', 'u', 's', 's', 'c', 'h', 'r', 'e', 'i', 'b', 'u', 'n', 'g', 'e', 'n', '-', 's', 'u', 'e', 'd', 't', 'i', 'r', 'o', 'l', '.', 'i', 't', '\0',
   /* "aussiecable.org", true */ 'a', 'u', 's', 's', 'i', 'e', 'c', 'a', 'b', 'l', 'e', '.', 'o', 'r', 'g', '\0',
   /* "aussiehq.com.au", true */ 'a', 'u', 's', 's', 'i', 'e', 'h', 'q', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0',
   /* "australiancattle.dog", true */ 'a', 'u', 's', 't', 'r', 'a', 'l', 'i', 'a', 'n', 'c', 'a', 't', 't', 'l', 'e', '.', 'd', 'o', 'g', '\0',
   /* "auth.adult", true */ 'a', 'u', 't', 'h', '.', 'a', 'd', 'u', 'l', 't', '\0',
   /* "authint.com", true */ 'a', 'u', 't', 'h', 'i', 'n', 't', '.', 'c', 'o', 'm', '\0',
   /* "author24.ru", true */ 'a', 'u', 't', 'h', 'o', 'r', '2', '4', '.', 'r', 'u', '\0',
   /* "authoritynutrition.com", true */ 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', 'n', 'u', 't', 'r', 'i', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0',
+  /* "autimatisering.nl", true */ 'a', 'u', 't', 'i', 'm', 'a', 't', 'i', 's', 'e', 'r', 'i', 'n', 'g', '.', 'n', 'l', '\0',
   /* "auto-anleitung.de", true */ 'a', 'u', 't', 'o', '-', 'a', 'n', 'l', 'e', 'i', 't', 'u', 'n', 'g', '.', 'd', 'e', '\0',
   /* "autoauctionsohio.com", true */ 'a', 'u', 't', 'o', 'a', 'u', 'c', 't', 'i', 'o', 'n', 's', 'o', 'h', 'i', 'o', '.', 'c', 'o', 'm', '\0',
   /* "autoauctionsvirginia.com", true */ 'a', 'u', 't', 'o', 'a', 'u', 'c', 't', 'i', 'o', 'n', 's', 'v', 'i', 'r', 'g', 'i', 'n', 'i', 'a', '.', 'c', 'o', 'm', '\0',
   /* "autodeploy.it", true */ 'a', 'u', 't', 'o', 'd', 'e', 'p', 'l', 'o', 'y', '.', 'i', 't', '\0',
   /* "autoledky.sk", true */ 'a', 'u', 't', 'o', 'l', 'e', 'd', 'k', 'y', '.', 's', 'k', '\0',
   /* "automacity.com", true */ 'a', 'u', 't', 'o', 'm', 'a', 'c', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0',
   /* "autoskola.hr", true */ 'a', 'u', 't', 'o', 's', 'k', 'o', 'l', 'a', '.', 'h', 'r', '\0',
   /* "autoskole.hr", true */ 'a', 'u', 't', 'o', 's', 'k', 'o', 'l', 'e', '.', 'h', 'r', '\0',
@@ -1057,17 +1055,16 @@ static const char kSTSHostTable[] = {
   /* "babyfotograf-schweiz.ch", true */ 'b', 'a', 'b', 'y', 'f', 'o', 't', 'o', 'g', 'r', 'a', 'f', '-', 's', 'c', 'h', 'w', 'e', 'i', 'z', '.', 'c', 'h', '\0',
   /* "babypibu.com", true */ 'b', 'a', 'b', 'y', 'p', 'i', 'b', 'u', '.', 'c', 'o', 'm', '\0',
   /* "babystep.tv", true */ 'b', 'a', 'b', 'y', 's', 't', 'e', 'p', '.', 't', 'v', '\0',
   /* "bacchanallia.com", true */ 'b', 'a', 'c', 'c', 'h', 'a', 'n', 'a', 'l', 'l', 'i', 'a', '.', 'c', 'o', 'm', '\0',
   /* "backeby.eu", true */ 'b', 'a', 'c', 'k', 'e', 'b', 'y', '.', 'e', 'u', '\0',
   /* "backmountaingas.com", true */ 'b', 'a', 'c', 'k', 'm', 'o', 'u', 'n', 't', 'a', 'i', 'n', 'g', 'a', 's', '.', 'c', 'o', 'm', '\0',
   /* "backpacker.dating", true */ 'b', 'a', 'c', 'k', 'p', 'a', 'c', 'k', 'e', 'r', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0',
   /* "backscattering.de", true */ 'b', 'a', 'c', 'k', 's', 'c', 'a', 't', 't', 'e', 'r', 'i', 'n', 'g', '.', 'd', 'e', '\0',
-  /* "backschues.net", true */ 'b', 'a', 'c', 'k', 's', 'c', 'h', 'u', 'e', 's', '.', 'n', 'e', 't', '\0',
   /* "bacon-monitoring.org", true */ 'b', 'a', 'c', 'o', 'n', '-', 'm', 'o', 'n', 'i', 't', 'o', 'r', 'i', 'n', 'g', '.', 'o', 'r', 'g', '\0',
   /* "bacontreeconsulting.com", true */ 'b', 'a', 'c', 'o', 'n', 't', 'r', 'e', 'e', 'c', 'o', 'n', 's', 'u', 'l', 't', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
   /* "bacula.jp", true */ 'b', 'a', 'c', 'u', 'l', 'a', '.', 'j', 'p', '\0',
   /* "bad.horse", true */ 'b', 'a', 'd', '.', 'h', 'o', 'r', 's', 'e', '\0',
   /* "badbee.cc", true */ 'b', 'a', 'd', 'b', 'e', 'e', '.', 'c', 'c', '\0',
   /* "badf00d.de", true */ 'b', 'a', 'd', 'f', '0', '0', 'd', '.', 'd', 'e', '\0',
   /* "badges.fedoraproject.org", true */ 'b', 'a', 'd', 'g', 'e', 's', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
   /* "badges.stg.fedoraproject.org", true */ 'b', 'a', 'd', 'g', 'e', 's', '.', 's', 't', 'g', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0',
@@ -1083,17 +1080,16 @@ static const char kSTSHostTable[] = {
   /* "bagheera.me.uk", true */ 'b', 'a', 'g', 'h', 'e', 'e', 'r', 'a', '.', 'm', 'e', '.', 'u', 'k', '\0',
   /* "bah.im", true */ 'b', 'a', 'h', '.', 'i', 'm', '\0',
   /* "baifubao.com", true */ 'b', 'a', 'i', 'f', 'u', 'b', 'a', 'o', '.', 'c', 'o', 'm', '\0',
   /* "baiker.info", true */ 'b', 'a', 'i', 'k', 'e', 'r', '.', 'i', 'n', 'f', 'o', '\0',
   /* "bair.io", true */ 'b', 'a', 'i', 'r', '.', 'i', 'o', '\0',
   /* "baiyangliu.com", true */ 'b', 'a', 'i', 'y', 'a', 'n', 'g', 'l', 'i', 'u', '.', 'c', 'o', 'm', '\0',
   /* "bajic.ch", true */ 'b', 'a', 'j', 'i', 'c', '.', 'c', 'h', '\0',
   /* "bakabt.info", true */ 'b', 'a', 'k', 'a', 'b', 't', '.', 'i', 'n', 'f', 'o', '\0',
-  /* "bakaweb.fr", true */ 'b', 'a', 'k', 'a', 'w', 'e', 'b', '.', 'f', 'r', '\0',
   /* "bakingstone.com", true */ 'b', 'a', 'k', 'i', 'n', 'g', 's', 't', 'o', 'n', 'e', '.', 'c', 'o', 'm', '\0',
   /* "balboa.io", true */ 'b', 'a', 'l', 'b', 'o', 'a', '.', 'i', 'o', '\0',
   /* "baleares.party", true */ 'b', 'a', 'l', 'e', 'a', 'r', 'e', 's', '.', 'p', 'a', 'r', 't', 'y', '\0',
   /* "balicekzdravi.cz", true */ 'b', 'a', 'l', 'i', 'c', 'e', 'k', 'z', 'd', 'r', 'a', 'v', 'i', '.', 'c', 'z', '\0',
   /* "balikonos.cz", true */ 'b', 'a', 'l', 'i', 'k', 'o', 'n', 'o', 's', '.', 'c', 'z', '\0',
   /* "balist.es", true */ 'b', 'a', 'l', 'i', 's', 't', '.', 'e', 's', '\0',
   /* "baliyano.com", true */ 'b', 'a', 'l', 'i', 'y', 'a', 'n', 'o', '.', 'c', 'o', 'm', '\0',
   /* "balkonien.org", true */ 'b', 'a', 'l', 'k', 'o', 'n', 'i', 'e', 'n', '.', 'o', 'r', 'g', '\0',
@@ -1145,17 +1141,16 @@ static const char kSTSHostTable[] = {
   /* "barslecht.nl", true */ 'b', 'a', 'r', 's', 'l', 'e', 'c', 'h', 't', '.', 'n', 'l', '\0',
   /* "bartel.ws", true */ 'b', 'a', 'r', 't', 'e', 'l', '.', 'w', 's', '\0',
   /* "bartelt.name", true */ 'b', 'a', 'r', 't', 'e', 'l', 't', '.', 'n', 'a', 'm', 'e', '\0',
   /* "bartlamboo.nl", true */ 'b', 'a', 'r', 't', 'l', 'a', 'm', 'b', 'o', 'o', '.', 'n', 'l', '\0',
   /* "bartula.de", true */ 'b', 'a', 'r', 't', 'u', 'l', 'a', '.', 'd', 'e', '\0',
   /* "baruch.me", true */ 'b', 'a', 'r', 'u', 'c', 'h', '.', 'm', 'e', '\0',
   /* "barunisystems.com", true */ 'b', 'a', 'r', 'u', 'n', 'i', 's', 'y', 's', 't', 'e', 'm', 's', '.', 'c', 'o', 'm', '\0',
   /* "bashc.at", true */ 'b', 'a', 's', 'h', 'c', '.', 'a', 't', '\0',
-  /* "basilisk.io", true */ 'b', 'a', 's', 'i', 'l', 'i', 's', 'k', '.', 'i', 'o', '\0',
   /* "baskettemple.com", true */ 'b', 'a', 's', 'k', 'e', 't', 't', 'e', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* &quo