Backed out 6 changesets (bug 1428745) for wpt failures on script-type-and-language-with-params.html. r=backout on a CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Wed, 10 Jan 2018 00:37:59 +0200
changeset 452778 38614ffd21d195add38b50056b89d5f99b53baee
parent 452777 8ae89b17787b7a67e3a7ce621e63fdf2d3c7bb26
child 452779 6be5a45a855e2af656477c53ee1d6f9a9f518212
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1428745
milestone59.0a1
backs out9e84285278feb4ef9b1cfce0bdc658739006f964
e199f1ccf64c5c2aee9373733bf0899fd3f9c839
dfb9af93ac532643b7f472c3d557ed3c9419665d
1d975770bd9a19208fb84e306729e5ce1ee396fc
1d5dc7dfd429af246a1d1aa1854485be1ad4b6ab
4e53f251c5b83bbb595e6d91ce14243f9381f9ee
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1428745) for wpt failures on script-type-and-language-with-params.html. r=backout on a CLOSED TREE Backed out changeset 9e84285278fe (bug 1428745) Backed out changeset e199f1ccf64c (bug 1428745) Backed out changeset dfb9af93ac53 (bug 1428745) Backed out changeset 1d975770bd9a (bug 1428745) Backed out changeset 1d5dc7dfd429 (bug 1428745) Backed out changeset 4e53f251c5b8 (bug 1428745)
browser/base/content/test/general/file_trackingUI_6.html
devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
devtools/client/storage/test/storage-cookies-samesite.html
dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html
dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html
dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html
dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html
dom/html/HTMLScriptElement.cpp
dom/html/test/test_checked.html
dom/script/ModuleLoadRequest.cpp
dom/script/ModuleLoadRequest.h
dom/script/ScriptLoadRequest.cpp
dom/script/ScriptLoadRequest.h
dom/script/ScriptLoader.cpp
dom/script/ScriptLoader.h
dom/tests/mochitest/bugs/test_bug1171215.html
dom/tests/mochitest/bugs/test_no_find_showDialog.html
dom/tests/mochitest/script/mochitest.ini
dom/tests/mochitest/script/test_bug1053321.html
dom/tests/mochitest/script/test_whitespace.html
dom/xbl/test/test_bug389322.xhtml
layout/style/test/bug453896_iframe.html
layout/style/test/chrome/test_moz_document_rules.html
layout/style/test/test_addSheet.html
layout/style/test/test_additional_sheets.html
layout/style/test/test_computed_style_prefs.html
layout/style/test/test_media_queries_dynamic.html
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html.ini
toolkit/components/extensions/test/mochitest/mochitest-common.ini
toolkit/components/extensions/test/mochitest/test_ext_jsversion.html
toolkit/components/telemetry/Histograms.json
uriloader/exthandler/tests/mochitest/download_page.html
--- a/browser/base/content/test/general/file_trackingUI_6.html
+++ b/browser/base/content/test/general/file_trackingUI_6.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <html>
 <head>
   <meta charset="UTF-8">
   <title>Testing the shield from fetch and XHR</title>
 </head>
 <body>
   <p>Hello there!</p>
-  <script type="application/javascript">
+  <script type="application/javascript; version=1.8">
     function test_fetch() {
       let url = "http://trackertest.org/browser/browser/base/content/test/general/file_trackingUI_6.js";
       return fetch(url);
     }
   </script>
 </body>
 </html>
--- a/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
+++ b/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
@@ -5,17 +5,17 @@
 <html>
 <!--
 Basic tests for the HSplitBox component.
 -->
 <head>
   <meta charset="utf-8">
   <title>Tree component test</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript "src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
   <link rel="stylesheet" href="resource://devtools/client/themes/splitters.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/components-h-split-box.css" type="text/css"/>
   <style>
     html {
       --theme-splitter-color: black;
     }
   </style>
--- a/devtools/client/storage/test/storage-cookies-samesite.html
+++ b/devtools/client/storage/test/storage-cookies-samesite.html
@@ -1,16 +1,16 @@
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset="utf-8">
     <title>Storage inspector cookie samesite test</title>
   </head>
   <body>
-    <script type="application/javascript">
+    <script type="application/javascript;version=1.7">
     "use strict";
     let expiresIn24Hours = new Date(Date.now() + 60 * 60 * 24 * 1000).toUTCString();
 
     document.cookie = "test1=value1;expires=" + expiresIn24Hours + ";";
     document.cookie = "test2=value2;expires=" + expiresIn24Hours + ";SameSite=lax";
     document.cookie = "test3=value3;expires=" + expiresIn24Hours + ";SameSite=strict";
     </script>
   </body>
--- a/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 795317</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a>
 
-<script type="application/javascript" src="browserElement_ExposableURI.js"></script>
+<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script>
 
 </body>
 </html>
 
--- a/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html
@@ -7,12 +7,12 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 710231</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a>
 
-<script type="application/javascript" src="browserElement_LoadEvents.js"></script>
+<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script>
 
 </body>
 </html>
--- a/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html
+++ b/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 795317</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a>
 
-<script type="application/javascript" src="browserElement_ExposableURI.js"></script>
+<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script>
 
 </body>
 </html>
 
--- a/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html
+++ b/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 710231</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a>
 
-<script type="application/javascript" src="browserElement_LoadEvents.js"></script>
+<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script>
 
 </body>
 </html>
 
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -166,30 +166,19 @@ HTMLScriptElement::SetText(const nsAStri
 {
   aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
 }
 
 // variation of this code in nsSVGScriptElement - check if changes
 // need to be transfered when modifying
 
 bool
-HTMLScriptElement::GetScriptType(nsAString& aType)
+HTMLScriptElement::GetScriptType(nsAString& type)
 {
-  nsAutoString type;
-  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
-    return false;
-  }
-
-  // ASCII whitespace https://infra.spec.whatwg.org/#ascii-whitespace:
-  // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
-  static const char kASCIIWhitespace[] = "\t\n\f\r ";
-  type.Trim(kASCIIWhitespace);
-
-  aType.Assign(type);
-  return true;
+  return GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
 }
 
 void
 HTMLScriptElement::GetScriptText(nsAString& text)
 {
   IgnoredErrorResult rv;
   GetText(text, rv);
 }
--- a/dom/html/test/test_checked.html
+++ b/dom/html/test/test_checked.html
@@ -21,17 +21,17 @@ and
   <form id="f2">
   </form>
   <menu id="m1">
   </menu>
   <menu id="m2">
   </menu>
 </div>
 <pre id="test">
-<script class="testbody" type="text/javascript">
+<script class="testbody" type="text/javascript; version=1.7">
 
 /** Test for Bug 418756 and 617528 **/
 var group1;
 var group2;
 var group3;
 
 var tags = ["input", "menuitem"];
 for (let tag of tags) {
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -24,40 +24,43 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(Modul
                                    mModuleScript,
                                    mImports)
 
 NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 
 ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
                                      nsIScriptElement* aElement,
+                                     ValidJSVersion aValidJSVersion,
                                      CORSMode aCORSMode,
                                      const SRIMetadata& aIntegrity,
                                      nsIURI* aReferrer,
                                      mozilla::net::ReferrerPolicy aReferrerPolicy,
                                      ScriptLoader* aLoader)
   : ScriptLoadRequest(ScriptKind::eModule,
                       aURI,
                       aElement,
+                      aValidJSVersion,
                       aCORSMode,
                       aIntegrity,
                       aReferrer,
                       aReferrerPolicy),
     mIsTopLevel(true),
     mLoader(aLoader),
     mVisitedSet(new VisitedURLSet())
 {
   mVisitedSet->PutEntry(aURI);
 }
 
 ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
                                      ModuleLoadRequest* aParent)
   : ScriptLoadRequest(ScriptKind::eModule,
                       aURI,
                       aParent->mElement,
+                      aParent->mValidJSVersion,
                       aParent->mCORSMode,
                       SRIMetadata(),
                       aParent->mURI,
                       aParent->mReferrerPolicy),
     mIsTopLevel(false),
     mLoader(aParent->mLoader),
     mVisitedSet(aParent->mVisitedSet)
 {
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -40,16 +40,17 @@ class ModuleLoadRequest final : public S
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 
   // Create a top-level module load request.
   ModuleLoadRequest(nsIURI* aURI,
                     nsIScriptElement* aElement,
+                    ValidJSVersion aValidJSVersion,
                     CORSMode aCORSMode,
                     const SRIMetadata& aIntegrity,
                     nsIURI* aReferrer,
                     mozilla::net::ReferrerPolicy,
                     ScriptLoader* aLoader);
 
   // Create a module load request for an imported module.
   ModuleLoadRequest(nsIURI* aURI,
--- a/dom/script/ScriptLoadRequest.cpp
+++ b/dom/script/ScriptLoadRequest.cpp
@@ -36,16 +36,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
                                      nsIURI* aURI,
                                      nsIScriptElement* aElement,
+                                     ValidJSVersion aValidJSVersion,
                                      mozilla::CORSMode aCORSMode,
                                      const SRIMetadata& aIntegrity,
                                      nsIURI* aReferrer,
                                      mozilla::net::ReferrerPolicy aReferrerPolicy)
   : mKind(aKind)
   , mElement(aElement)
   , mScriptFromHead(false)
   , mProgress(Progress::eLoading)
@@ -59,16 +60,17 @@ ScriptLoadRequest::ScriptLoadRequest(Scr
   , mIsXSLT(false)
   , mIsCanceled(false)
   , mWasCompiledOMT(false)
   , mIsTracking(false)
   , mOffThreadToken(nullptr)
   , mScriptText()
   , mScriptBytecode()
   , mBytecodeOffset(0)
+  , mValidJSVersion(aValidJSVersion)
   , mURI(aURI)
   , mLineNo(1)
   , mCORSMode(aCORSMode)
   , mIntegrity(aIntegrity)
   , mReferrer(aReferrer)
   , mReferrerPolicy(aReferrerPolicy)
 {
 }
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -24,16 +24,21 @@ namespace dom {
 class ModuleLoadRequest;
 class ScriptLoadRequestList;
 
 enum class ScriptKind {
   eClassic,
   eModule
 };
 
+enum class ValidJSVersion : bool {
+  eInvalid,
+  eValid
+};
+
 /*
  * A class that handles loading and evaluation of <script> elements.
  */
 
 class ScriptLoadRequest : public nsISupports,
                           private mozilla::LinkedListElement<ScriptLoadRequest>
 {
   typedef LinkedListElement<ScriptLoadRequest> super;
@@ -44,16 +49,17 @@ class ScriptLoadRequest : public nsISupp
 
 protected:
   virtual ~ScriptLoadRequest();
 
 public:
   ScriptLoadRequest(ScriptKind aKind,
                     nsIURI* aURI,
                     nsIScriptElement* aElement,
+                    ValidJSVersion aValidJSVersion,
                     mozilla::CORSMode aCORSMode,
                     const SRIMetadata &aIntegrity,
                     nsIURI* aReferrer,
                     mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest)
 
@@ -206,16 +212,17 @@ public:
   // ownership to jsapi.
   mozilla::Vector<char16_t> mScriptText;
 
   // Holds the SRI serialized hash and the script bytecode for non-inline
   // scripts.
   mozilla::Vector<uint8_t> mScriptBytecode;
   uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
 
+  ValidJSVersion mValidJSVersion;
   const nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   nsAutoCString mURL;     // Keep the URI's filename alive during off thread parsing.
   int32_t mLineNo;
   const mozilla::CORSMode mCORSMode;
   const SRIMetadata mIntegrity;
   const nsCOMPtr<nsIURI> mReferrer;
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -1054,21 +1054,22 @@ ScriptLoader::StartLoad(ScriptLoadReques
       contentPolicyType,
       loadGroup,
       prompter,
       nsIRequest::LOAD_NORMAL |
       nsIChannel::LOAD_CLASSIFY_URI);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // To avoid decoding issues, the build-id is part of the JSBytecodeMimeType
-  // constant.
+  // To avoid decoding issues, the JSVersion is explicitly guarded here, and the
+  // build-id is part of the JSBytecodeMimeType constant.
   aRequest->mCacheInfo = nullptr;
   nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(channel));
-  if (cic && nsContentUtils::IsBytecodeCacheEnabled()) {
+  if (cic && nsContentUtils::IsBytecodeCacheEnabled() &&
+      aRequest->mValidJSVersion == ValidJSVersion::eValid) {
     if (!aRequest->IsLoadingSource()) {
       // Inform the HTTP cache that we prefer to have information coming from the
       // bytecode cache instead of the sources, if such entry is already registered.
       LOG(("ScriptLoadRequest (%p): Maybe request bytecode", aRequest));
       cic->PreferAlternativeDataType(nsContentUtils::JSBytecodeMimeType());
     } else {
       // If we are explicitly loading from the sources, such as after a
       // restarted request, we might still want to save the bytecode after.
@@ -1168,16 +1169,73 @@ bool
 ScriptLoader::PreloadURIComparator::Equals(const PreloadInfo& aPi,
                                            nsIURI* const& aURI) const
 {
   bool same;
   return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
          same;
 }
 
+/**
+ * Returns ValidJSVersion::eValid if aVersionStr is a string of the form '1.n',
+ * n = 0, ..., 8, and ValidJSVersion::eInvalid for other strings.
+ */
+static ValidJSVersion
+ParseJavascriptVersion(const nsAString& aVersionStr)
+{
+  if (aVersionStr.Length() != 3 || aVersionStr[0] != '1' ||
+      aVersionStr[1] != '.') {
+    return ValidJSVersion::eInvalid;
+  }
+  if ('0' <= aVersionStr[2] && aVersionStr[2] <= '8') {
+    return ValidJSVersion::eValid;
+  }
+  return ValidJSVersion::eInvalid;
+}
+
+static inline bool
+ParseTypeAttribute(const nsAString& aType, ValidJSVersion* aVersion)
+{
+  MOZ_ASSERT(!aType.IsEmpty());
+  MOZ_ASSERT(aVersion);
+  MOZ_ASSERT(*aVersion == ValidJSVersion::eValid);
+
+  nsContentTypeParser parser(aType);
+
+  nsAutoString mimeType;
+  nsresult rv = parser.GetType(mimeType);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  if (!nsContentUtils::IsJavascriptMIMEType(mimeType)) {
+    return false;
+  }
+
+  // Get the version string, and ensure the language supports it.
+  nsAutoString versionName;
+  rv = parser.GetParameter("version", versionName);
+
+  if (rv == NS_ERROR_INVALID_ARG) {
+    Telemetry::Accumulate(Telemetry::SCRIPT_LOADED_WITH_VERSION, false);
+    // Argument not set.
+    return true;
+  }
+
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  *aVersion = ParseJavascriptVersion(versionName);
+  if (*aVersion == ValidJSVersion::eValid) {
+    Telemetry::Accumulate(Telemetry::SCRIPT_LOADED_WITH_VERSION, true);
+    return true;
+  }
+
+  return true;
+}
+
 static bool
 CSPAllowsInlineScript(nsIScriptElement* aElement, nsIDocument* aDocument)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   // Note: For imports NodePrincipal and the principal of the master are
   // the same.
   nsresult rv = aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, false);
@@ -1200,34 +1258,35 @@ CSPAllowsInlineScript(nsIScriptElement* 
                             &allowInlineScript);
   return allowInlineScript;
 }
 
 ScriptLoadRequest*
 ScriptLoader::CreateLoadRequest(ScriptKind aKind,
                                 nsIURI* aURI,
                                 nsIScriptElement* aElement,
+                                ValidJSVersion aValidJSVersion,
                                 CORSMode aCORSMode,
                                 const SRIMetadata& aIntegrity,
                                 mozilla::net::ReferrerPolicy aReferrerPolicy)
 {
   nsIURI* referrer = mDocument->GetDocumentURI();
 
   if (aKind == ScriptKind::eClassic) {
     ScriptLoadRequest* slr = new ScriptLoadRequest(aKind, aURI, aElement,
-                                                   aCORSMode, aIntegrity,
+                                                   aValidJSVersion, aCORSMode, aIntegrity,
                                                    referrer, aReferrerPolicy);
 
     LOG(("ScriptLoader %p creates ScriptLoadRequest %p", this, slr));
     return slr;
   }
 
   MOZ_ASSERT(aKind == ScriptKind::eModule);
-  return new ModuleLoadRequest(aURI, aElement, aCORSMode, aIntegrity, referrer,
-                               aReferrerPolicy, this);
+  return new ModuleLoadRequest(aURI, aElement, aValidJSVersion, aCORSMode,
+                               aIntegrity, referrer, aReferrerPolicy, this);
 }
 
 bool
 ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement)
 {
   // We need a document to evaluate scripts.
   NS_ENSURE_TRUE(mDocument, false);
 
@@ -1246,21 +1305,23 @@ ScriptLoader::ProcessScriptElement(nsISc
   ScriptKind scriptKind =
     aElement->GetScriptIsModule() ? ScriptKind::eModule : ScriptKind::eClassic;
 
   // Step 13. Check that the script is not an eventhandler
   if (IsScriptEventHandler(scriptKind, scriptContent)) {
     return false;
   }
 
+  ValidJSVersion validJSVersion = ValidJSVersion::eValid;
+
   // For classic scripts, check the type attribute to determine language and
   // version. If type exists, it trumps the deprecated 'language='
   if (scriptKind == ScriptKind::eClassic) {
     if (!type.IsEmpty()) {
-      NS_ENSURE_TRUE(nsContentUtils::IsJavascriptMIMEType(type), false);
+      NS_ENSURE_TRUE(ParseTypeAttribute(type, &validJSVersion), false);
     } else if (!hasType) {
       // no 'type=' element
       // "language" is a deprecated attribute of HTML, so we check it only for
       // HTML script elements.
       if (scriptContent->IsHTMLElement()) {
         nsAutoString language;
         scriptContent->AsElement()->GetAttr(kNameSpaceID_None,
                                             nsGkAtoms::language,
@@ -1363,18 +1424,19 @@ ScriptLoader::ProcessScriptElement(nsISc
         }
       }
 
       nsCOMPtr<nsIPrincipal> principal = aElement->GetScriptURITriggeringPrincipal();
       if (!principal) {
         principal = scriptContent->NodePrincipal();
       }
 
-      request = CreateLoadRequest(scriptKind, scriptURI, aElement, ourCORSMode,
-                                  sriMetadata, ourRefPolicy);
+      request = CreateLoadRequest(scriptKind, scriptURI, aElement,
+                                  validJSVersion, ourCORSMode, sriMetadata,
+                                  ourRefPolicy);
       request->mTriggeringPrincipal = Move(principal);
       request->mIsInline = false;
       request->SetScriptMode(aElement->GetScriptDeferred(),
                              aElement->GetScriptAsync());
       // keep request->mScriptFromHead to false so we don't treat non preloaded
       // scripts as blockers for full page load. See bug 792438.
 
       rv = StartLoad(request);
@@ -1389,16 +1451,18 @@ ScriptLoader::ProcessScriptElement(nsISc
         return false;
       }
     }
 
     // Should still be in loading stage of script.
     NS_ASSERTION(!request->InCompilingStage(),
                  "Request should not yet be in compiling stage.");
 
+    request->mValidJSVersion = validJSVersion;
+
     if (request->IsAsyncScript()) {
       AddAsyncRequest(request);
       if (request->IsReadyToRun()) {
         // The script is available already. Run it ASAP when the event
         // loop gets a chance to spin.
 
         // KVKV TODO: Instead of processing immediately, try off-thread-parsing
         // it and only schedule a pending ProcessRequest if that fails.
@@ -1491,19 +1555,20 @@ ScriptLoader::ProcessScriptElement(nsISc
 
   // Inline classic scripts ignore their CORS mode and are always CORS_NONE.
   CORSMode corsMode = CORS_NONE;
   if (scriptKind == ScriptKind::eModule) {
     corsMode = aElement->GetCORSMode();
   }
 
   request = CreateLoadRequest(scriptKind, mDocument->GetDocumentURI(), aElement,
-                              corsMode,
+                              validJSVersion, corsMode,
                               SRIMetadata(), // SRI doesn't apply
                               ourRefPolicy);
+  request->mValidJSVersion = validJSVersion;
   request->mIsInline = true;
   request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mLineNo = aElement->GetScriptLineNumber();
   request->mProgress = ScriptLoadRequest::Progress::eLoading_Source;
   request->mDataType = ScriptLoadRequest::DataType::eSource;
   TRACE_FOR_TEST_BOOL(request->mElement, "scriptloader_load_source");
   CollectScriptTelemetry(nullptr, request);
 
@@ -2122,16 +2187,20 @@ ScriptLoader::EvaluateScript(ScriptLoadR
   // Make sure context is a strong reference since we access it after
   // we've executed a script, which may cause all other references to
   // the context to go away.
   nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext();
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
+  if (aRequest->mValidJSVersion == ValidJSVersion::eInvalid) {
+    return NS_OK;
+  }
+
   // New script entry point required, due to the "Create a script" sub-step of
   // http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
   nsAutoMicroTask mt;
   AutoEntryScript aes(globalObject, "<script> element", true);
   JSContext* cx = aes.cx();
   JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
 
   bool oldProcessingScriptTag = context->GetProcessingScriptTag();
@@ -3136,17 +3205,17 @@ ScriptLoader::PreloadURI(nsIURI* aURI, c
     nsAutoCString sourceUri;
     if (mDocument->GetDocumentURI()) {
       mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
     }
     SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
   }
 
   RefPtr<ScriptLoadRequest> request =
-    CreateLoadRequest(ScriptKind::eClassic, aURI, nullptr,
+    CreateLoadRequest(ScriptKind::eClassic, aURI, nullptr, ValidJSVersion::eValid,
                       Element::StringToCORSMode(aCrossOrigin), sriMetadata,
                       aReferrerPolicy);
   request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mIsInline = false;
   request->mScriptFromHead = aScriptFromHead;
   request->SetScriptMode(aDefer, aAsync);
 
   nsresult rv = StartLoad(request);
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -337,16 +337,17 @@ public:
   }
 
 private:
   virtual ~ScriptLoader();
 
   ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
                                        nsIURI* aURI,
                                        nsIScriptElement* aElement,
+                                       ValidJSVersion aValidJSVersion,
                                        mozilla::CORSMode aCORSMode,
                                        const SRIMetadata& aIntegrity,
                                        mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   /**
    * Unblocks the creator parser of the parser-blocking scripts.
    */
   void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
--- a/dom/tests/mochitest/bugs/test_bug1171215.html
+++ b/dom/tests/mochitest/bugs/test_bug1171215.html
@@ -5,17 +5,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1022869</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <iframe src="about:blank"></iframe>
-  <script type="text/javascript">
+  <script type="text/javascript; version=1.8">
 
   var f = document.getElementsByTagName("iframe")[0];
 
   SimpleTest.waitForExplicitFinish();
 
   /** Test for Bug 1022869 **/
   function startTest() {
     // Initialize our cookie.
--- a/dom/tests/mochitest/bugs/test_no_find_showDialog.html
+++ b/dom/tests/mochitest/bugs/test_no_find_showDialog.html
@@ -2,17 +2,17 @@
 <html>
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1348409</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <iframe src="about:blank"></iframe>
-  <script type="text/javascript">
+  <script type="text/javascript; version=1.8">
 
   function checkForFindDialog() {
     let chromeScript = SpecialPowers.loadChromeScript(_ => {
       addMessageListener("test:check", () => {
         const { utils: Cu } = Components;
 
         Cu.import("resource://gre/modules/Services.jsm");
 
@@ -84,9 +84,9 @@
 </p>
 
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 </pre>
 </body>
-</html>
+</html>
\ No newline at end of file
--- a/dom/tests/mochitest/script/mochitest.ini
+++ b/dom/tests/mochitest/script/mochitest.ini
@@ -1,7 +1,6 @@
 [DEFAULT]
 support-files =
   file_blocked_script.sjs
 
 [test_bug1053321.html]
 skip-if = os == 'android' # bug 1386644
-[test_whitespace.html]
--- a/dom/tests/mochitest/script/test_bug1053321.html
+++ b/dom/tests/mochitest/script/test_bug1053321.html
@@ -18,24 +18,23 @@ are unexpectedly blocked.
   <!-- this script is not loaded until file_blocked_script.sjs?unblock&async request is made,
        when this script is executed, it sets window.script_executed_async to true
    -->
   <script async src="file_blocked_script.sjs?blocked&async"></script>
 </head>
 
 <body>
   <script>
-    SimpleTest.waitForExplicitFinish();
-
+    // No need for an async test, we make it all before window.onload.
+    //
     // We can't test whether the two scripts have not been executed here, since
     // preloads of the two images below (that unblock the two tested <head>
     // scripts) may happen sooner than this script executes.
     document.addEventListener("DOMContentLoaded", function() {
       ok(window.script_executed_defer, "Deferred script executed before DOMContentLoaded");
     });
     window.addEventListener("load", function() {
       ok(window.script_executed_async, "Async script executed before onload");
-      SimpleTest.finish();
     }, true);
   </script>
   <img src="file_blocked_script.sjs?unblock&defer"/>
   <img src="file_blocked_script.sjs?unblock&async"/>
 </body>
deleted file mode 100644
--- a/dom/tests/mochitest/script/test_whitespace.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for ScriptLoader and type with whitespaces</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<script type="application/javascript">
-let passed = false;
-
-let tests = [
-  [ " application/javascript", true ],
-  [ "\tapplication/javascript\n\r \t", true ],
-];
-
-for (let i = 0; i < tests.length; ++i) {
-  passed = false;
-
-  let script = document.createElement('script');
-  script.setAttribute('type', tests[i][0]);
-  script.innerText = "passed = true;";
-  document.body.appendChild(script);
-
-  ok (passed, tests[i][1], "Test " + tests[i][0] + " passed");
-}
-</script>
-
-</body>
-</html>
--- a/dom/xbl/test/test_bug389322.xhtml
+++ b/dom/xbl/test/test_bug389322.xhtml
@@ -100,19 +100,27 @@ addLoadEvent(function() {
 });
 addLoadEvent(SimpleTest.finish);
 
 function report(testName, success) {
   is(success, true, "JS 1.7 should work in " + testName);
 }
 ]]>
 </script>
+<script type="text/javascript; version=1.7"><![CDATA[
+  try {
+    eval("let x = 1;");
+    var success = true;
+  }
+  catch (e) { success = false; }
+  report("HTML script tags with explicit version", success)
+]]></script>
 <script type="text/javascript"><![CDATA[
   try {
     eval("let x = 1;");
     var success = true;
   }
   catch (e) { success = false; }
-  is(success, true, "let should work in HTML script tags");
+  is(success, true, "let should work in versionless HTML script tags");
 ]]></script>
 </pre>
 </body>
 </html>
--- a/layout/style/test/bug453896_iframe.html
+++ b/layout/style/test/bug453896_iframe.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
 <html lang="en-US">
 <head>
   <title>Bug 453896 Test middle frame</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta http-equiv="Content-Style-Type" content="text/css">
-  <script type="application/javascript">
+  <script type="application/javascript; version=1.7">
 
 function run(test_window)
 {
   var subdoc = document.getElementById("subdoc").contentDocument;
   var subwin = document.getElementById("subdoc").contentWindow;
   var style = subdoc.getElementById("style");
   var iframe_style = document.getElementById("subdoc").style;
   var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body);
--- a/layout/style/test/chrome/test_moz_document_rules.html
+++ b/layout/style/test/chrome/test_moz_document_rules.html
@@ -5,17 +5,17 @@
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=398962">Mozilla Bug 398962</a>
 <iframe id="iframe" src="http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.html"></iframe>
 <pre id="test">
-<script type="application/javascript">
+<script type="application/javascript; version=1.8">
 
 var [gStyleSheetService, gIOService] = (function() {
     return [
             Components.classes["@mozilla.org/content/style-sheet-service;1"]
                 .getService(Components.interfaces.nsIStyleSheetService),
             Components.classes["@mozilla.org/network/io-service;1"]
                 .getService(Components.interfaces.nsIIOService)
            ];
--- a/layout/style/test/test_addSheet.html
+++ b/layout/style/test/test_addSheet.html
@@ -7,17 +7,17 @@
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024707">Mozilla Bug 1024707</a>
 
 <iframe id="iframe1" src="additional_sheets_helper.html"></iframe>
 <iframe id="iframe2" src="additional_sheets_helper.html"></iframe>
 
 <pre id="test">
-<script type="application/javascript">
+<script type="application/javascript; version=1.8">
 
 let gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
   .getService(SpecialPowers.Ci.nsIIOService);
 
 let gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
   .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function test(win, sheet) {
--- a/layout/style/test/test_additional_sheets.html
+++ b/layout/style/test/test_additional_sheets.html
@@ -4,17 +4,17 @@
   <title>Test for additional sheets</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737003">Mozilla Bug 737003</a>
 <iframe id="iframe" src="additional_sheets_helper.html"></iframe>
 <pre id="test">
-<script type="application/javascript">
+<script type="application/javascript; version=1.8">
 
 var gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
   .getService(SpecialPowers.Ci.nsIIOService)
 
 var gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
   .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function getUri(style)
--- a/layout/style/test/test_computed_style_prefs.html
+++ b/layout/style/test/test_computed_style_prefs.html
@@ -7,17 +7,17 @@
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=919594">Mozilla Bug 919594</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
-<script type="application/javascript">
+<script type="application/javascript; version=1.7">
 
 /** Test that preffed off properties do not appear in computed style **/
 
 function testWithAllPrefsDisabled() {
   let exposedProperties = Object.keys(gCS).map(i => gCS[i]);
 
   // Store the number of properties for later tests to use.
   gLengthWithAllPrefsDisabled = gCS.length;
--- a/layout/style/test/test_media_queries_dynamic.html
+++ b/layout/style/test/test_media_queries_dynamic.html
@@ -10,17 +10,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=473400">Mozilla Bug 473400</a>
 <iframe id="subdoc" src="about:blank"></iframe>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
-<script class="testbody" type="application/javascript">
+<script class="testbody" type="application/javascript; version=1.7">
 
 /** Test for Bug 473400 **/
 
 SimpleTest.waitForExplicitFinish();
 
 function run() {
   var subdoc = document.getElementById("subdoc").contentDocument;
   var subwin = document.getElementById("subdoc").contentWindow;
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html.ini
+++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html.ini
@@ -1,10 +1,199 @@
 [script-type-and-language-js.html]
-  [Script shouldn't run with type=" "]
+  [Script should run with type="application/ecmascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="application/javascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="application/x-ecmascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="application/x-javascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="\\fapplication/ecmascript"]
+    expected: FAIL
+
+  [Script should run with type="\\fapplication/javascript"]
+    expected: FAIL
+
+  [Script should run with type="\\fapplication/x-ecmascript"]
+    expected: FAIL
+
+  [Script should run with type="\\fapplication/x-javascript"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/ecmascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/javascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/x-ecmascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/x-javascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/ecmascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/javascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/x-ecmascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="application/x-javascript\\0foo"]
+    expected: FAIL
+
+  [Script should run with type="text/ecmascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.0\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.1\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.2\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.3\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.4\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/javascript1.5\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/jscript\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/livescript\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/x-ecmascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="text/x-javascript\\f"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/ecmascript"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.0"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.1"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.2"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.3"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.4"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/javascript1.5"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/jscript"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/livescript"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/x-ecmascript"]
+    expected: FAIL
+
+  [Script should run with type="\\ftext/x-javascript"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/ecmascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.0\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.1\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.2\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.3\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.4\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.5\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/jscript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/livescript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/x-ecmascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/x-javascript\\0"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/ecmascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.0\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.1\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.2\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.3\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.4\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/javascript1.5\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/jscript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/livescript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/x-ecmascript\\0foo"]
+    expected: FAIL
+
+  [Script shouldn't run with type="text/x-javascript\\0foo"]
     expected: FAIL
 
   [Script should run with language="ecmascript"]
     expected: FAIL
 
   [Script should run with language="jscript"]
     expected: FAIL
 
@@ -20,8 +209,9 @@
   [Script should run with language="JSCRIPT"]
     expected: FAIL
 
   [Script should run with language="X-ECMASCRIPT"]
     expected: FAIL
 
   [Script should run with language="X-JAVASCRIPT"]
     expected: FAIL
+
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -104,16 +104,17 @@ skip-if = os == 'android' # Android does
 [test_ext_geolocation.html]
 skip-if = os == 'android' # Android support Bug 1336194
 [test_ext_geturl.html]
 [test_ext_identity.html]
 skip-if = os == 'android' # unsupported.
 [test_ext_idle.html]
 [test_ext_inIncognitoContext_window.html]
 skip-if = os == 'android' # Android does not support multiple windows.
+[test_ext_jsversion.html]
 [test_ext_listener_proxies.html]
 [test_ext_new_tab_processType.html]
 [test_ext_notifications.html]
 skip-if = os == "win" # Bug 1398518
 [test_ext_permission_xhr.html]
 [test_ext_protocolHandlers.html]
 skip-if = (toolkit == 'android') # bug 1342577
 [test_ext_redirect_jar.html]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_jsversion.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for simple WebExtension</title>
+  <meta charset="utf-8">
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+  <script type="text/javascript" src="head.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+add_task(async function test_versioned_js() {
+  // We need to deal with escaping the close script tags.
+  // May as well consolidate it into one place.
+  let script = attrs => `<script ${attrs}><\/script>`;
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "background": {"page": "background.html"},
+    },
+
+    files: {
+      "background.html": `
+        <meta charset="utf-8">
+        ${script('src="background.js" type="application/javascript"')}
+        ${script('src="background-1.js" type="application/javascript;version=1.8"')}
+        ${script('src="background-2.js" type="application/javascript;version=latest"')}
+        ${script('src="background-3.js" type="application/javascript"')}
+      `,
+
+      "background.js": function() {
+        window.reportResult = msg => {
+          browser.test.assertEq(
+            msg, "background-script-3",
+            "Expected a message only from the unversioned background script.");
+
+          browser.test.sendMessage("finished");
+        };
+      },
+
+      "background-1.js": function() {
+        window.reportResult("background-script-1");
+      },
+      "background-2.js": function() {
+        window.reportResult("background-script-2");
+      },
+      "background-3.js": function() {
+        window.reportResult("background-script-3");
+      },
+    },
+  });
+
+  consoleMonitor.start([{message: /Versioned JavaScript.*not supported in WebExtension.*developer\.mozilla\.org/},
+                        {message: /Versioned JavaScript.*not supported in WebExtension.*developer\.mozilla\.org/}]);
+
+  await Promise.all([extension.startup(),
+                     extension.awaitMessage("finished")]);
+
+  await consoleMonitor.finished();
+  await extension.unload();
+});
+
+</script>
+
+</body>
+</html>
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -13857,16 +13857,24 @@
     "alert_emails": ["gfx-telemetry-alerts@mozilla.com","danderson@mozilla.com"],
     "expires_in_version": "61",
     "kind": "exponential",
     "high": 200,
     "n_buckets": 50,
     "description": "Amount of time in milliseconds the main thread spends waiting for the paint thread to complete, if the time was greater than 200us.",
     "bug_numbers": [1386968]
   },
+  "SCRIPT_LOADED_WITH_VERSION": {
+    "record_in_processes": ["main", "content"],
+    "alert_emails": ["amarchesini@mozilla.com"],
+    "bug_numbers": [1418860],
+    "expires_in_version": "60",
+    "kind": "boolean",
+    "description": "Tracking how often scripts are loaded with a 'valid' version parameter. This telemetry ID helps us to decide if and when remove the support of script versioning."
+  },
   "STYLO_PARALLEL_RESTYLE_FRACTION": {
     "record_in_processes": ["content"],
     "alert_emails": ["manish@mozilla.com"],
     "expires_in_version": "60",
     "kind": "linear",
     "high": 100,
     "n_buckets": 50,
     "description": "Percentage of restyles on a single page that were parallel",
--- a/uriloader/exthandler/tests/mochitest/download_page.html
+++ b/uriloader/exthandler/tests/mochitest/download_page.html
@@ -1,16 +1,16 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE html>
 <html>
 <head>
   <meta charset=UTF-8>
   <title>Test page for link clicking</title>
-  <script type="text/javascript">
+  <script type="text/javascript; version=1.8">
     function launch_download() {
       window.open("download.bin", "_blank", "height=100,width=100");
     }
   </script>
 </head>
 <body>
   <a href="download.bin" id="regular_load">regular load</a>
   <a href="download.bin" id="target_blank" target="_blank">target blank</a>