summaryrefslogtreecommitdiff
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/abort/AbortController.cpp98
-rw-r--r--dom/abort/AbortController.h59
-rw-r--r--dom/abort/AbortSignal.cpp124
-rw-r--r--dom/abort/AbortSignal.h76
-rw-r--r--dom/abort/moz.build26
-rw-r--r--dom/abort/tests/file_abort_controller.html113
-rw-r--r--dom/abort/tests/mochitest.ini6
-rw-r--r--dom/abort/tests/moz.build8
-rw-r--r--dom/abort/tests/test_abort_controller.html40
-rw-r--r--dom/abort/tests/worker_abort_controller.js27
-rw-r--r--dom/base/CustomElementRegistry.cpp3
-rw-r--r--dom/base/ImportManager.cpp8
-rw-r--r--dom/base/ImportManager.h8
-rw-r--r--dom/base/Location.cpp2
-rwxr-xr-xdom/base/moz.build7
-rw-r--r--dom/base/nsContentPermissionHelper.cpp3
-rw-r--r--dom/base/nsContentSink.cpp2
-rw-r--r--dom/base/nsContentSink.h7
-rw-r--r--dom/base/nsDocument.cpp19
-rw-r--r--dom/base/nsDocument.h6
-rw-r--r--dom/base/nsFrameMessageManager.cpp8
-rw-r--r--dom/base/nsGkAtomList.h2
-rw-r--r--dom/base/nsGlobalWindow.cpp2
-rw-r--r--dom/base/nsIDocument.h4
-rw-r--r--dom/base/nsINode.cpp25
-rw-r--r--dom/base/nsINode.h10
-rw-r--r--dom/base/nsInProcessTabChildGlobal.cpp2
-rw-r--r--dom/base/nsJSEnvironment.cpp2
-rw-r--r--dom/base/nsJSUtils.cpp13
-rw-r--r--dom/base/nsJSUtils.h8
-rw-r--r--dom/base/nsPlainTextSerializer.h1
-rw-r--r--dom/base/test/jsmodules/test_syntaxError.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorAsync.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInline.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html15
-rwxr-xr-xdom/console/Console.cpp2
-rw-r--r--dom/events/DOMEventTargetHelper.cpp2
-rw-r--r--dom/fetch/Fetch.cpp289
-rw-r--r--dom/fetch/FetchDriver.cpp82
-rw-r--r--dom/fetch/FetchDriver.h31
-rw-r--r--dom/fetch/FetchObserver.cpp117
-rw-r--r--dom/fetch/FetchObserver.h54
-rw-r--r--dom/fetch/Request.h1
-rw-r--r--dom/fetch/moz.build2
-rw-r--r--dom/html/HTMLScriptElement.cpp2
-rw-r--r--dom/html/HTMLScriptElement.h7
-rw-r--r--dom/html/nsGenericHTMLElement.cpp2
-rw-r--r--dom/html/nsHTMLContentSink.cpp2
-rw-r--r--dom/media/MediaDecoderReader.h1
-rw-r--r--dom/media/webspeech/moz.build6
-rw-r--r--dom/messagechannel/MessagePort.cpp2
-rw-r--r--dom/moz.build2
-rw-r--r--dom/script/ModuleLoadRequest.cpp139
-rw-r--r--dom/script/ModuleLoadRequest.h87
-rw-r--r--dom/script/ModuleScript.cpp122
-rw-r--r--dom/script/ModuleScript.h53
-rw-r--r--dom/script/ScriptElement.cpp (renamed from dom/base/nsScriptElement.cpp)60
-rw-r--r--dom/script/ScriptElement.h (renamed from dom/base/nsScriptElement.h)18
-rw-r--r--dom/script/ScriptLoadHandler.cpp216
-rw-r--r--dom/script/ScriptLoadHandler.h76
-rw-r--r--dom/script/ScriptLoader.cpp (renamed from dom/base/nsScriptLoader.cpp)1121
-rw-r--r--dom/script/ScriptLoader.h (renamed from dom/base/nsScriptLoader.h)228
-rw-r--r--dom/script/ScriptSettings.cpp (renamed from dom/base/ScriptSettings.cpp)8
-rw-r--r--dom/script/ScriptSettings.h (renamed from dom/base/ScriptSettings.h)0
-rw-r--r--dom/script/moz.build36
-rw-r--r--dom/script/nsIScriptElement.h (renamed from dom/base/nsIScriptElement.h)0
-rw-r--r--dom/script/nsIScriptLoaderObserver.idl (renamed from dom/base/nsIScriptLoaderObserver.idl)0
-rw-r--r--dom/svg/SVGScriptElement.cpp4
-rw-r--r--dom/svg/SVGScriptElement.h6
-rw-r--r--dom/tests/mochitest/fetch/file_fetch_observer.html146
-rw-r--r--dom/tests/mochitest/fetch/mochitest.ini3
-rw-r--r--dom/tests/mochitest/fetch/slow.sjs11
-rw-r--r--dom/tests/mochitest/fetch/test_fetch_observer.html41
-rw-r--r--dom/tests/mochitest/webcomponents/mochitest.ini1
-rw-r--r--dom/tests/mochitest/webcomponents/test_bug1269155.html89
-rw-r--r--dom/webidl/AbortController.webidl13
-rw-r--r--dom/webidl/AbortSignal.webidl13
-rw-r--r--dom/webidl/FetchObserver.webidl27
-rw-r--r--dom/webidl/Node.webidl9
-rw-r--r--dom/webidl/Request.webidl6
-rw-r--r--dom/webidl/moz.build3
-rw-r--r--dom/workers/ScriptLoader.cpp20
-rw-r--r--dom/workers/ServiceWorkerManager.cpp2
-rw-r--r--dom/workers/ServiceWorkerScriptCache.cpp14
-rw-r--r--dom/workers/WorkerPrefs.h2
-rw-r--r--dom/worklet/Worklet.cpp8
-rw-r--r--dom/xml/nsXMLContentSink.cpp2
-rw-r--r--dom/xml/nsXMLFragmentContentSink.cpp2
-rw-r--r--dom/xslt/xslt/txMozillaXMLOutput.cpp8
-rw-r--r--dom/xul/XULDocument.cpp8
-rw-r--r--dom/xul/XULDocument.h2
-rw-r--r--dom/xul/nsXULContentSink.cpp2
92 files changed, 2869 insertions, 1120 deletions
diff --git a/dom/abort/AbortController.cpp b/dom/abort/AbortController.cpp
new file mode 100644
index 0000000000..bd8159e7b5
--- /dev/null
+++ b/dom/abort/AbortController.cpp
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AbortController.h"
+#include "AbortSignal.h"
+#include "mozilla/dom/AbortControllerBinding.h"
+#include "WorkerPrivate.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AbortController, mGlobal, mSignal)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(AbortController)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(AbortController)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortController)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+/* static */ bool
+AbortController::IsEnabled(JSContext* aCx, JSObject* aGlobal)
+{
+ if (NS_IsMainThread()) {
+ return Preferences::GetBool("dom.abortController.enabled", false);
+ }
+
+ using namespace workers;
+
+ // Otherwise, check the pref via the WorkerPrivate
+ WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+ if (!workerPrivate) {
+ return false;
+ }
+
+ return workerPrivate->AbortControllerEnabled();
+}
+
+/* static */ already_AddRefed<AbortController>
+AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
+{
+ nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+ if (!global) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ RefPtr<AbortController> abortController = new AbortController(global);
+ return abortController.forget();
+}
+
+AbortController::AbortController(nsIGlobalObject* aGlobal)
+ : mGlobal(aGlobal)
+ , mAborted(false)
+{}
+
+JSObject*
+AbortController::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return AbortControllerBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsIGlobalObject*
+AbortController::GetParentObject() const
+{
+ return mGlobal;
+}
+
+AbortSignal*
+AbortController::Signal()
+{
+ if (!mSignal) {
+ mSignal = new AbortSignal(this, mAborted);
+ }
+
+ return mSignal;
+}
+
+void
+AbortController::Abort()
+{
+ if (mAborted) {
+ return;
+ }
+
+ mAborted = true;
+
+ if (mSignal) {
+ mSignal->Abort();
+ }
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/abort/AbortController.h b/dom/abort/AbortController.h
new file mode 100644
index 0000000000..0b99dc49c2
--- /dev/null
+++ b/dom/abort/AbortController.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_AbortController_h
+#define mozilla_dom_AbortController_h
+
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/AbortSignal.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+#include "mozilla/ErrorResult.h"
+#include "nsIGlobalObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class AbortController final : public nsISupports
+ , public nsWrapperCache
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortController)
+
+ static bool
+ IsEnabled(JSContext* aCx, JSObject* aGlobal);
+
+ static already_AddRefed<AbortController>
+ Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
+
+ explicit AbortController(nsIGlobalObject* aGlobal);
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ nsIGlobalObject*
+ GetParentObject() const;
+
+ AbortSignal*
+ Signal();
+
+ void
+ Abort();
+
+private:
+ ~AbortController() = default;
+
+ nsCOMPtr<nsIGlobalObject> mGlobal;
+ RefPtr<AbortSignal> mSignal;
+
+ bool mAborted;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_AbortController_h
diff --git a/dom/abort/AbortSignal.cpp b/dom/abort/AbortSignal.cpp
new file mode 100644
index 0000000000..20f36d2abb
--- /dev/null
+++ b/dom/abort/AbortSignal.cpp
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AbortSignal.h"
+#include "AbortController.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/AbortSignalBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(AbortSignal)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AbortSignal,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AbortSignal,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mController)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AbortSignal)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(AbortSignal, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(AbortSignal, DOMEventTargetHelper)
+
+AbortSignal::AbortSignal(AbortController* aController,
+ bool aAborted)
+ : DOMEventTargetHelper(aController->GetParentObject())
+ , mController(aController)
+ , mAborted(aAborted)
+{}
+
+AbortSignal::AbortSignal(bool aAborted)
+ : mAborted(aAborted)
+{}
+
+JSObject*
+AbortSignal::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return AbortSignalBinding::Wrap(aCx, this, aGivenProto);
+}
+
+bool
+AbortSignal::Aborted() const
+{
+ return mAborted;
+}
+
+void
+AbortSignal::Abort()
+{
+ MOZ_ASSERT(!mAborted);
+ mAborted = true;
+
+ // Let's inform the followers.
+ for (uint32_t i = 0; i < mFollowers.Length(); ++i) {
+ mFollowers[i]->Aborted();
+ }
+
+ EventInit init;
+ init.mBubbles = false;
+ init.mCancelable = false;
+
+ RefPtr<Event> event =
+ Event::Constructor(this, NS_LITERAL_STRING("abort"), init);
+ event->SetTrusted(true);
+
+ bool dummy;
+ DispatchEvent(event, &dummy);
+}
+
+void
+AbortSignal::AddFollower(AbortSignal::Follower* aFollower)
+{
+ MOZ_DIAGNOSTIC_ASSERT(aFollower);
+ if (!mFollowers.Contains(aFollower)) {
+ mFollowers.AppendElement(aFollower);
+ }
+}
+
+void
+AbortSignal::RemoveFollower(AbortSignal::Follower* aFollower)
+{
+ MOZ_DIAGNOSTIC_ASSERT(aFollower);
+ mFollowers.RemoveElement(aFollower);
+}
+
+// AbortSignal::Follower
+// ----------------------------------------------------------------------------
+
+AbortSignal::Follower::~Follower()
+{
+ Unfollow();
+}
+
+void
+AbortSignal::Follower::Follow(AbortSignal* aSignal)
+{
+ MOZ_DIAGNOSTIC_ASSERT(aSignal);
+
+ Unfollow();
+
+ mFollowingSignal = aSignal;
+ aSignal->AddFollower(this);
+}
+
+void
+AbortSignal::Follower::Unfollow()
+{
+ if (mFollowingSignal) {
+ mFollowingSignal->RemoveFollower(this);
+ mFollowingSignal = nullptr;
+ }
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/abort/AbortSignal.h b/dom/abort/AbortSignal.h
new file mode 100644
index 0000000000..35e5829429
--- /dev/null
+++ b/dom/abort/AbortSignal.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_AbortSignal_h
+#define mozilla_dom_AbortSignal_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+
+namespace mozilla {
+namespace dom {
+
+class AbortController;
+class AbortSignal;
+
+class AbortSignal final : public DOMEventTargetHelper
+{
+public:
+ // This class must be implemented by objects who want to follow a AbortSignal.
+ class Follower
+ {
+ public:
+ virtual void Aborted() = 0;
+
+ protected:
+ virtual ~Follower();
+
+ void
+ Follow(AbortSignal* aSignal);
+
+ void
+ Unfollow();
+
+ RefPtr<AbortSignal> mFollowingSignal;
+ };
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AbortSignal, DOMEventTargetHelper)
+
+ AbortSignal(AbortController* aController, bool aAborted);
+ explicit AbortSignal(bool aAborted);
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ bool
+ Aborted() const;
+
+ void
+ Abort();
+
+ IMPL_EVENT_HANDLER(abort);
+
+ void
+ AddFollower(Follower* aFollower);
+
+ void
+ RemoveFollower(Follower* aFollower);
+
+private:
+ ~AbortSignal() = default;
+
+ RefPtr<AbortController> mController;
+
+ // Raw pointers. Follower unregisters itself in the DTOR.
+ nsTArray<Follower*> mFollowers;
+
+ bool mAborted;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_AbortSignal_h
diff --git a/dom/abort/moz.build b/dom/abort/moz.build
new file mode 100644
index 0000000000..cb48ee15f4
--- /dev/null
+++ b/dom/abort/moz.build
@@ -0,0 +1,26 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "DOM")
+
+TEST_DIRS += ['tests']
+
+EXPORTS.mozilla.dom += [
+ 'AbortController.h',
+ 'AbortSignal.h',
+]
+
+UNIFIED_SOURCES += [
+ 'AbortController.cpp',
+ 'AbortSignal.cpp',
+]
+
+LOCAL_INCLUDES += [
+ '../workers',
+]
+
+FINAL_LIBRARY = 'xul'
diff --git a/dom/abort/tests/file_abort_controller.html b/dom/abort/tests/file_abort_controller.html
new file mode 100644
index 0000000000..3a15fa3469
--- /dev/null
+++ b/dom/abort/tests/file_abort_controller.html
@@ -0,0 +1,113 @@
+<script>
+function ok(a, msg) {
+ parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function testWebIDL() {
+ ok("FetchController" in self, "We have a FetchController prototype");
+ ok("FetchSignal" in self, "We have a FetchSignal prototype");
+
+ var fc = new FetchController();
+ ok(!!fc, "FetchController can be created");
+ ok(fc instanceof FetchController, "FetchController is a FetchController");
+
+ ok(!!fc.signal, "FetchController has a signal");
+ ok(fc.signal instanceof FetchSignal, "fetchSignal is a FetchSignal");
+ is(fc.signal.aborted, false, "By default FetchSignal.aborted is false");
+ next();
+}
+
+function testUpdateData() {
+ var fc = new FetchController();
+
+ is(fc.signal.aborted, false, "By default FetchSignal.aborted is false");
+
+ fc.abort();
+ is(fc.signal.aborted, true, "Signal is aborted");
+
+ next();
+}
+
+function testAbortEvent() {
+ var fc = new FetchController();
+ fc.signal.onabort = function(e) {
+ is(e.type, "abort", "Abort received");
+ next();
+ }
+ fc.abort();
+}
+
+function testAbortedFetch() {
+ var fc = new FetchController();
+ fc.abort();
+
+ fetch('slow.sjs', { signal: fc.signal }).then(() => {
+ ok(false, "Fetch should not return a resolved promise");
+ }, e => {
+ is(e.name, "AbortError", "We have an abort error");
+ }).then(next);
+}
+
+function testFetchAndAbort() {
+ var fc = new FetchController();
+
+ var p = fetch('slow.sjs', { signal: fc.signal });
+ fc.abort();
+
+ p.then(() => {
+ ok(false, "Fetch should not return a resolved promise");
+ }, e => {
+ is(e.name, "AbortError", "We have an abort error");
+ }).then(next);
+}
+
+function testWorkerAbortedFetch() {
+ var w = new Worker('worker_fetch_controller.js');
+ w.onmessage = function(e) {
+ ok(e.data, "Abort + Fetch works in workers");
+ next();
+ }
+ w.postMessage('testWorkerAbortedFetch');
+}
+
+function testWorkerFetchAndAbort() {
+ var w = new Worker('worker_fetch_controller.js');
+ w.onmessage = function(e) {
+ ok(e.data, "Abort + Fetch works in workers");
+ next();
+ }
+ w.postMessage('testWorkerFetchAndAbort');
+}
+
+var steps = [
+ // Simple stuff
+ testWebIDL,
+ testUpdateData,
+
+ // Event propagation
+ testAbortEvent,
+
+ // fetch + signaling
+ testAbortedFetch,
+ testFetchAndAbort,
+ testWorkerAbortedFetch,
+ testWorkerFetchAndAbort,
+];
+
+function next() {
+ if (!steps.length) {
+ parent.postMessage({ type: "finish" }, "*");
+ return;
+ }
+
+ var step = steps.shift();
+ step();
+}
+
+next();
+
+</script>
diff --git a/dom/abort/tests/mochitest.ini b/dom/abort/tests/mochitest.ini
new file mode 100644
index 0000000000..c8cc95fdab
--- /dev/null
+++ b/dom/abort/tests/mochitest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+support-files =
+ file_abort_controller.html
+ worker_fetch_controller.js
+
+[test_abort_controller.html]
diff --git a/dom/abort/tests/moz.build b/dom/abort/tests/moz.build
new file mode 100644
index 0000000000..8e5cb5d717
--- /dev/null
+++ b/dom/abort/tests/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+MOCHITEST_MANIFESTS += ['mochitest.ini']
+
diff --git a/dom/abort/tests/test_abort_controller.html b/dom/abort/tests/test_abort_controller.html
new file mode 100644
index 0000000000..812fb91616
--- /dev/null
+++ b/dom/abort/tests/test_abort_controller.html
@@ -0,0 +1,40 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test FetchController</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SpecialPowers.pushPrefEnv({"set": [["dom.fetchController.enabled", true ]]}, () => {
+ let ifr = document.createElement('iframe');
+ ifr.src = "file_fetch_controller.html";
+ document.body.appendChild(ifr);
+
+ onmessage = function(e) {
+ if (e.data.type == "finish") {
+ SimpleTest.finish();
+ return;
+ }
+
+ if (e.data.type == "check") {
+ ok(e.data.status, e.data.message);
+ return;
+ }
+
+ ok(false, "Something when wrong.");
+ }
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</body>
+</html>
+
diff --git a/dom/abort/tests/worker_abort_controller.js b/dom/abort/tests/worker_abort_controller.js
new file mode 100644
index 0000000000..6fd1c78884
--- /dev/null
+++ b/dom/abort/tests/worker_abort_controller.js
@@ -0,0 +1,27 @@
+function testWorkerAbortedFetch() {
+ var fc = new AbortController();
+ fc.abort();
+
+ fetch('slow.sjs', { signal: fc.signal }).then(() => {
+ postMessage(false);
+ }, e => {
+ postMessage(e.name == "AbortError");
+ });
+}
+
+function testWorkerFetchAndAbort() {
+ var fc = new AbortController();
+
+ var p = fetch('slow.sjs', { signal: fc.signal });
+ fc.abort();
+
+ p.then(() => {
+ postMessage(false);
+ }, e => {
+ postMessage(e.name == "AbortError");
+ });
+}
+
+onmessage = function(e) {
+ self[e.data]();
+}
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index f582d635f9..3f83221998 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -166,8 +166,11 @@ NS_INTERFACE_MAP_END
/* static */ bool
CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
{
+ return false;
+/*
return Preferences::GetBool("dom.webcomponents.customelements.enabled") ||
Preferences::GetBool("dom.webcomponents.enabled");
+*/
}
/* static */ already_AddRefed<CustomElementRegistry>
diff --git a/dom/base/ImportManager.cpp b/dom/base/ImportManager.cpp
index d0e514b591..1f4d376b37 100644
--- a/dom/base/ImportManager.cpp
+++ b/dom/base/ImportManager.cpp
@@ -6,6 +6,7 @@
#include "ImportManager.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/EventListenerManager.h"
#include "HTMLLinkElement.h"
#include "nsContentPolicyUtils.h"
@@ -18,7 +19,6 @@
#include "nsIDOMEvent.h"
#include "nsIPrincipal.h"
#include "nsIScriptObjectPrincipal.h"
-#include "nsScriptLoader.h"
#include "nsNetUtil.h"
//-----------------------------------------------------------------------------
@@ -156,7 +156,7 @@ ImportLoader::Updater::UpdateMainReferrer(uint32_t aNewIdx)
// Our nearest predecessor has changed. So let's add the ScriptLoader to the
// new one if there is any. And remove it from the old one.
RefPtr<ImportManager> manager = mLoader->Manager();
- nsScriptLoader* loader = mLoader->mDocument->ScriptLoader();
+ ScriptLoader* loader = mLoader->mDocument->ScriptLoader();
ImportLoader*& pred = mLoader->mBlockingPredecessor;
ImportLoader* newPred = manager->GetNearestPredecessor(newMainReferrer);
if (pred) {
@@ -339,7 +339,7 @@ ImportLoader::DispatchEventIfFinished(nsINode* aNode)
}
void
-ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
+ImportLoader::AddBlockedScriptLoader(ScriptLoader* aScriptLoader)
{
if (mBlockedScriptLoaders.Contains(aScriptLoader)) {
return;
@@ -352,7 +352,7 @@ ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
}
bool
-ImportLoader::RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader)
+ImportLoader::RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader)
{
aScriptLoader->RemoveParserBlockingScriptExecutionBlocker();
return mBlockedScriptLoaders.RemoveElement(aScriptLoader);
diff --git a/dom/base/ImportManager.h b/dom/base/ImportManager.h
index 258d4691cf..ccc00125ae 100644
--- a/dom/base/ImportManager.h
+++ b/dom/base/ImportManager.h
@@ -45,8 +45,8 @@
#include "nsIStreamListener.h"
#include "nsIWeakReferenceUtils.h"
#include "nsRefPtrHashtable.h"
-#include "nsScriptLoader.h"
#include "nsURIHashKey.h"
+#include "mozilla/dom/ScriptLoader.h"
class nsIDocument;
class nsIPrincipal;
@@ -184,8 +184,8 @@ public:
// and wait for that to run its scripts. We keep track of all the
// ScriptRunners that are waiting for this import. NOTE: updating
// the main referrer might change this list.
- void AddBlockedScriptLoader(nsScriptLoader* aScriptLoader);
- bool RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader);
+ void AddBlockedScriptLoader(ScriptLoader* aScriptLoader);
+ bool RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader);
void SetBlockingPredecessor(ImportLoader* aLoader);
private:
@@ -230,7 +230,7 @@ private:
// List of pending ScriptLoaders that are waiting for this import
// to finish.
- nsTArray<RefPtr<nsScriptLoader>> mBlockedScriptLoaders;
+ nsTArray<RefPtr<ScriptLoader>> mBlockedScriptLoaders;
// There is always exactly one referrer link that is flagged as
// the main referrer the primary link. This is the one that is
diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp
index 1483c32f9d..308e9a4ff6 100644
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -32,9 +32,9 @@
#include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h"
#include "nsNullPrincipal.h"
-#include "ScriptSettings.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/LocationBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
namespace mozilla {
namespace dom {
diff --git a/dom/base/moz.build b/dom/base/moz.build
index 89f1785ca7..aadafe4127 100755
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -26,7 +26,6 @@ XPIDL_SOURCES += [
'nsIObjectLoadingContent.idl',
'nsIRemoteWindowContext.idl',
'nsIScriptChannel.idl',
- 'nsIScriptLoaderObserver.idl',
'nsISelection.idl',
'nsISelectionController.idl',
'nsISelectionDisplay.idl',
@@ -96,7 +95,6 @@ EXPORTS += [
'nsINode.h',
'nsINodeList.h',
'nsIScriptContext.h',
- 'nsIScriptElement.h',
'nsIScriptGlobalObject.h',
'nsIScriptNameSpaceManager.h',
'nsIScriptObjectPrincipal.h',
@@ -117,7 +115,6 @@ EXPORTS += [
'nsRange.h',
'nsReferencedElement.h',
'nsSandboxFlags.h',
- 'nsScriptLoader.h',
'nsStructuredCloneContainer.h',
'nsStubAnimationObserver.h',
'nsStubDocumentObserver.h',
@@ -208,7 +205,6 @@ EXPORTS.mozilla.dom += [
'ResponsiveImageSelector.h',
'SameProcessMessageQueue.h',
'ScreenOrientation.h',
- 'ScriptSettings.h',
'ShadowRoot.h',
'SimpleTreeIterator.h',
'StructuredCloneHolder.h',
@@ -328,8 +324,6 @@ SOURCES += [
'nsRange.cpp',
'nsReferencedElement.cpp',
'nsScreen.cpp',
- 'nsScriptElement.cpp',
- 'nsScriptLoader.cpp',
'nsScriptNameSpaceManager.cpp',
'nsStructuredCloneContainer.cpp',
'nsStubAnimationObserver.cpp',
@@ -356,7 +350,6 @@ SOURCES += [
'ResponsiveImageSelector.cpp',
'SameProcessMessageQueue.cpp',
'ScreenOrientation.cpp',
- 'ScriptSettings.cpp',
'ShadowRoot.cpp',
'StructuredCloneHolder.cpp',
'StyleSheetList.cpp',
diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp
index c57fc6233b..eaaec2a412 100644
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -29,9 +29,8 @@
#include "nsIDocument.h"
#include "nsIDOMEvent.h"
#include "nsWeakPtr.h"
-#include "ScriptSettings.h"
-using mozilla::Unused; // <snicker>
+using mozilla::Unused;
using namespace mozilla::dom;
using namespace mozilla;
diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp
index 490f0ec17c..1e6465a1bf 100644
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -10,7 +10,6 @@
*/
#include "nsContentSink.h"
-#include "nsScriptLoader.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "mozilla/css/Loader.h"
@@ -49,6 +48,7 @@
#include "nsHTMLDNSPrefetch.h"
#include "nsIObserverService.h"
#include "mozilla/Preferences.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "nsParserConstants.h"
#include "nsSandboxFlags.h"
diff --git a/dom/base/nsContentSink.h b/dom/base/nsContentSink.h
index b1a7588740..2d914a8d7b 100644
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -36,13 +36,16 @@ class nsIAtom;
class nsIChannel;
class nsIContent;
class nsNodeInfoManager;
-class nsScriptLoader;
class nsIApplicationCache;
namespace mozilla {
namespace css {
class Loader;
} // namespace css
+
+namespace dom {
+class ScriptLoader;
+} // namespace dom
} // namespace mozilla
#ifdef DEBUG
@@ -273,7 +276,7 @@ protected:
nsCOMPtr<nsIDocShell> mDocShell;
RefPtr<mozilla::css::Loader> mCSSLoader;
RefPtr<nsNodeInfoManager> mNodeInfoManager;
- RefPtr<nsScriptLoader> mScriptLoader;
+ RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
// back off timer notification after count
int32_t mBackoffCount;
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 3805937375..d0634b0f9d 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1880,7 +1880,7 @@ nsDocument::Init()
mScopeObject = do_GetWeakReference(global);
MOZ_ASSERT(mScopeObject);
- mScriptLoader = new nsScriptLoader(this);
+ mScriptLoader = new dom::ScriptLoader(this);
mozilla::HoldJSObjects(this);
@@ -4685,7 +4685,7 @@ nsDocument::GetWindowInternal() const
return win;
}
-nsScriptLoader*
+ScriptLoader*
nsDocument::ScriptLoader()
{
return mScriptLoader;
@@ -5709,9 +5709,9 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
JS::Rooted<JSObject*> obj(aCx, aObject);
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
- return true;
- }
+ //if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ // return true;
+ //}
// Check for the webcomponents permission. See Bug 1181555.
JSAutoCompartment ac(aCx, obj);
@@ -5725,9 +5725,9 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
bool
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
{
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
- return true;
- }
+ //if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ // return true;
+ //}
nsIDocument* doc = aNodeInfo->GetDocument();
// Use GetScopeObject() here so that data documents work the same way as the
@@ -5740,6 +5740,7 @@ nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
bool
nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
{
+/*
if (aWindow) {
nsresult rv;
nsCOMPtr<nsIPermissionManager> permMgr =
@@ -5753,7 +5754,7 @@ nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
return perm == nsIPermissionManager::ALLOW_ACTION;
}
-
+*/
return false;
}
diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h
index 8ea4993f07..a319ad13e6 100644
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -31,7 +31,6 @@
#include "nsJSThingHashtable.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIURI.h"
-#include "nsScriptLoader.h"
#include "nsIRadioGroupContainer.h"
#include "nsILayoutHistoryState.h"
#include "nsIRequest.h"
@@ -60,6 +59,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/PendingAnimationTracker.h"
#include "mozilla/dom/DOMImplementation.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/StyleSheetList.h"
#include "nsDataHashtable.h"
#include "mozilla/TimeStamp.h"
@@ -674,7 +674,7 @@ public:
/**
* Get the script loader for this document
*/
- virtual nsScriptLoader* ScriptLoader() override;
+ virtual mozilla::dom::ScriptLoader* ScriptLoader() override;
/**
* Add/Remove an element to the document's id and name hashes
@@ -1417,7 +1417,7 @@ public:
RefPtr<mozilla::EventListenerManager> mListenerManager;
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
- RefPtr<nsScriptLoader> mScriptLoader;
+ RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
nsDocHeaderData* mHeaderData;
/* mIdentifierMap works as follows for IDs:
* 1) Attribute changes affect the table immediately (removing and adding
diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
index bba4232aa8..331931f19d 100644
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -19,7 +19,6 @@
#include "nsJSUtils.h"
#include "nsJSPrincipals.h"
#include "nsNetUtil.h"
-#include "nsScriptLoader.h"
#include "nsFrameLoader.h"
#include "nsIXULRuntime.h"
#include "nsIScriptError.h"
@@ -38,6 +37,7 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/SameProcessMessageQueue.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
@@ -1786,9 +1786,9 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) {
return;
}
- nsScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
- EmptyString(), nullptr,
- dataStringBuf, dataStringLength);
+ ScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
+ EmptyString(), nullptr,
+ dataStringBuf, dataStringLength);
}
JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength,
diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h
index 73a3a02b1f..96f5acf3a2 100644
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -910,7 +910,9 @@ GK_ATOM(onreadystatechange, "onreadystatechange")
GK_ATOM(onreceived, "onreceived")
GK_ATOM(onremoteheld, "onremoteheld")
GK_ATOM(onremoteresumed, "onremoteresumed")
+GK_ATOM(onrequestprogress, "onrequestprogress")
GK_ATOM(onresourcetimingbufferfull, "onresourcetimingbufferfull")
+GK_ATOM(onresponseprogress, "onresponseprogress")
GK_ATOM(onretrieving, "onretrieving")
GK_ATOM(onRequest, "onRequest")
GK_ATOM(onrequestmediaplaystatus, "onrequestmediaplaystatus")
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index dd1fe45862..d696d826bd 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -62,7 +62,7 @@
#include "nsReadableUtils.h"
#include "nsDOMClassInfo.h"
#include "nsJSEnvironment.h"
-#include "ScriptSettings.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/Preferences.h"
#include "mozilla/Likely.h"
#include "mozilla/Sprintf.h"
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index fdaee39ca3..506acc7e4c 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -91,7 +91,6 @@ class nsIVariant;
class nsViewManager;
class nsPresContext;
class nsRange;
-class nsScriptLoader;
class nsSMILAnimationController;
class nsTextNode;
class nsWindowSizes;
@@ -152,6 +151,7 @@ enum class OrientationType : uint32_t;
class ProcessingInstruction;
class Promise;
class Selection;
+class ScriptLoader;
class StyleSheetList;
class SVGDocument;
class SVGSVGElement;
@@ -1290,7 +1290,7 @@ public:
/**
* Get the script loader for this document
*/
- virtual nsScriptLoader* ScriptLoader() = 0;
+ virtual mozilla::dom::ScriptLoader* ScriptLoader() = 0;
/**
* Add/Remove an element to the document's id and name hashes
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
index 212110b729..355bf0ebfa 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -107,6 +107,7 @@
#include "GeometryUtils.h"
#include "nsIAnimationObserver.h"
#include "nsChildContentList.h"
+#include "mozilla/dom/NodeBinding.h"
#ifdef ACCESSIBILITY
#include "mozilla/dom/AccessibleNode.h"
@@ -250,6 +251,30 @@ nsINode::GetTextEditorRootContent(nsIEditor** aEditor)
return nullptr;
}
+nsINode* nsINode::GetRootNode(const GetRootNodeOptions& aOptions)
+{
+ if (aOptions.mComposed) {
+ if (IsInComposedDoc() && GetComposedDoc()) {
+ return OwnerDoc();
+ }
+
+ nsINode* node = this;
+ ShadowRoot* shadowRootParent = nullptr;
+ while(node) {
+ node = node->SubtreeRoot();
+ shadowRootParent = ShadowRoot::FromNode(node);
+ if (!shadowRootParent) {
+ break;
+ }
+ node = shadowRootParent->GetHost();
+ }
+
+ return node;
+ }
+
+ return SubtreeRoot();
+}
+
nsINode*
nsINode::SubtreeRoot() const
{
diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
index d82f5f8990..43d44db607 100644
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -83,6 +83,7 @@ template<typename> class Sequence;
class Text;
class TextOrElementOrDocument;
struct DOMPointInit;
+struct GetRootNodeOptions;
} // namespace dom
} // namespace mozilla
@@ -942,10 +943,11 @@ public:
*/
nsINode* SubtreeRoot() const;
- nsINode* RootNode() const
- {
- return SubtreeRoot();
- }
+ /*
+ * Get context object's shadow-including root if options's composed is true,
+ * and context object's root otherwise.
+ */
+ nsINode* GetRootNode(const mozilla::dom::GetRootNodeOptions& aOptions);
/**
* See nsIDOMEventTarget
diff --git a/dom/base/nsInProcessTabChildGlobal.cpp b/dom/base/nsInProcessTabChildGlobal.cpp
index 10ccf4aec3..2e129f9f0c 100644
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -11,13 +11,13 @@
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsComponentManagerUtils.h"
-#include "nsScriptLoader.h"
#include "nsFrameLoader.h"
#include "xpcpublic.h"
#include "nsIMozBrowserFrame.h"
#include "nsDOMClassInfoID.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/SameProcessMessageQueue.h"
+#include "mozilla/dom/ScriptLoader.h"
using namespace mozilla;
using namespace mozilla::dom;
diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
index efea3ee401..605b1917fd 100644
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -37,7 +37,6 @@
#include "nsXPCOMCIDInternal.h"
#include "nsIXULRuntime.h"
#include "nsTextFormatter.h"
-#include "ScriptSettings.h"
#include "xpcpublic.h"
@@ -55,6 +54,7 @@
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/ErrorEvent.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "nsAXPCNativeCallContext.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/Telemetry.h"
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
index c9cec96db3..5c7e204249 100644
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -306,17 +306,18 @@ nsJSUtils::CompileModule(JSContext* aCx,
}
nsresult
-nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*> aModule)
+nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
{
- PROFILER_LABEL("nsJSUtils", "ModuleDeclarationInstantiation",
+ PROFILER_LABEL("nsJSUtils", "ModuleInstantiate",
js::ProfileEntry::Category::JS);
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(nsContentUtils::IsInMicroTask());
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
- if (!JS::ModuleDeclarationInstantiation(aCx, aModule)) {
+ if (!JS::ModuleInstantiate(aCx, aModule)) {
return NS_ERROR_FAILURE;
}
@@ -324,9 +325,9 @@ nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*>
}
nsresult
-nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
+nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule)
{
- PROFILER_LABEL("nsJSUtils", "ModuleEvaluation",
+ PROFILER_LABEL("nsJSUtils", "ModuleEvaluate",
js::ProfileEntry::Category::JS);
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
@@ -335,7 +336,7 @@ nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
- if (!JS::ModuleEvaluation(aCx, aModule)) {
+ if (!JS::ModuleEvaluate(aCx, aModule)) {
return NS_ERROR_FAILURE;
}
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
index 4affab2d36..9eea6ae83d 100644
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -116,11 +116,11 @@ public:
JS::CompileOptions &aCompileOptions,
JS::MutableHandle<JSObject*> aModule);
- static nsresult ModuleDeclarationInstantiation(JSContext* aCx,
- JS::Handle<JSObject*> aModule);
+ static nsresult ModuleInstantiate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule);
- static nsresult ModuleEvaluation(JSContext* aCx,
- JS::Handle<JSObject*> aModule);
+ static nsresult ModuleEvaluate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule);
// Returns false if an exception got thrown on aCx. Passing a null
// aElement is allowed; that wil produce an empty aScopeChain.
diff --git a/dom/base/nsPlainTextSerializer.h b/dom/base/nsPlainTextSerializer.h
index 650a8e3e73..58aeb42078 100644
--- a/dom/base/nsPlainTextSerializer.h
+++ b/dom/base/nsPlainTextSerializer.h
@@ -16,6 +16,7 @@
#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
#include "nsIAtom.h"
+#include "nsCycleCollectionParticipant.h"
#include "nsIContentSerializer.h"
#include "nsIDocumentEncoder.h"
#include "nsILineBreaker.h"
diff --git a/dom/base/test/jsmodules/test_syntaxError.html b/dom/base/test/jsmodules/test_syntaxError.html
index 53f95c96cc..5bd688fe3f 100644
--- a/dom/base/test/jsmodules/test_syntaxError.html
+++ b/dom/base/test/jsmodules/test_syntaxError.html
@@ -4,20 +4,27 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" src="module_badSyntax.js"></script>
+<script type="module" src="module_badSyntax.js" onerror="eventCount++"></script>
<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorAsync.html b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
index 35d9237553..3593d9dd73 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorAsync.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
@@ -4,20 +4,27 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" src="module_badSyntax.js" async></script>
+<script type="module" src="module_badSyntax.js" async onerror="eventCount++"></script>
<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInline.html b/dom/base/test/jsmodules/test_syntaxErrorInline.html
index 705bc5902e..b85b954ece 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorInline.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorInline.html
@@ -4,22 +4,29 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module">
+<script type="module" onerror="eventCount++">
// Module with a syntax error.
some invalid js syntax;
wasRun = true;
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
index 5e79928234..cc4bf12575 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
@@ -4,22 +4,29 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" async>
+<script type="module" async onerror="eventCount++">
// Module with a syntax error.
some invalid js syntax;
wasRun = true;
diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp
index b174172e01..119a259fe0 100755
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -12,6 +12,7 @@
#include "mozilla/dom/File.h"
#include "mozilla/dom/FunctionBinding.h"
#include "mozilla/dom/Performance.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/WorkletGlobalScope.h"
@@ -22,7 +23,6 @@
#include "nsGlobalWindow.h"
#include "nsJSUtils.h"
#include "nsNetUtil.h"
-#include "ScriptSettings.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"
diff --git a/dom/events/DOMEventTargetHelper.cpp b/dom/events/DOMEventTargetHelper.cpp
index 7daf7f7a77..ea68ead9de 100644
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -8,7 +8,7 @@
#include "nsIDocument.h"
#include "mozilla/Sprintf.h"
#include "nsGlobalWindow.h"
-#include "ScriptSettings.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp
index f944352e3b..191f4cfc3e 100644
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -39,6 +39,7 @@
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
+#include "FetchObserver.h"
#include "InternalRequest.h"
#include "InternalResponse.h"
@@ -52,38 +53,141 @@ namespace dom {
using namespace workers;
+// This class helps the proxying of AbortSignal changes cross threads.
+class AbortSignalProxy final : public AbortSignal::Follower
+{
+ // This is created and released on the main-thread.
+ RefPtr<AbortSignal> mSignalMainThread;
+
+ // This value is used only for the creation of AbortSignal on the
+ // main-thread. They are not updated.
+ const bool mAborted;
+
+ // This runnable propagates changes from the AbortSignal on workers to the
+ // AbortSignal on main-thread.
+ class AbortSignalProxyRunnable final : public Runnable
+ {
+ RefPtr<AbortSignalProxy> mProxy;
+
+ public:
+ explicit AbortSignalProxyRunnable(AbortSignalProxy* aProxy)
+ : mProxy(aProxy)
+ {}
+
+ NS_IMETHOD
+ Run() override
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ AbortSignal* signal = mProxy->GetOrCreateSignalForMainThread();
+ signal->Abort();
+ return NS_OK;
+ }
+ };
+
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbortSignalProxy)
+
+ explicit AbortSignalProxy(AbortSignal* aSignal)
+ : mAborted(aSignal->Aborted())
+ {
+ Follow(aSignal);
+ }
+
+ void
+ Aborted() override
+ {
+ RefPtr<AbortSignalProxyRunnable> runnable =
+ new AbortSignalProxyRunnable(this);
+ NS_DispatchToMainThread(runnable);
+ }
+
+ AbortSignal*
+ GetOrCreateSignalForMainThread()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!mSignalMainThread) {
+ mSignalMainThread = new AbortSignal(mAborted);
+ }
+ return mSignalMainThread;
+ }
+
+ void
+ Shutdown()
+ {
+ Unfollow();
+ }
+
+private:
+ ~AbortSignalProxy()
+ {
+ NS_ReleaseOnMainThread(mSignalMainThread.forget());
+ }
+};
+
class WorkerFetchResolver final : public FetchDriverObserver
{
friend class MainThreadFetchRunnable;
+ friend class WorkerDataAvailableRunnable;
+ friend class WorkerFetchResponseEndBase;
friend class WorkerFetchResponseEndRunnable;
friend class WorkerFetchResponseRunnable;
RefPtr<PromiseWorkerProxy> mPromiseProxy;
+ RefPtr<AbortSignalProxy> mSignalProxy;
+ RefPtr<FetchObserver> mFetchObserver;
+
public:
// Returns null if worker is shutting down.
static already_AddRefed<WorkerFetchResolver>
- Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise)
+ Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise,
+ AbortSignal* aSignal, FetchObserver* aObserver)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
- RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(aWorkerPrivate, aPromise);
+ RefPtr<PromiseWorkerProxy> proxy =
+ PromiseWorkerProxy::Create(aWorkerPrivate, aPromise);
if (!proxy) {
return nullptr;
}
- RefPtr<WorkerFetchResolver> r = new WorkerFetchResolver(proxy);
+ RefPtr<AbortSignalProxy> signalProxy;
+ if (aSignal) {
+ signalProxy = new AbortSignalProxy(aSignal);
+ }
+
+ RefPtr<WorkerFetchResolver> r =
+ new WorkerFetchResolver(proxy, signalProxy, aObserver);
return r.forget();
}
+ AbortSignal*
+ GetAbortSignal()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!mSignalProxy) {
+ return nullptr;
+ }
+
+ return mSignalProxy->GetOrCreateSignalForMainThread();
+ }
+
void
OnResponseAvailableInternal(InternalResponse* aResponse) override;
void
- OnResponseEnd() override;
+ OnResponseEnd(FetchDriverObserver::EndReason eReason) override;
+
+ void
+ OnDataAvailable() override;
private:
- explicit WorkerFetchResolver(PromiseWorkerProxy* aProxy)
+ WorkerFetchResolver(PromiseWorkerProxy* aProxy,
+ AbortSignalProxy* aSignalProxy,
+ FetchObserver* aObserver)
: mPromiseProxy(aProxy)
+ , mSignalProxy(aSignalProxy)
+ , mFetchObserver(aObserver)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mPromiseProxy);
@@ -100,12 +204,16 @@ class MainThreadFetchResolver final : public FetchDriverObserver
{
RefPtr<Promise> mPromise;
RefPtr<Response> mResponse;
+ RefPtr<FetchObserver> mFetchObserver;
nsCOMPtr<nsIDocument> mDocument;
NS_DECL_OWNINGTHREAD
public:
- explicit MainThreadFetchResolver(Promise* aPromise);
+ MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver)
+ : mPromise(aPromise)
+ , mFetchObserver(aObserver)
+ {}
void
OnResponseAvailableInternal(InternalResponse* aResponse) override;
@@ -115,11 +223,20 @@ public:
mDocument = aDocument;
}
- virtual void OnResponseEnd() override
+ void OnResponseEnd(FetchDriverObserver::EndReason aReason) override
{
+ if (aReason == eAborted) {
+ mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ }
+
+ mFetchObserver = nullptr;
+
FlushConsoleReport();
}
+ void
+ OnDataAvailable() override;
+
private:
~MainThreadFetchResolver();
@@ -170,9 +287,11 @@ public:
fetch->SetWorkerScript(spec);
}
+ RefPtr<AbortSignal> signal = mResolver->GetAbortSignal();
+
// ...but release it before calling Fetch, because mResolver's callback can
// be called synchronously and they want the mutex, too.
- return fetch->Fetch(mResolver);
+ return fetch->Fetch(signal, mResolver);
}
};
@@ -210,6 +329,23 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
RefPtr<InternalRequest> r = request->GetInternalRequest();
+ RefPtr<AbortSignal> signal;
+ if (aInit.mSignal.WasPassed()) {
+ signal = &aInit.mSignal.Value();
+ }
+
+ if (signal && signal->Aborted()) {
+ // An already aborted signal should reject immediately.
+ aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
+ return nullptr;
+ }
+
+ RefPtr<FetchObserver> observer;
+ if (aInit.mObserve.WasPassed()) {
+ observer = new FetchObserver(aGlobal, signal);
+ aInit.mObserve.Value().HandleEvent(*observer);
+ }
+
if (NS_IsMainThread()) {
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
nsCOMPtr<nsIDocument> doc;
@@ -236,11 +372,12 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
}
}
- RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
+ RefPtr<MainThreadFetchResolver> resolver =
+ new MainThreadFetchResolver(p, observer);
RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
fetch->SetDocument(doc);
resolver->SetDocument(doc);
- aRv = fetch->Fetch(resolver);
+ aRv = fetch->Fetch(signal, resolver);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
@@ -252,7 +389,8 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
r->SetSkipServiceWorker();
}
- RefPtr<WorkerFetchResolver> resolver = WorkerFetchResolver::Create(worker, p);
+ RefPtr<WorkerFetchResolver> resolver =
+ WorkerFetchResolver::Create(worker, p, signal, observer);
if (!resolver) {
NS_WARNING("Could not add WorkerFetchResolver workerHolder to worker");
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
@@ -266,11 +404,6 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
return p.forget();
}
-MainThreadFetchResolver::MainThreadFetchResolver(Promise* aPromise)
- : mPromise(aPromise)
-{
-}
-
void
MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
{
@@ -278,16 +411,39 @@ MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse
AssertIsOnMainThread();
if (aResponse->Type() != ResponseType::Error) {
+ if (mFetchObserver) {
+ mFetchObserver->SetState(FetchState::Complete);
+ }
+
nsCOMPtr<nsIGlobalObject> go = mPromise->GetParentObject();
mResponse = new Response(go, aResponse);
mPromise->MaybeResolve(mResponse);
} else {
+ if (mFetchObserver) {
+ mFetchObserver->SetState(FetchState::Errored);
+ }
+
ErrorResult result;
result.ThrowTypeError<MSG_FETCH_FAILED>();
mPromise->MaybeReject(result);
}
}
+void
+MainThreadFetchResolver::OnDataAvailable()
+{
+ NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver);
+ AssertIsOnMainThread();
+
+ if (!mFetchObserver) {
+ return;
+ }
+
+ if (mFetchObserver->State() == FetchState::Requesting) {
+ mFetchObserver->SetState(FetchState::Responding);
+ }
+}
+
MainThreadFetchResolver::~MainThreadFetchResolver()
{
NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver);
@@ -306,6 +462,7 @@ public:
, mResolver(aResolver)
, mInternalResponse(aResponse)
{
+ MOZ_ASSERT(mResolver);
}
bool
@@ -317,10 +474,18 @@ public:
RefPtr<Promise> promise = mResolver->mPromiseProxy->WorkerPromise();
if (mInternalResponse->Type() != ResponseType::Error) {
+ if (mResolver->mFetchObserver) {
+ mResolver->mFetchObserver->SetState(FetchState::Complete);
+ }
+
RefPtr<nsIGlobalObject> global = aWorkerPrivate->GlobalScope();
RefPtr<Response> response = new Response(global, mInternalResponse);
promise->MaybeResolve(response);
} else {
+ if (mResolver->mFetchObserver) {
+ mResolver->mFetchObserver->SetState(FetchState::Errored);
+ }
+
ErrorResult result;
result.ThrowTypeError<MSG_FETCH_FAILED>();
promise->MaybeReject(result);
@@ -329,14 +494,42 @@ public:
}
};
+class WorkerDataAvailableRunnable final : public MainThreadWorkerRunnable
+{
+ RefPtr<WorkerFetchResolver> mResolver;
+public:
+ WorkerDataAvailableRunnable(WorkerPrivate* aWorkerPrivate,
+ WorkerFetchResolver* aResolver)
+ : MainThreadWorkerRunnable(aWorkerPrivate)
+ , mResolver(aResolver)
+ {
+ }
+
+ bool
+ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+ {
+ MOZ_ASSERT(aWorkerPrivate);
+ aWorkerPrivate->AssertIsOnWorkerThread();
+
+ if (mResolver->mFetchObserver &&
+ mResolver->mFetchObserver->State() == FetchState::Requesting) {
+ mResolver->mFetchObserver->SetState(FetchState::Responding);
+ }
+
+ return true;
+ }
+};
+
class WorkerFetchResponseEndBase
{
- RefPtr<PromiseWorkerProxy> mPromiseProxy;
+protected:
+ RefPtr<WorkerFetchResolver> mResolver;
+
public:
- explicit WorkerFetchResponseEndBase(PromiseWorkerProxy* aPromiseProxy)
- : mPromiseProxy(aPromiseProxy)
+ explicit WorkerFetchResponseEndBase(WorkerFetchResolver* aResolver)
+ : mResolver(aResolver)
{
- MOZ_ASSERT(mPromiseProxy);
+ MOZ_ASSERT(aResolver);
}
void
@@ -344,23 +537,41 @@ public:
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
- mPromiseProxy->CleanUp();
+
+ mResolver->mPromiseProxy->CleanUp();
+
+ mResolver->mFetchObserver = nullptr;
+
+ if (mResolver->mSignalProxy) {
+ mResolver->mSignalProxy->Shutdown();
+ mResolver->mSignalProxy = nullptr;
+ }
}
};
class WorkerFetchResponseEndRunnable final : public MainThreadWorkerRunnable
, public WorkerFetchResponseEndBase
{
+ FetchDriverObserver::EndReason mReason;
+
public:
- explicit WorkerFetchResponseEndRunnable(PromiseWorkerProxy* aPromiseProxy)
- : MainThreadWorkerRunnable(aPromiseProxy->GetWorkerPrivate())
- , WorkerFetchResponseEndBase(aPromiseProxy)
+ WorkerFetchResponseEndRunnable(WorkerPrivate* aWorkerPrivate,
+ WorkerFetchResolver* aResolver,
+ FetchDriverObserver::EndReason aReason)
+ : MainThreadWorkerRunnable(aWorkerPrivate)
+ , WorkerFetchResponseEndBase(aResolver)
+ , mReason(aReason)
{
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
+ if (mReason == FetchDriverObserver::eAborted) {
+ RefPtr<Promise> promise = mResolver->mPromiseProxy->WorkerPromise();
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ }
+
WorkerRunInternal(aWorkerPrivate);
return true;
}
@@ -379,9 +590,10 @@ class WorkerFetchResponseEndControlRunnable final : public MainThreadWorkerContr
, public WorkerFetchResponseEndBase
{
public:
- explicit WorkerFetchResponseEndControlRunnable(PromiseWorkerProxy* aPromiseProxy)
- : MainThreadWorkerControlRunnable(aPromiseProxy->GetWorkerPrivate())
- , WorkerFetchResponseEndBase(aPromiseProxy)
+ WorkerFetchResponseEndControlRunnable(WorkerPrivate* aWorkerPrivate,
+ WorkerFetchResolver* aResolver)
+ : MainThreadWorkerControlRunnable(aWorkerPrivate)
+ , WorkerFetchResponseEndBase(aResolver)
{
}
@@ -415,7 +627,22 @@ WorkerFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
}
void
-WorkerFetchResolver::OnResponseEnd()
+WorkerFetchResolver::OnDataAvailable()
+{
+ AssertIsOnMainThread();
+
+ MutexAutoLock lock(mPromiseProxy->Lock());
+ if (mPromiseProxy->CleanedUp()) {
+ return;
+ }
+
+ RefPtr<WorkerDataAvailableRunnable> r =
+ new WorkerDataAvailableRunnable(mPromiseProxy->GetWorkerPrivate(), this);
+ Unused << r->Dispatch();
+}
+
+void
+WorkerFetchResolver::OnResponseEnd(FetchDriverObserver::EndReason aReason)
{
AssertIsOnMainThread();
MutexAutoLock lock(mPromiseProxy->Lock());
@@ -426,11 +653,13 @@ WorkerFetchResolver::OnResponseEnd()
FlushConsoleReport();
RefPtr<WorkerFetchResponseEndRunnable> r =
- new WorkerFetchResponseEndRunnable(mPromiseProxy);
+ new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(),
+ this, aReason);
if (!r->Dispatch()) {
RefPtr<WorkerFetchResponseEndControlRunnable> cr =
- new WorkerFetchResponseEndControlRunnable(mPromiseProxy);
+ new WorkerFetchResponseEndControlRunnable(mPromiseProxy->GetWorkerPrivate(),
+ this);
// This can fail if the worker thread is canceled or killed causing
// the PromiseWorkerProxy to give up its WorkerHolder immediately,
// allowing the worker thread to become Dead.
diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp
index 6294b0dc5c..067e32db48 100644
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -67,7 +67,7 @@ FetchDriver::~FetchDriver()
}
nsresult
-FetchDriver::Fetch(FetchDriverObserver* aObserver)
+FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver)
{
workers::AssertIsOnMainThread();
#ifdef DEBUG
@@ -90,6 +90,18 @@ FetchDriver::Fetch(FetchDriverObserver* aObserver)
}
mRequest->SetPrincipalInfo(Move(principalInfo));
+
+ // If the signal is aborted, it's time to inform the observer and terminate
+ // the operation.
+ if (aSignal) {
+ if (aSignal->Aborted()) {
+ Aborted();
+ return NS_OK;
+ }
+
+ Follow(aSignal);
+ }
+
if (NS_FAILED(HttpFetch())) {
FailWithNetworkError();
}
@@ -114,11 +126,7 @@ FetchDriver::HttpFetch()
nsAutoCString url;
mRequest->GetURL(url);
nsCOMPtr<nsIURI> uri;
- rv = NS_NewURI(getter_AddRefs(uri),
- url,
- nullptr,
- nullptr,
- ios);
+ rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr, ios);
NS_ENSURE_SUCCESS(rv, rv);
// Unsafe requests aren't allowed with when using no-core mode.
@@ -380,6 +388,8 @@ FetchDriver::HttpFetch()
NS_ENSURE_SUCCESS(rv, rv);
// Step 4 onwards of "HTTP Fetch" is handled internally by Necko.
+
+ mChannel = chan;
return NS_OK;
}
already_AddRefed<InternalResponse>
@@ -433,9 +443,11 @@ FetchDriver::FailWithNetworkError()
#ifdef DEBUG
mResponseAvailableCalled = true;
#endif
- mObserver->OnResponseEnd();
+ mObserver->OnResponseEnd(FetchDriverObserver::eByNetworking);
mObserver = nullptr;
}
+
+ mChannel = nullptr;
}
namespace {
@@ -655,6 +667,31 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
return NS_OK;
}
+namespace {
+
+// Runnable to call the observer OnDataAvailable on the main-thread.
+class DataAvailableRunnable final : public Runnable
+{
+ RefPtr<FetchDriverObserver> mObserver;
+
+public:
+ explicit DataAvailableRunnable(FetchDriverObserver* aObserver)
+ : mObserver(aObserver)
+ {
+ MOZ_ASSERT(aObserver);
+ }
+
+ NS_IMETHOD
+ Run() override
+ {
+ mObserver->OnDataAvailable();
+ mObserver = nullptr;
+ return NS_OK;
+ }
+};
+
+} // anonymous namespace
+
NS_IMETHODIMP
FetchDriver::OnDataAvailable(nsIRequest* aRequest,
nsISupports* aContext,
@@ -666,6 +703,18 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest,
// called between OnStartRequest and OnStopRequest, so we don't need to worry
// about races.
+ if (mObserver) {
+ if (NS_IsMainThread()) {
+ mObserver->OnDataAvailable();
+ } else {
+ RefPtr<Runnable> runnable = new DataAvailableRunnable(mObserver);
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ }
+
uint32_t aRead;
MOZ_ASSERT(mResponse);
MOZ_ASSERT(mPipeOutputStream);
@@ -777,10 +826,11 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
#endif
}
- mObserver->OnResponseEnd();
+ mObserver->OnResponseEnd(FetchDriverObserver::eByNetworking);
mObserver = nullptr;
}
+ mChannel = nullptr;
return NS_OK;
}
@@ -921,5 +971,21 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const
}
}
+void FetchDriver::Aborted()
+{
+ if (mObserver) {
+#ifdef DEBUG
+ mResponseAvailableCalled = true;
+#endif
+ mObserver->OnResponseEnd(FetchDriverObserver::eAborted);
+ mObserver = nullptr;
+ }
+
+ if (mChannel) {
+ mChannel->Cancel(NS_BINDING_ABORTED);
+ mChannel = nullptr;
+ }
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h
index f74298a48c..57dffa5a70 100644
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -12,6 +12,7 @@
#include "nsIStreamListener.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "mozilla/ConsoleReportCollector.h"
+#include "mozilla/dom/AbortSignal.h"
#include "mozilla/dom/SRIMetadata.h"
#include "mozilla/RefPtr.h"
@@ -49,7 +50,14 @@ public:
mGotResponseAvailable = true;
OnResponseAvailableInternal(aResponse);
}
- virtual void OnResponseEnd()
+
+ enum EndReason
+ {
+ eAborted,
+ eByNetworking,
+ };
+
+ virtual void OnResponseEnd(EndReason aReason)
{ };
nsIConsoleReportCollector* GetReporter() const
@@ -58,6 +66,9 @@ public:
}
virtual void FlushConsoleReport() = 0;
+
+ virtual void OnDataAvailable() = 0;
+
protected:
virtual ~FetchDriverObserver()
{ };
@@ -72,7 +83,8 @@ private:
class FetchDriver final : public nsIStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
- public nsIThreadRetargetableStreamListener
+ public nsIThreadRetargetableStreamListener,
+ public AbortSignal::Follower
{
public:
NS_DECL_ISUPPORTS
@@ -82,9 +94,12 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
- explicit FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
- nsILoadGroup* aLoadGroup);
- NS_IMETHOD Fetch(FetchDriverObserver* aObserver);
+ FetchDriver(InternalRequest* aRequest,
+ nsIPrincipal* aPrincipal,
+ nsILoadGroup* aLoadGroup);
+
+ nsresult Fetch(AbortSignal* aSignal,
+ FetchDriverObserver* aObserver);
void
SetDocument(nsIDocument* aDocument);
@@ -96,6 +111,11 @@ public:
mWorkerScript = aWorkerScirpt;
}
+ // AbortSignal::Follower
+
+ void
+ Aborted() override;
+
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsILoadGroup> mLoadGroup;
@@ -104,6 +124,7 @@ private:
nsCOMPtr<nsIOutputStream> mPipeOutputStream;
RefPtr<FetchDriverObserver> mObserver;
nsCOMPtr<nsIDocument> mDocument;
+ nsCOMPtr<nsIChannel> mChannel;
nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
SRIMetadata mSRIMetadata;
nsCString mWorkerScript;
diff --git a/dom/fetch/FetchObserver.cpp b/dom/fetch/FetchObserver.cpp
new file mode 100644
index 0000000000..93d93773f7
--- /dev/null
+++ b/dom/fetch/FetchObserver.cpp
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FetchObserver.h"
+#include "WorkerPrivate.h"
+#include "mozilla/dom/Event.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(FetchObserver)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchObserver,
+ DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchObserver,
+ DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchObserver)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(FetchObserver, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(FetchObserver, DOMEventTargetHelper)
+
+/* static */ bool
+FetchObserver::IsEnabled(JSContext* aCx, JSObject* aGlobal)
+{
+ if (NS_IsMainThread()) {
+ return Preferences::GetBool("dom.fetchObserver.enabled", false);
+ }
+
+ using namespace workers;
+
+ // Otherwise, check the pref via the WorkerPrivate
+ WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+ if (!workerPrivate) {
+ return false;
+ }
+
+ return workerPrivate->FetchObserverEnabled();
+}
+
+FetchObserver::FetchObserver(nsIGlobalObject* aGlobal,
+ AbortSignal* aSignal)
+ : DOMEventTargetHelper(aGlobal)
+ , mState(FetchState::Requesting)
+{
+ if (aSignal) {
+ Follow(aSignal);
+ }
+}
+
+JSObject*
+FetchObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return FetchObserverBinding::Wrap(aCx, this, aGivenProto);
+}
+
+FetchState
+FetchObserver::State() const
+{
+ return mState;
+}
+
+void
+FetchObserver::Aborted()
+{
+ SetState(FetchState::Aborted);
+}
+
+void
+FetchObserver::SetState(FetchState aState)
+{
+ MOZ_ASSERT(mState < aState);
+
+ if (mState == FetchState::Aborted ||
+ mState == FetchState::Errored ||
+ mState == FetchState::Complete) {
+ // We are already in a final state.
+ return;
+ }
+
+ // We cannot pass from Requesting to Complete directly.
+ if (mState == FetchState::Requesting &&
+ aState == FetchState::Complete) {
+ SetState(FetchState::Responding);
+ }
+
+ mState = aState;
+
+ if (mState == FetchState::Aborted ||
+ mState == FetchState::Errored ||
+ mState == FetchState::Complete) {
+ Unfollow();
+ }
+
+ EventInit init;
+ init.mBubbles = false;
+ init.mCancelable = false;
+
+ // TODO which kind of event should we dispatch here?
+
+ RefPtr<Event> event =
+ Event::Constructor(this, NS_LITERAL_STRING("statechange"), init);
+ event->SetTrusted(true);
+
+ bool dummy;
+ DispatchEvent(event, &dummy);
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/fetch/FetchObserver.h b/dom/fetch/FetchObserver.h
new file mode 100644
index 0000000000..5cd835b3df
--- /dev/null
+++ b/dom/fetch/FetchObserver.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_FetchObserver_h
+#define mozilla_dom_FetchObserver_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/FetchObserverBinding.h"
+#include "mozilla/dom/AbortSignal.h"
+
+namespace mozilla {
+namespace dom {
+
+class FetchObserver final : public DOMEventTargetHelper
+ , public AbortSignal::Follower
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchObserver, DOMEventTargetHelper)
+
+ static bool
+ IsEnabled(JSContext* aCx, JSObject* aGlobal);
+
+ FetchObserver(nsIGlobalObject* aGlobal, AbortSignal* aSignal);
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ FetchState
+ State() const;
+
+ IMPL_EVENT_HANDLER(statechange);
+ IMPL_EVENT_HANDLER(requestprogress);
+ IMPL_EVENT_HANDLER(responseprogress);
+
+ void
+ Aborted() override;
+
+ void
+ SetState(FetchState aState);
+
+private:
+ ~FetchObserver() = default;
+
+ FetchState mState;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_FetchObserver_h
diff --git a/dom/fetch/Request.h b/dom/fetch/Request.h
index d33c748122..f6fe9be7bd 100644
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -12,6 +12,7 @@
#include "nsWrapperCache.h"
#include "mozilla/dom/Fetch.h"
+#include "mozilla/dom/AbortSignal.h"
#include "mozilla/dom/InternalRequest.h"
// Required here due to certain WebIDL enums/classes being declared in both
// files.
diff --git a/dom/fetch/moz.build b/dom/fetch/moz.build
index be820ab570..e2b4664282 100644
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -9,6 +9,7 @@ EXPORTS.mozilla.dom += [
'Fetch.h',
'FetchDriver.h',
'FetchIPCTypes.h',
+ 'FetchObserver.h',
'FetchUtil.h',
'Headers.h',
'InternalHeaders.h',
@@ -28,6 +29,7 @@ UNIFIED_SOURCES += [
SOURCES += [
'ChannelInfo.cpp',
'FetchDriver.cpp',
+ 'FetchObserver.cpp',
'FetchUtil.cpp',
'Headers.cpp',
'InternalHeaders.cpp',
diff --git a/dom/html/HTMLScriptElement.cpp b/dom/html/HTMLScriptElement.cpp
index 095b9b77de..ddeb925eb7 100644
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -37,7 +37,7 @@ HTMLScriptElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
HTMLScriptElement::HTMLScriptElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLElement(aNodeInfo)
- , nsScriptElement(aFromParser)
+ , ScriptElement(aFromParser)
{
AddMutationObserver(this);
}
diff --git a/dom/html/HTMLScriptElement.h b/dom/html/HTMLScriptElement.h
index 19ceb414f9..073cf7faf7 100644
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -8,16 +8,16 @@
#define mozilla_dom_HTMLScriptElement_h
#include "nsIDOMHTMLScriptElement.h"
-#include "nsScriptElement.h"
#include "nsGenericHTMLElement.h"
#include "mozilla/Attributes.h"
+#include "mozilla/dom/ScriptElement.h"
namespace mozilla {
namespace dom {
class HTMLScriptElement final : public nsGenericHTMLElement,
public nsIDOMHTMLScriptElement,
- public nsScriptElement
+ public ScriptElement
{
public:
using Element::GetText;
@@ -96,7 +96,8 @@ protected:
virtual ~HTMLScriptElement();
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
- // nsScriptElement
+
+ // ScriptElement
virtual bool HasScriptContent() override;
};
diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index 1e2f1c1860..ef077cfb2b 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -48,7 +48,6 @@
#include "nsIDocShell.h"
#include "nsNameSpaceManager.h"
#include "nsError.h"
-#include "nsScriptLoader.h"
#include "nsRuleData.h"
#include "nsIPrincipal.h"
#include "nsContainerFrame.h"
@@ -92,6 +91,7 @@
#include "mozilla/dom/FromParser.h"
#include "mozilla/dom/Link.h"
#include "mozilla/BloomFilter.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "nsVariant.h"
#include "nsDOMTokenList.h"
diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp
index 3e8e019b83..409b225ef7 100644
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -19,10 +19,10 @@
#include "nsIHTMLContentSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
-#include "nsScriptLoader.h"
#include "nsIURI.h"
#include "nsIContentViewer.h"
#include "mozilla/dom/NodeInfo.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "nsToken.h"
#include "nsIAppShell.h"
#include "nsCRT.h"
diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h
index f53c74689f..a31687be87 100644
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -17,6 +17,7 @@
#include "MediaMetadataManager.h"
#include "MediaQueue.h"
#include "MediaTimer.h"
+#include "MP3Demuxer.h"
#include "AudioCompactor.h"
#include "Intervals.h"
#include "TimeUnits.h"
diff --git a/dom/media/webspeech/moz.build b/dom/media/webspeech/moz.build
index 677e0656f6..c61c63b720 100644
--- a/dom/media/webspeech/moz.build
+++ b/dom/media/webspeech/moz.build
@@ -3,5 +3,11 @@
# 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/.
+# Due to IPC entanglement we always need the synthesis ipdls
if CONFIG['MOZ_WEBSPEECH']:
DIRS += ['synth']
+else:
+ IPDL_SOURCES += [
+ 'synth/ipc/PSpeechSynthesis.ipdl',
+ 'synth/ipc/PSpeechSynthesisRequest.ipdl',
+ ] \ No newline at end of file
diff --git a/dom/messagechannel/MessagePort.cpp b/dom/messagechannel/MessagePort.cpp
index 56204da995..fcbe36a723 100644
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/messagechannel/MessagePort.cpp
@@ -16,6 +16,7 @@
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/MessagePortChild.h"
#include "mozilla/dom/PMessagePort.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerScope.h"
@@ -28,7 +29,6 @@
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsPresContext.h"
-#include "ScriptSettings.h"
#include "SharedMessagePortMessage.h"
#include "nsIBFCacheEntry.h"
diff --git a/dom/moz.build b/dom/moz.build
index 89c539b4b1..7888ccd69f 100644
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -37,6 +37,7 @@ interfaces = [
DIRS += ['interfaces/' + i for i in interfaces]
DIRS += [
+ 'abort',
'animation',
'apps',
'base',
@@ -99,6 +100,7 @@ DIRS += [
'performance',
'xhr',
'worklet',
+ 'script',
]
if CONFIG['OS_ARCH'] == 'WINNT':
diff --git a/dom/script/ModuleLoadRequest.cpp b/dom/script/ModuleLoadRequest.cpp
new file mode 100644
index 0000000000..d622143044
--- /dev/null
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ModuleLoadRequest.h"
+#include "ModuleScript.h"
+#include "ScriptLoader.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest)
+NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest,
+ mBaseURL,
+ mLoader,
+ mParent,
+ mModuleScript,
+ mImports)
+
+NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
+NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
+
+ModuleLoadRequest::ModuleLoadRequest(nsIScriptElement* aElement,
+ uint32_t aVersion,
+ CORSMode aCORSMode,
+ const SRIMetadata &aIntegrity,
+ ScriptLoader* aLoader)
+ : ScriptLoadRequest(ScriptKind::Module,
+ aElement,
+ aVersion,
+ aCORSMode,
+ aIntegrity),
+ mIsTopLevel(true),
+ mLoader(aLoader)
+{}
+
+void ModuleLoadRequest::Cancel()
+{
+ ScriptLoadRequest::Cancel();
+ mModuleScript = nullptr;
+ mProgress = ScriptLoadRequest::Progress::Ready;
+ CancelImports();
+ mReady.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
+}
+
+void
+ModuleLoadRequest::CancelImports()
+{
+ for (size_t i = 0; i < mImports.Length(); i++) {
+ mImports[i]->Cancel();
+ }
+}
+
+void
+ModuleLoadRequest::SetReady()
+{
+ // Mark a module as ready to execute. This means that this module and all it
+ // dependencies have had their source loaded, parsed as a module and the
+ // modules instantiated.
+ //
+ // The mReady promise is used to ensure that when all dependencies of a module
+ // have become ready, DependenciesLoaded is called on that module
+ // request. This is set up in StartFetchingModuleDependencies.
+
+#ifdef DEBUG
+ for (size_t i = 0; i < mImports.Length(); i++) {
+ MOZ_ASSERT(mImports[i]->IsReadyToRun());
+ }
+#endif
+
+ ScriptLoadRequest::SetReady();
+ mReady.ResolveIfExists(true, __func__);
+}
+
+void
+ModuleLoadRequest::ModuleLoaded()
+{
+ // A module that was found to be marked as fetching in the module map has now
+ // been loaded.
+
+ mModuleScript = mLoader->GetFetchedModule(mURI);
+ if (!mModuleScript || mModuleScript->IsErrored()) {
+ ModuleErrored();
+ return;
+ }
+
+ mLoader->StartFetchingModuleDependencies(this);
+}
+
+void
+ModuleLoadRequest::ModuleErrored()
+{
+ mLoader->CheckModuleDependenciesLoaded(this);
+ MOZ_ASSERT(!mModuleScript || mModuleScript->IsErrored());
+
+ CancelImports();
+ SetReady();
+ LoadFinished();
+}
+
+void
+ModuleLoadRequest::DependenciesLoaded()
+{
+ // The module and all of its dependencies have been successfully fetched and
+ // compiled.
+
+ MOZ_ASSERT(mModuleScript);
+
+ mLoader->CheckModuleDependenciesLoaded(this);
+ SetReady();
+ LoadFinished();
+}
+
+void
+ModuleLoadRequest::LoadFailed()
+{
+ // We failed to load the source text or an error occurred unrelated to the
+ // content of the module (e.g. OOM).
+
+ MOZ_ASSERT(!mModuleScript);
+
+ Cancel();
+ LoadFinished();
+}
+
+void
+ModuleLoadRequest::LoadFinished()
+{
+ mLoader->ProcessLoadedModuleTree(this);
+ mLoader = nullptr;
+ mParent = nullptr;
+}
+
+} // dom namespace
+} // mozilla namespace \ No newline at end of file
diff --git a/dom/script/ModuleLoadRequest.h b/dom/script/ModuleLoadRequest.h
new file mode 100644
index 0000000000..7b06dd2cf3
--- /dev/null
+++ b/dom/script/ModuleLoadRequest.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ModuleLoadRequest_h
+#define mozilla_dom_ModuleLoadRequest_h
+
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/MozPromise.h"
+
+namespace mozilla {
+namespace dom {
+
+class ModuleScript;
+class ScriptLoader;
+
+// A load request for a module, created for every top level module script and
+// every module import. Load request can share a ModuleScript if there are
+// multiple imports of the same module.
+
+class ModuleLoadRequest final : public ScriptLoadRequest
+{
+ ~ModuleLoadRequest() {}
+
+ ModuleLoadRequest(const ModuleLoadRequest& aOther) = delete;
+ ModuleLoadRequest(ModuleLoadRequest&& aOther) = delete;
+
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
+
+ ModuleLoadRequest(nsIScriptElement* aElement,
+ uint32_t aVersion,
+ CORSMode aCORSMode,
+ const SRIMetadata& aIntegrity,
+ ScriptLoader* aLoader);
+
+ bool IsTopLevel() const {
+ return mIsTopLevel;
+ }
+
+ void SetReady() override;
+ void Cancel() override;
+
+ void ModuleLoaded();
+ void ModuleErrored();
+ void DependenciesLoaded();
+ void LoadFailed();
+
+private:
+ void LoadFinished();
+ void CancelImports();
+
+public:
+ // Is this a request for a top level module script or an import?
+ bool mIsTopLevel;
+
+ // The base URL used for resolving relative module imports.
+ nsCOMPtr<nsIURI> mBaseURL;
+
+ // Pointer to the script loader, used to trigger actions when the module load
+ // finishes.
+ RefPtr<ScriptLoader> mLoader;
+
+ // The importing module, or nullptr for top level module scripts. Used to
+ // implement the ancestor list checked when fetching module dependencies.
+ RefPtr<ModuleLoadRequest> mParent;
+
+ // Set to a module script object after a successful load or nullptr on
+ // failure.
+ RefPtr<ModuleScript> mModuleScript;
+
+ // A promise that is completed on successful load of this module and all of
+ // its dependencies, indicating that the module is ready for instantiation and
+ // evaluation.
+ MozPromiseHolder<GenericPromise> mReady;
+
+ // Array of imported modules.
+ nsTArray<RefPtr<ModuleLoadRequest>> mImports;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_ModuleLoadRequest_h \ No newline at end of file
diff --git a/dom/script/ModuleScript.cpp b/dom/script/ModuleScript.cpp
new file mode 100644
index 0000000000..28b97a3cb5
--- /dev/null
+++ b/dom/script/ModuleScript.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * A class that handles loading and evaluation of <script> elements.
+ */
+
+#include "ModuleScript.h"
+#include "mozilla/HoldDropJSObjects.h"
+#include "ScriptLoader.h"
+
+namespace mozilla {
+namespace dom {
+
+// A single module script. May be used to satisfy multiple load requests.
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
+ tmp->UnlinkModuleRecord();
+ tmp->mError.setUndefined();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mError)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
+
+ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL)
+ : mLoader(aLoader),
+ mBaseURL(aBaseURL)
+{
+ MOZ_ASSERT(mLoader);
+ MOZ_ASSERT(mBaseURL);
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
+}
+
+void
+ModuleScript::UnlinkModuleRecord()
+{
+ // Remove module's back reference to this object request if present.
+ if (mModuleRecord) {
+ MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
+ this);
+ JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
+ mModuleRecord = nullptr;
+ }
+}
+
+ModuleScript::~ModuleScript()
+{
+ // The object may be destroyed without being unlinked first.
+ UnlinkModuleRecord();
+ DropJSObjects(this);
+}
+
+void
+ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
+{
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
+
+ mModuleRecord = aModuleRecord;
+
+ // Make module's host defined field point to this module script object.
+ // This is cleared in the UnlinkModuleRecord().
+ JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
+ HoldJSObjects(this);
+}
+
+void
+ModuleScript::SetPreInstantiationError(const JS::Value& aError)
+{
+ MOZ_ASSERT(!aError.isUndefined());
+
+ UnlinkModuleRecord();
+ mError = aError;
+
+ HoldJSObjects(this);
+}
+
+bool
+ModuleScript::IsErrored() const
+{
+ if (!mModuleRecord) {
+ MOZ_ASSERT(!mError.isUndefined());
+ return true;
+ }
+
+ return JS::IsModuleErrored(mModuleRecord);
+}
+
+JS::Value
+ModuleScript::Error() const
+{
+ MOZ_ASSERT(IsErrored());
+
+ if (!mModuleRecord) {
+ return mError;
+ }
+
+ return JS::GetModuleError(mModuleRecord);
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/script/ModuleScript.h b/dom/script/ModuleScript.h
new file mode 100644
index 0000000000..5713598592
--- /dev/null
+++ b/dom/script/ModuleScript.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ModuleScript_h
+#define mozilla_dom_ModuleScript_h
+
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "jsapi.h"
+
+class nsIURI;
+
+namespace mozilla {
+namespace dom {
+
+class ScriptLoader;
+
+class ModuleScript final : public nsISupports
+{
+ RefPtr<ScriptLoader> mLoader;
+ nsCOMPtr<nsIURI> mBaseURL;
+ JS::Heap<JSObject*> mModuleRecord;
+ JS::Heap<JS::Value> mError;
+
+ ~ModuleScript();
+
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
+
+ ModuleScript(ScriptLoader* aLoader,
+ nsIURI* aBaseURL);
+
+ void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
+ void SetPreInstantiationError(const JS::Value& aError);
+
+ ScriptLoader* Loader() const { return mLoader; }
+ JSObject* ModuleRecord() const { return mModuleRecord; }
+ nsIURI* BaseURL() const { return mBaseURL; }
+
+ bool IsErrored() const;
+ JS::Value Error() const;
+
+ void UnlinkModuleRecord();
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_ModuleScript_h \ No newline at end of file
diff --git a/dom/base/nsScriptElement.cpp b/dom/script/ScriptElement.cpp
index ebeb18f81c..0cb17dcb06 100644
--- a/dom/base/nsScriptElement.cpp
+++ b/dom/script/ScriptElement.cpp
@@ -4,13 +4,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsScriptElement.h"
+#include "ScriptElement.h"
+#include "ScriptLoader.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/Element.h"
#include "nsContentUtils.h"
#include "nsPresContext.h"
-#include "nsScriptLoader.h"
#include "nsIParser.h"
#include "nsGkAtoms.h"
#include "nsContentSink.h"
@@ -19,11 +19,11 @@ using namespace mozilla;
using namespace mozilla::dom;
NS_IMETHODIMP
-nsScriptElement::ScriptAvailable(nsresult aResult,
- nsIScriptElement *aElement,
- bool aIsInline,
- nsIURI *aURI,
- int32_t aLineNo)
+ScriptElement::ScriptAvailable(nsresult aResult,
+ nsIScriptElement *aElement,
+ bool aIsInline,
+ nsIURI *aURI,
+ int32_t aLineNo)
{
if (!aIsInline && NS_FAILED(aResult)) {
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
@@ -40,7 +40,7 @@ nsScriptElement::ScriptAvailable(nsresult aResult,
}
/* virtual */ nsresult
-nsScriptElement::FireErrorEvent()
+ScriptElement::FireErrorEvent()
{
nsCOMPtr<nsIContent> cont =
do_QueryInterface((nsIScriptElement*) this);
@@ -53,9 +53,9 @@ nsScriptElement::FireErrorEvent()
}
NS_IMETHODIMP
-nsScriptElement::ScriptEvaluated(nsresult aResult,
- nsIScriptElement *aElement,
- bool aIsInline)
+ScriptElement::ScriptEvaluated(nsresult aResult,
+ nsIScriptElement *aElement,
+ bool aIsInline)
{
nsresult rv = NS_OK;
if (!aIsInline) {
@@ -78,44 +78,44 @@ nsScriptElement::ScriptEvaluated(nsresult aResult,
}
void
-nsScriptElement::CharacterDataChanged(nsIDocument *aDocument,
- nsIContent* aContent,
- CharacterDataChangeInfo* aInfo)
+ScriptElement::CharacterDataChanged(nsIDocument *aDocument,
+ nsIContent* aContent,
+ CharacterDataChangeInfo* aInfo)
{
MaybeProcessScript();
}
void
-nsScriptElement::AttributeChanged(nsIDocument* aDocument,
- Element* aElement,
- int32_t aNameSpaceID,
- nsIAtom* aAttribute,
- int32_t aModType,
- const nsAttrValue* aOldValue)
+ScriptElement::AttributeChanged(nsIDocument* aDocument,
+ Element* aElement,
+ int32_t aNameSpaceID,
+ nsIAtom* aAttribute,
+ int32_t aModType,
+ const nsAttrValue* aOldValue)
{
MaybeProcessScript();
}
void
-nsScriptElement::ContentAppended(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aFirstNewContent,
- int32_t aNewIndexInContainer)
+ScriptElement::ContentAppended(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aFirstNewContent,
+ int32_t aNewIndexInContainer)
{
MaybeProcessScript();
}
void
-nsScriptElement::ContentInserted(nsIDocument *aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- int32_t aIndexInContainer)
+ScriptElement::ContentInserted(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ int32_t aIndexInContainer)
{
MaybeProcessScript();
}
bool
-nsScriptElement::MaybeProcessScript()
+ScriptElement::MaybeProcessScript()
{
nsCOMPtr<nsIContent> cont =
do_QueryInterface((nsIScriptElement*) this);
@@ -145,6 +145,6 @@ nsScriptElement::MaybeProcessScript()
}
}
- RefPtr<nsScriptLoader> loader = ownerDoc->ScriptLoader();
+ RefPtr<ScriptLoader> loader = ownerDoc->ScriptLoader();
return loader->ProcessScriptElement(this);
}
diff --git a/dom/base/nsScriptElement.h b/dom/script/ScriptElement.h
index 4a2a584ac2..0babda674a 100644
--- a/dom/base/nsScriptElement.h
+++ b/dom/script/ScriptElement.h
@@ -4,22 +4,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef nsScriptElement_h
-#define nsScriptElement_h
+#ifndef mozilla_dom_ScriptElement_h
+#define mozilla_dom_ScriptElement_h
#include "mozilla/Attributes.h"
#include "nsIScriptLoaderObserver.h"
#include "nsIScriptElement.h"
#include "nsStubMutationObserver.h"
+namespace mozilla {
+namespace dom {
+
/**
* Baseclass useful for script elements (such as <xhtml:script> and
* <svg:script>). Currently the class assumes that only the 'src'
* attribute and the children of the class affect what script to execute.
*/
-class nsScriptElement : public nsIScriptElement,
- public nsStubMutationObserver
+class ScriptElement : public nsIScriptElement,
+ public nsStubMutationObserver
{
public:
// nsIScriptLoaderObserver
@@ -31,7 +34,7 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
- explicit nsScriptElement(mozilla::dom::FromParser aFromParser)
+ explicit ScriptElement(FromParser aFromParser)
: nsIScriptElement(aFromParser)
{
}
@@ -49,4 +52,7 @@ protected:
virtual bool MaybeProcessScript() override;
};
-#endif // nsScriptElement_h
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_ScriptElement_h
diff --git a/dom/script/ScriptLoadHandler.cpp b/dom/script/ScriptLoadHandler.cpp
new file mode 100644
index 0000000000..80fb70f6ae
--- /dev/null
+++ b/dom/script/ScriptLoadHandler.cpp
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * A class that handles loading and evaluation of <script> elements.
+ */
+
+#include "ScriptLoadHandler.h"
+#include "ScriptLoader.h"
+#include "nsContentUtils.h"
+
+#include "mozilla/dom/EncodingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+ScriptLoadHandler::ScriptLoadHandler(ScriptLoader *aScriptLoader,
+ ScriptLoadRequest *aRequest,
+ mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier)
+ : mScriptLoader(aScriptLoader),
+ mRequest(aRequest),
+ mSRIDataVerifier(aSRIDataVerifier),
+ mSRIStatus(NS_OK),
+ mDecoder(),
+ mBuffer()
+{}
+
+ScriptLoadHandler::~ScriptLoadHandler()
+{}
+
+NS_IMPL_ISUPPORTS(ScriptLoadHandler, nsIIncrementalStreamLoaderObserver)
+
+NS_IMETHODIMP
+ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
+ nsISupports* aContext,
+ uint32_t aDataLength,
+ const uint8_t* aData,
+ uint32_t *aConsumedLength)
+{
+ if (mRequest->IsCanceled()) {
+ // If request cancelled, ignore any incoming data.
+ *aConsumedLength = aDataLength;
+ return NS_OK;
+ }
+
+ if (!EnsureDecoder(aLoader, aData, aDataLength,
+ /* aEndOfStream = */ false)) {
+ return NS_OK;
+ }
+
+ // Below we will/shall consume entire data chunk.
+ *aConsumedLength = aDataLength;
+
+ // Decoder has already been initialized. -- trying to decode all loaded bytes.
+ nsresult rv = TryDecodeRawData(aData, aDataLength,
+ /* aEndOfStream = */ false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // If SRI is required for this load, appending new bytes to the hash.
+ if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
+ mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
+ }
+
+ return rv;
+}
+
+nsresult
+ScriptLoadHandler::TryDecodeRawData(const uint8_t* aData,
+ uint32_t aDataLength,
+ bool aEndOfStream)
+{
+ int32_t srcLen = aDataLength;
+ const char* src = reinterpret_cast<const char *>(aData);
+ int32_t dstLen;
+ nsresult rv =
+ mDecoder->GetMaxLength(src, srcLen, &dstLen);
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t haveRead = mBuffer.length();
+
+ CheckedInt<uint32_t> capacity = haveRead;
+ capacity += dstLen;
+
+ if (!capacity.isValid() || !mBuffer.reserve(capacity.value())) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = mDecoder->Convert(src,
+ &srcLen,
+ mBuffer.begin() + haveRead,
+ &dstLen);
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ haveRead += dstLen;
+ MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
+ MOZ_ALWAYS_TRUE(mBuffer.resizeUninitialized(haveRead));
+
+ return NS_OK;
+}
+
+bool
+ScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
+ const uint8_t* aData,
+ uint32_t aDataLength,
+ bool aEndOfStream)
+{
+ // Check if decoder has already been created.
+ if (mDecoder) {
+ return true;
+ }
+
+ nsAutoCString charset;
+
+ // JavaScript modules are always UTF-8.
+ if (mRequest->IsModuleRequest()) {
+ charset = "UTF-8";
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+ }
+
+ // Determine if BOM check should be done. This occurs either
+ // if end-of-stream has been reached, or at least 3 bytes have
+ // been read from input.
+ if (!aEndOfStream && (aDataLength < 3)) {
+ return false;
+ }
+
+ // Do BOM detection.
+ if (nsContentUtils::CheckForBOM(aData, aDataLength, charset)) {
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+ }
+
+ // BOM detection failed, check content stream for charset.
+ nsCOMPtr<nsIRequest> req;
+ nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
+ NS_ASSERTION(req, "StreamLoader's request went away prematurely");
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
+
+ if (channel &&
+ NS_SUCCEEDED(channel->GetContentCharset(charset)) &&
+ EncodingUtils::FindEncodingForLabel(charset, charset)) {
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+ }
+
+ // Check the hint charset from the script element or preload
+ // request.
+ nsAutoString hintCharset;
+ if (!mRequest->IsPreload()) {
+ mRequest->mElement->GetScriptCharset(hintCharset);
+ } else {
+ nsTArray<ScriptLoader::PreloadInfo>::index_type i =
+ mScriptLoader->mPreloads.IndexOf(mRequest, 0,
+ ScriptLoader::PreloadRequestComparator());
+
+ NS_ASSERTION(i != mScriptLoader->mPreloads.NoIndex,
+ "Incorrect preload bookkeeping");
+ hintCharset = mScriptLoader->mPreloads[i].mCharset;
+ }
+
+ if (EncodingUtils::FindEncodingForLabel(hintCharset, charset)) {
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+ }
+
+ // Get the charset from the charset of the document.
+ if (mScriptLoader->mDocument) {
+ charset = mScriptLoader->mDocument->GetDocumentCharacterSet();
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+ }
+
+ // Curiously, there are various callers that don't pass aDocument. The
+ // fallback in the old code was ISO-8859-1, which behaved like
+ // windows-1252. Saying windows-1252 for clarity and for compliance
+ // with the Encoding Standard.
+ charset = "windows-1252";
+ mDecoder = EncodingUtils::DecoderForEncoding(charset);
+ return true;
+}
+
+NS_IMETHODIMP
+ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
+ nsISupports* aContext,
+ nsresult aStatus,
+ uint32_t aDataLength,
+ const uint8_t* aData)
+{
+ if (!mRequest->IsCanceled()) {
+ DebugOnly<bool> encoderSet =
+ EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
+ MOZ_ASSERT(encoderSet);
+ DebugOnly<nsresult> rv = TryDecodeRawData(aData, aDataLength,
+ /* aEndOfStream = */ true);
+
+ // If SRI is required for this load, appending new bytes to the hash.
+ if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
+ mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
+ }
+ }
+
+ // we have to mediate and use mRequest.
+ return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus,
+ mBuffer, mSRIDataVerifier);
+}
+
+} // dom namespace
+} // mozilla namespace \ No newline at end of file
diff --git a/dom/script/ScriptLoadHandler.h b/dom/script/ScriptLoadHandler.h
new file mode 100644
index 0000000000..b70f873974
--- /dev/null
+++ b/dom/script/ScriptLoadHandler.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * A class that handles loading and evaluation of <script> elements.
+ */
+
+#ifndef mozilla_dom_ScriptLoadHandler_h
+#define mozilla_dom_ScriptLoadHandler_h
+
+#include "nsIIncrementalStreamLoader.h"
+#include "nsIUnicodeDecoder.h"
+#include "nsAutoPtr.h"
+#include "mozilla/Vector.h"
+
+namespace mozilla {
+namespace dom {
+
+class ScriptLoadRequest;
+class ScriptLoader;
+class SRICheckDataVerifier;
+
+class ScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
+{
+public:
+ explicit ScriptLoadHandler(ScriptLoader* aScriptLoader,
+ ScriptLoadRequest* aRequest,
+ SRICheckDataVerifier* aSRIDataVerifier);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
+
+private:
+ virtual ~ScriptLoadHandler();
+
+ /*
+ * Try to decode some raw data.
+ */
+ nsresult TryDecodeRawData(const uint8_t* aData, uint32_t aDataLength,
+ bool aEndOfStream);
+
+ /*
+ * Discover the charset by looking at the stream data, the script
+ * tag, and other indicators. Returns true if charset has been
+ * discovered.
+ */
+ bool EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
+ const uint8_t* aData, uint32_t aDataLength,
+ bool aEndOfStream);
+
+ // ScriptLoader which will handle the parsed script.
+ RefPtr<ScriptLoader> mScriptLoader;
+
+ // The ScriptLoadRequest for this load.
+ RefPtr<ScriptLoadRequest> mRequest;
+
+ // SRI data verifier.
+ nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
+
+ // Status of SRI data operations.
+ nsresult mSRIStatus;
+
+ // Unicode decoder for charset.
+ nsCOMPtr<nsIUnicodeDecoder> mDecoder;
+
+ // Accumulated decoded char buffer.
+ mozilla::Vector<char16_t> mBuffer;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif //mozilla_dom_ScriptLoader_h
diff --git a/dom/base/nsScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index 25482fe7b6..a530989742 100644
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -4,11 +4,10 @@
* 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/. */
-/*
- * A class that handles loading and evaluation of <script> elements.
- */
-
-#include "nsScriptLoader.h"
+#include "ScriptLoader.h"
+#include "ScriptLoadHandler.h"
+#include "ModuleLoadRequest.h"
+#include "ModuleScript.h"
#include "prsystem.h"
#include "jsapi.h"
@@ -58,19 +57,19 @@
#include "mozilla/Unused.h"
#include "nsIScriptError.h"
-using namespace mozilla;
-using namespace mozilla::dom;
-
using JS::SourceBufferHolder;
+namespace mozilla {
+namespace dom {
+
static LazyLogModule gCspPRLog("CSP");
void
-ImplCycleCollectionUnlink(nsScriptLoadRequestList& aField);
+ImplCycleCollectionUnlink(ScriptLoadRequestList& aField);
void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- nsScriptLoadRequestList& aField,
+ ScriptLoadRequestList& aField,
const char* aName,
uint32_t aFlags = 0);
@@ -78,23 +77,23 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
// nsScriptLoadRequest
//////////////////////////////////////////////////////////////
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptLoadRequest)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadRequest)
NS_INTERFACE_MAP_END
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptLoadRequest)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptLoadRequest)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoadRequest)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoadRequest)
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptLoadRequest)
+NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptLoadRequest)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptLoadRequest)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-nsScriptLoadRequest::~nsScriptLoadRequest()
+ScriptLoadRequest::~ScriptLoadRequest()
{
js_free(mScriptTextBuf);
@@ -107,21 +106,21 @@ nsScriptLoadRequest::~nsScriptLoadRequest()
}
void
-nsScriptLoadRequest::SetReady()
+ScriptLoadRequest::SetReady()
{
MOZ_ASSERT(mProgress != Progress::Ready);
mProgress = Progress::Ready;
}
void
-nsScriptLoadRequest::Cancel()
+ScriptLoadRequest::Cancel()
{
MaybeCancelOffThreadScript();
mIsCanceled = true;
}
void
-nsScriptLoadRequest::MaybeCancelOffThreadScript()
+ScriptLoadRequest::MaybeCancelOffThreadScript()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -134,306 +133,28 @@ nsScriptLoadRequest::MaybeCancelOffThreadScript()
mOffThreadToken = nullptr;
}
-//////////////////////////////////////////////////////////////
-// nsModuleLoadRequest
-//////////////////////////////////////////////////////////////
-
-// A load request for a module, created for every top level module script and
-// every module import. Load request can share an nsModuleScript if there are
-// multiple imports of the same module.
-
-class nsModuleLoadRequest final : public nsScriptLoadRequest
-{
- ~nsModuleLoadRequest() {}
-
- nsModuleLoadRequest(const nsModuleLoadRequest& aOther) = delete;
- nsModuleLoadRequest(nsModuleLoadRequest&& aOther) = delete;
-
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsModuleLoadRequest, nsScriptLoadRequest)
-
- nsModuleLoadRequest(nsIScriptElement* aElement,
- uint32_t aVersion,
- CORSMode aCORSMode,
- const SRIMetadata& aIntegrity,
- nsScriptLoader* aLoader);
-
- bool IsTopLevel() const {
- return mIsTopLevel;
- }
-
- void SetReady() override;
- void Cancel() override;
-
- void ModuleLoaded();
- void DependenciesLoaded();
- void LoadFailed();
-
- // Is this a request for a top level module script or an import?
- bool mIsTopLevel;
-
- // The base URL used for resolving relative module imports.
- nsCOMPtr<nsIURI> mBaseURL;
-
- // Pointer to the script loader, used to trigger actions when the module load
- // finishes.
- RefPtr<nsScriptLoader> mLoader;
-
- // The importing module, or nullptr for top level module scripts. Used to
- // implement the ancestor list checked when fetching module dependencies.
- RefPtr<nsModuleLoadRequest> mParent;
-
- // Set to a module script object after a successful load or nullptr on
- // failure.
- RefPtr<nsModuleScript> mModuleScript;
-
- // A promise that is completed on successful load of this module and all of
- // its dependencies, indicating that the module is ready for instantiation and
- // evaluation.
- MozPromiseHolder<GenericPromise> mReady;
-
- // Array of imported modules.
- nsTArray<RefPtr<nsModuleLoadRequest>> mImports;
-};
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsModuleLoadRequest)
-NS_INTERFACE_MAP_END_INHERITING(nsScriptLoadRequest)
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(nsModuleLoadRequest, nsScriptLoadRequest,
- mBaseURL,
- mLoader,
- mParent,
- mModuleScript,
- mImports)
-
-NS_IMPL_ADDREF_INHERITED(nsModuleLoadRequest, nsScriptLoadRequest)
-NS_IMPL_RELEASE_INHERITED(nsModuleLoadRequest, nsScriptLoadRequest)
-
-nsModuleLoadRequest::nsModuleLoadRequest(nsIScriptElement* aElement,
- uint32_t aVersion,
- CORSMode aCORSMode,
- const SRIMetadata &aIntegrity,
- nsScriptLoader* aLoader)
- : nsScriptLoadRequest(nsScriptKind::Module,
- aElement,
- aVersion,
- aCORSMode,
- aIntegrity),
- mIsTopLevel(true),
- mLoader(aLoader)
-{}
-
-inline nsModuleLoadRequest*
-nsScriptLoadRequest::AsModuleRequest()
+inline ModuleLoadRequest*
+ScriptLoadRequest::AsModuleRequest()
{
MOZ_ASSERT(IsModuleRequest());
- return static_cast<nsModuleLoadRequest*>(this);
-}
-
-void nsModuleLoadRequest::Cancel()
-{
- nsScriptLoadRequest::Cancel();
- mModuleScript = nullptr;
- mProgress = nsScriptLoadRequest::Progress::Ready;
- for (size_t i = 0; i < mImports.Length(); i++) {
- mImports[i]->Cancel();
- }
- mReady.RejectIfExists(NS_ERROR_FAILURE, __func__);
-}
-
-void
-nsModuleLoadRequest::SetReady()
-{
-#ifdef DEBUG
- for (size_t i = 0; i < mImports.Length(); i++) {
- MOZ_ASSERT(mImports[i]->IsReadyToRun());
- }
-#endif
-
- nsScriptLoadRequest::SetReady();
- mReady.ResolveIfExists(true, __func__);
-}
-
-void
-nsModuleLoadRequest::ModuleLoaded()
-{
- // A module that was found to be marked as fetching in the module map has now
- // been loaded.
-
- mModuleScript = mLoader->GetFetchedModule(mURI);
- mLoader->StartFetchingModuleDependencies(this);
-}
-
-void
-nsModuleLoadRequest::DependenciesLoaded()
-{
- // The module and all of its dependencies have been successfully fetched and
- // compiled.
-
- if (!mLoader->InstantiateModuleTree(this)) {
- LoadFailed();
- return;
- }
-
- SetReady();
- mLoader->ProcessLoadedModuleTree(this);
- mLoader = nullptr;
- mParent = nullptr;
-}
-
-void
-nsModuleLoadRequest::LoadFailed()
-{
- Cancel();
- mLoader->ProcessLoadedModuleTree(this);
- mLoader = nullptr;
- mParent = nullptr;
-}
-
-//////////////////////////////////////////////////////////////
-// nsModuleScript
-//////////////////////////////////////////////////////////////
-
-// A single module script. May be used to satisfy multiple load requests.
-
-class nsModuleScript final : public nsISupports
-{
- enum InstantiationState {
- Uninstantiated,
- Instantiated,
- Errored
- };
-
- RefPtr<nsScriptLoader> mLoader;
- nsCOMPtr<nsIURI> mBaseURL;
- JS::Heap<JSObject*> mModuleRecord;
- JS::Heap<JS::Value> mException;
- InstantiationState mInstantiationState;
-
- ~nsModuleScript();
-
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsModuleScript)
-
- nsModuleScript(nsScriptLoader* aLoader,
- nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord);
-
- nsScriptLoader* Loader() const { return mLoader; }
- JSObject* ModuleRecord() const { return mModuleRecord; }
- JS::Value Exception() const { return mException; }
- nsIURI* BaseURL() const { return mBaseURL; }
-
- void SetInstantiationResult(JS::Handle<JS::Value> aMaybeException);
- bool IsUninstantiated() const {
- return mInstantiationState == Uninstantiated;
- }
- bool IsInstantiated() const {
- return mInstantiationState == Instantiated;
- }
- bool InstantiationFailed() const {
- return mInstantiationState == Errored;
- }
-
- void UnlinkModuleRecord();
-};
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsModuleScript)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsModuleScript)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsModuleScript)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
- tmp->UnlinkModuleRecord();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsModuleScript)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsModuleScript)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mException)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsModuleScript)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsModuleScript)
-
-nsModuleScript::nsModuleScript(nsScriptLoader *aLoader, nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord)
- : mLoader(aLoader),
- mBaseURL(aBaseURL),
- mModuleRecord(aModuleRecord),
- mInstantiationState(Uninstantiated)
-{
- MOZ_ASSERT(mLoader);
- MOZ_ASSERT(mBaseURL);
- MOZ_ASSERT(mModuleRecord);
- MOZ_ASSERT(mException.isUndefined());
-
- // Make module's host defined field point to this module script object.
- // This is cleared in the UnlinkModuleRecord().
- JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
- HoldJSObjects(this);
-}
-
-void
-nsModuleScript::UnlinkModuleRecord()
-{
- // Remove module's back reference to this object request if present.
- if (mModuleRecord) {
- MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
- this);
- JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
- }
- mModuleRecord = nullptr;
- mException.setUndefined();
-}
-
-nsModuleScript::~nsModuleScript()
-{
- if (mModuleRecord) {
- // The object may be destroyed without being unlinked first.
- UnlinkModuleRecord();
- }
- DropJSObjects(this);
-}
-
-void
-nsModuleScript::SetInstantiationResult(JS::Handle<JS::Value> aMaybeException)
-{
- MOZ_ASSERT(mInstantiationState == Uninstantiated);
- MOZ_ASSERT(mModuleRecord);
- MOZ_ASSERT(mException.isUndefined());
-
- if (aMaybeException.isUndefined()) {
- mInstantiationState = Instantiated;
- } else {
- mModuleRecord = nullptr;
- mException = aMaybeException;
- mInstantiationState = Errored;
- }
+ return static_cast<ModuleLoadRequest*>(this);
}
//////////////////////////////////////////////////////////////
-// nsScriptLoadRequestList
+// ScriptLoadRequestList
//////////////////////////////////////////////////////////////
-nsScriptLoadRequestList::~nsScriptLoadRequestList()
+ScriptLoadRequestList::~ScriptLoadRequestList()
{
Clear();
}
void
-nsScriptLoadRequestList::Clear()
+ScriptLoadRequestList::Clear()
{
while (!isEmpty()) {
- RefPtr<nsScriptLoadRequest> first = StealFirst();
+ RefPtr<ScriptLoadRequest> first = StealFirst();
first->Cancel();
// And just let it go out of scope and die.
}
@@ -441,9 +162,9 @@ nsScriptLoadRequestList::Clear()
#ifdef DEBUG
bool
-nsScriptLoadRequestList::Contains(nsScriptLoadRequest* aElem) const
+ScriptLoadRequestList::Contains(ScriptLoadRequest* aElem) const
{
- for (const nsScriptLoadRequest* req = getFirst();
+ for (const ScriptLoadRequest* req = getFirst();
req; req = req->getNext()) {
if (req == aElem) {
return true;
@@ -455,20 +176,20 @@ nsScriptLoadRequestList::Contains(nsScriptLoadRequest* aElem) const
#endif // DEBUG
inline void
-ImplCycleCollectionUnlink(nsScriptLoadRequestList& aField)
+ImplCycleCollectionUnlink(ScriptLoadRequestList& aField)
{
while (!aField.isEmpty()) {
- RefPtr<nsScriptLoadRequest> first = aField.StealFirst();
+ RefPtr<ScriptLoadRequest> first = aField.StealFirst();
}
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- nsScriptLoadRequestList& aField,
+ ScriptLoadRequestList& aField,
const char* aName,
uint32_t aFlags)
{
- for (nsScriptLoadRequest* request = aField.getFirst();
+ for (ScriptLoadRequest* request = aField.getFirst();
request; request = request->getNext())
{
CycleCollectionNoteChild(aCallback, request, aName, aFlags);
@@ -476,18 +197,18 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
}
//////////////////////////////////////////////////////////////
-// nsScriptLoader::PreloadInfo
+// ScriptLoader::PreloadInfo
//////////////////////////////////////////////////////////////
inline void
-ImplCycleCollectionUnlink(nsScriptLoader::PreloadInfo& aField)
+ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField)
{
ImplCycleCollectionUnlink(aField.mRequest);
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- nsScriptLoader::PreloadInfo& aField,
+ ScriptLoader::PreloadInfo& aField,
const char* aName,
uint32_t aFlags = 0)
{
@@ -495,13 +216,13 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
}
//////////////////////////////////////////////////////////////
-// nsScriptLoader
+// ScriptLoader
//////////////////////////////////////////////////////////////
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptLoader)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoader)
NS_INTERFACE_MAP_END
-NS_IMPL_CYCLE_COLLECTION(nsScriptLoader,
+NS_IMPL_CYCLE_COLLECTION(ScriptLoader,
mNonAsyncExternalScriptInsertedRequests,
mLoadingAsyncRequests,
mLoadedAsyncRequests,
@@ -512,10 +233,10 @@ NS_IMPL_CYCLE_COLLECTION(nsScriptLoader,
mPendingChildLoaders,
mFetchedModules)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptLoader)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptLoader)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoader)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoader)
-nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
+ScriptLoader::ScriptLoader(nsIDocument *aDocument)
: mDocument(aDocument),
mParserBlockingBlockerCount(0),
mBlockerCount(0),
@@ -528,7 +249,7 @@ nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
{
}
-nsScriptLoader::~nsScriptLoader()
+ScriptLoader::~ScriptLoader()
{
mObservers.Clear();
@@ -536,27 +257,27 @@ nsScriptLoader::~nsScriptLoader()
mParserBlockingRequest->FireScriptAvailable(NS_ERROR_ABORT);
}
- for (nsScriptLoadRequest* req = mXSLTRequests.getFirst(); req;
+ for (ScriptLoadRequest* req = mXSLTRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
- for (nsScriptLoadRequest* req = mDeferRequests.getFirst(); req;
+ for (ScriptLoadRequest* req = mDeferRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
- for (nsScriptLoadRequest* req = mLoadingAsyncRequests.getFirst(); req;
+ for (ScriptLoadRequest* req = mLoadingAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
- for (nsScriptLoadRequest* req = mLoadedAsyncRequests.getFirst(); req;
+ for (ScriptLoadRequest* req = mLoadedAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
- for(nsScriptLoadRequest* req = mNonAsyncExternalScriptInsertedRequests.getFirst();
+ for(ScriptLoadRequest* req = mNonAsyncExternalScriptInsertedRequests.getFirst();
req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
@@ -623,11 +344,11 @@ IsScriptEventHandler(nsIContent* aScriptElement)
}
nsresult
-nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
- nsISupports *aContext,
- nsIURI *aURI,
- const nsAString &aType,
- bool aIsPreLoad)
+ScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
+ nsISupports *aContext,
+ nsIURI *aURI,
+ const nsAString &aType,
+ bool aIsPreLoad)
{
nsContentPolicyType contentPolicyType = aIsPreLoad
? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
@@ -654,7 +375,7 @@ nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
}
bool
-nsScriptLoader::ModuleScriptsEnabled()
+ScriptLoader::ModuleScriptsEnabled()
{
static bool sEnabledForContent = false;
static bool sCachedPref = false;
@@ -667,7 +388,7 @@ nsScriptLoader::ModuleScriptsEnabled()
}
bool
-nsScriptLoader::ModuleMapContainsModule(nsModuleLoadRequest *aRequest) const
+ScriptLoader::ModuleMapContainsModule(ModuleLoadRequest *aRequest) const
{
// Returns whether we have fetched, or are currently fetching, a module script
// for the request's URL.
@@ -676,7 +397,7 @@ nsScriptLoader::ModuleMapContainsModule(nsModuleLoadRequest *aRequest) const
}
bool
-nsScriptLoader::IsFetchingModule(nsModuleLoadRequest *aRequest) const
+ScriptLoader::IsFetchingModule(ModuleLoadRequest *aRequest) const
{
bool fetching = mFetchingModules.Contains(aRequest->mURI);
MOZ_ASSERT_IF(fetching, !mFetchedModules.Contains(aRequest->mURI));
@@ -684,7 +405,7 @@ nsScriptLoader::IsFetchingModule(nsModuleLoadRequest *aRequest) const
}
void
-nsScriptLoader::SetModuleFetchStarted(nsModuleLoadRequest *aRequest)
+ScriptLoader::SetModuleFetchStarted(ModuleLoadRequest *aRequest)
{
// Update the module map to indicate that a module is currently being fetched.
@@ -694,24 +415,26 @@ nsScriptLoader::SetModuleFetchStarted(nsModuleLoadRequest *aRequest)
}
void
-nsScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(nsModuleLoadRequest *aRequest,
- nsresult aResult)
+ScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
+ nsresult aResult)
{
- // Update module map with the result of fetching a single module script. The
- // module script pointer is nullptr on error.
-
- MOZ_ASSERT(!aRequest->IsReadyToRun());
+ // Update module map with the result of fetching a single module script.
+ //
+ // If any requests for the same URL are waiting on this one to complete, they
+ // will have ModuleLoaded or LoadFailed on them when the promise is
+ // resolved/rejected. This is set up in StartLoad.
RefPtr<GenericPromise::Private> promise;
MOZ_ALWAYS_TRUE(mFetchingModules.Get(aRequest->mURI, getter_AddRefs(promise)));
mFetchingModules.Remove(aRequest->mURI);
- RefPtr<nsModuleScript> ms(aRequest->mModuleScript);
- MOZ_ASSERT(NS_SUCCEEDED(aResult) == (ms != nullptr));
- mFetchedModules.Put(aRequest->mURI, ms);
+ RefPtr<ModuleScript> moduleScript(aRequest->mModuleScript);
+ MOZ_ASSERT(NS_FAILED(aResult) == !moduleScript);
+
+ mFetchedModules.Put(aRequest->mURI, moduleScript);
if (promise) {
- if (ms) {
+ if (moduleScript) {
promise->Resolve(true, __func__);
} else {
promise->Reject(aResult, __func__);
@@ -720,7 +443,7 @@ nsScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(nsModuleLoadReque
}
RefPtr<GenericPromise>
-nsScriptLoader::WaitForModuleFetch(nsModuleLoadRequest *aRequest)
+ScriptLoader::WaitForModuleFetch(ModuleLoadRequest *aRequest)
{
MOZ_ASSERT(ModuleMapContainsModule(aRequest));
@@ -733,7 +456,7 @@ nsScriptLoader::WaitForModuleFetch(nsModuleLoadRequest *aRequest)
return promise;
}
- RefPtr<nsModuleScript> ms;
+ RefPtr<ModuleScript> ms;
MOZ_ALWAYS_TRUE(mFetchedModules.Get(aRequest->mURI, getter_AddRefs(ms)));
if (!ms) {
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
@@ -742,36 +465,46 @@ nsScriptLoader::WaitForModuleFetch(nsModuleLoadRequest *aRequest)
return GenericPromise::CreateAndResolve(true, __func__);
}
-nsModuleScript*
-nsScriptLoader::GetFetchedModule(nsIURI* aURL) const
+ModuleScript*
+ScriptLoader::GetFetchedModule(nsIURI* aURL) const
{
bool found;
- nsModuleScript* ms = mFetchedModules.GetWeak(aURL, &found);
+ ModuleScript* ms = mFetchedModules.GetWeak(aURL, &found);
MOZ_ASSERT(found);
return ms;
}
nsresult
-nsScriptLoader::ProcessFetchedModuleSource(nsModuleLoadRequest* aRequest)
+ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(!aRequest->mModuleScript);
nsresult rv = CreateModuleScript(aRequest);
+ MOZ_ASSERT(NS_FAILED(rv) == !aRequest->mModuleScript);
+
SetModuleFetchFinishedAndResumeWaitingRequests(aRequest, rv);
free(aRequest->mScriptTextBuf);
aRequest->mScriptTextBuf = nullptr;
aRequest->mScriptTextLength = 0;
- if (NS_SUCCEEDED(rv)) {
+ if (NS_FAILED(rv)) {
+ aRequest->LoadFailed();
+ return rv;
+ }
+
+ if (!aRequest->mModuleScript->IsErrored()) {
StartFetchingModuleDependencies(aRequest);
}
- return rv;
+ return NS_OK;
}
+static nsresult
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>& aUrls);
+
nsresult
-nsScriptLoader::CreateModuleScript(nsModuleLoadRequest* aRequest)
+ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(!aRequest->mModuleScript);
MOZ_ASSERT(aRequest->mBaseURL);
@@ -823,9 +556,34 @@ nsScriptLoader::CreateModuleScript(nsModuleLoadRequest* aRequest)
}
}
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
- if (module) {
- aRequest->mModuleScript =
- new nsModuleScript(this, aRequest->mBaseURL, module);
+ RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
+ aRequest->mModuleScript = moduleScript;
+
+ if (!module) {
+ // Compilation failed
+ MOZ_ASSERT(aes.HasException());
+ JS::Rooted<JS::Value> error(cx);
+ if (!aes.StealException(&error)) {
+ aRequest->mModuleScript = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ moduleScript->SetPreInstantiationError(error);
+ aRequest->ModuleErrored();
+ return NS_OK;
+ }
+
+ moduleScript->SetModuleRecord(module);
+
+ // Validate requested modules and treat failure to resolve module specifiers
+ // the same as a parse error.
+ nsCOMArray<nsIURI> urls;
+ rv = ResolveRequestedModules(aRequest, urls);
+ if (NS_FAILED(rv)) {
+ // ResolveRequestedModules sets pre-instanitation error on failure.
+ MOZ_ASSERT(moduleScript->IsErrored());
+ aRequest->ModuleErrored();
+ return NS_OK;
}
}
@@ -835,8 +593,8 @@ nsScriptLoader::CreateModuleScript(nsModuleLoadRequest* aRequest)
}
static bool
-ThrowTypeError(JSContext* aCx, nsModuleScript* aScript,
- const nsString& aMessage)
+CreateTypeError(JSContext* aCx, ModuleScript* aScript, const nsString& aMessage,
+ JS::MutableHandle<JS::Value> aError)
{
JS::Rooted<JSObject*> module(aCx, aScript->ModuleRecord());
JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aCx, module));
@@ -851,18 +609,12 @@ ThrowTypeError(JSContext* aCx, nsModuleScript* aScript,
return false;
}
- JS::Rooted<JS::Value> error(aCx);
- if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
- message, &error)) {
- return false;
- }
-
- JS_SetPendingException(aCx, error);
- return false;
+ return JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
+ message, aError);
}
-static bool
-HandleResolveFailure(JSContext* aCx, nsModuleScript* aScript,
+static nsresult
+HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
const nsAString& aSpecifier)
{
// TODO: How can we get the line number of the failed import?
@@ -870,23 +622,17 @@ HandleResolveFailure(JSContext* aCx, nsModuleScript* aScript,
nsAutoString message(NS_LITERAL_STRING("Error resolving module specifier: "));
message.Append(aSpecifier);
- return ThrowTypeError(aCx, aScript, message);
-}
-
-static bool
-HandleModuleNotFound(JSContext* aCx, nsModuleScript* aScript,
- const nsAString& aSpecifier)
-{
- // TODO: How can we get the line number of the failed import?
-
- nsAutoString message(NS_LITERAL_STRING("Resolved module not found in map: "));
- message.Append(aSpecifier);
+ JS::Rooted<JS::Value> error(aCx);
+ if (!CreateTypeError(aCx, aScript, message, &error)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
- return ThrowTypeError(aCx, aScript, message);
+ aScript->SetPreInstantiationError(error);
+ return NS_OK;
}
static already_AddRefed<nsIURI>
-ResolveModuleSpecifier(nsModuleScript* aScript,
+ResolveModuleSpecifier(ModuleScript* aScript,
const nsAString& aSpecifier)
{
// The following module specifiers are allowed by the spec:
@@ -921,7 +667,7 @@ ResolveModuleSpecifier(nsModuleScript* aScript,
}
static nsresult
-RequestedModuleIsInAncestorList(nsModuleLoadRequest* aRequest, nsIURI* aURL, bool* aResult)
+RequestedModuleIsInAncestorList(ModuleLoadRequest* aRequest, nsIURI* aURL, bool* aResult)
{
const size_t ImportDepthLimit = 100;
@@ -947,9 +693,9 @@ RequestedModuleIsInAncestorList(nsModuleLoadRequest* aRequest, nsIURI* aURL, boo
}
static nsresult
-ResolveRequestedModules(nsModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
{
- nsModuleScript* ms = aRequest->mModuleScript;
+ ModuleScript* ms = aRequest->mModuleScript;
AutoJSAPI jsapi;
if (!jsapi.Init(ms->ModuleRecord())) {
@@ -977,10 +723,11 @@ ResolveRequestedModules(nsModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls
}
// Let url be the result of resolving a module specifier given module script and requested.
- nsModuleScript* ms = aRequest->mModuleScript;
+ ModuleScript* ms = aRequest->mModuleScript;
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
if (!uri) {
- HandleResolveFailure(cx, ms, specifier);
+ nsresult rv = HandleResolveFailure(cx, ms, specifier);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_ERROR_FAILURE;
}
@@ -996,16 +743,18 @@ ResolveRequestedModules(nsModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls
}
void
-nsScriptLoader::StartFetchingModuleDependencies(nsModuleLoadRequest* aRequest)
+ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mModuleScript);
+ MOZ_ASSERT(!aRequest->mModuleScript->IsErrored());
MOZ_ASSERT(!aRequest->IsReadyToRun());
- aRequest->mProgress = nsModuleLoadRequest::Progress::FetchingImports;
+
+ aRequest->mProgress = ModuleLoadRequest::Progress::FetchingImports;
nsCOMArray<nsIURI> urls;
nsresult rv = ResolveRequestedModules(aRequest, urls);
if (NS_FAILED(rv)) {
- aRequest->LoadFailed();
+ aRequest->ModuleErrored();
return;
}
@@ -1028,19 +777,19 @@ nsScriptLoader::StartFetchingModuleDependencies(nsModuleLoadRequest* aRequest)
RefPtr<GenericPromise::AllPromiseType> allReady =
GenericPromise::All(AbstractThread::GetCurrent(), importsReady);
allReady->Then(AbstractThread::GetCurrent(), __func__, aRequest,
- &nsModuleLoadRequest::DependenciesLoaded,
- &nsModuleLoadRequest::LoadFailed);
+ &ModuleLoadRequest::DependenciesLoaded,
+ &ModuleLoadRequest::ModuleErrored);
}
RefPtr<GenericPromise>
-nsScriptLoader::StartFetchingModuleAndDependencies(nsModuleLoadRequest* aRequest,
- nsIURI* aURI)
+ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
+ nsIURI* aURI)
{
MOZ_ASSERT(aURI);
- RefPtr<nsModuleLoadRequest> childRequest =
- new nsModuleLoadRequest(aRequest->mElement, aRequest->mJSVersion,
- aRequest->mCORSMode, aRequest->mIntegrity, this);
+ RefPtr<ModuleLoadRequest> childRequest =
+ new ModuleLoadRequest(aRequest->mElement, aRequest->mJSVersion,
+ aRequest->mCORSMode, aRequest->mIntegrity, this);
childRequest->mIsTopLevel = false;
childRequest->mURI = aURI;
@@ -1052,6 +801,7 @@ nsScriptLoader::StartFetchingModuleAndDependencies(nsModuleLoadRequest* aRequest
nsresult rv = StartLoad(childRequest, NS_LITERAL_STRING("module"), false);
if (NS_FAILED(rv)) {
+ MOZ_ASSERT(!childRequest->mModuleScript);
childRequest->mReady.Reject(rv, __func__);
return ready;
}
@@ -1060,6 +810,7 @@ nsScriptLoader::StartFetchingModuleAndDependencies(nsModuleLoadRequest* aRequest
return ready;
}
+// 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
bool
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
{
@@ -1070,35 +821,29 @@ HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
// Let referencing module script be referencingModule.[[HostDefined]].
JS::Value value = JS::GetModuleHostDefinedField(module);
- auto script = static_cast<nsModuleScript*>(value.toPrivate());
+ auto script = static_cast<ModuleScript*>(value.toPrivate());
MOZ_ASSERT(script->ModuleRecord() == module);
// Let url be the result of resolving a module specifier given referencing
- // module script and specifier. If the result is failure, throw a TypeError
- // exception and abort these steps.
+ // module script and specifier.
nsAutoJSString string;
if (!string.init(aCx, specifier)) {
return false;
}
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
- if (!uri) {
- return HandleResolveFailure(aCx, script, string);
- }
- // Let resolved module script be the value of the entry in module map whose
- // key is url. If no such entry exists, throw a TypeError exception and abort
- // these steps.
- nsModuleScript* ms = script->Loader()->GetFetchedModule(uri);
- if (!ms) {
- return HandleModuleNotFound(aCx, script, string);
- }
+ // This cannot fail because resolving a module specifier must have been
+ // previously successful with these same two arguments.
+ MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
- if (ms->InstantiationFailed()) {
- JS::Rooted<JS::Value> exception(aCx, ms->Exception());
- JS_SetPendingException(aCx, exception);
- return false;
- }
+ // Let resolved module script be moduleMap[url]. (This entry must exist for us
+ // to have gotten to this point.)
+
+ ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
+ MOZ_ASSERT(ms, "Resolved module not found in module map");
+
+ MOZ_ASSERT(!ms->IsErrored());
*vp = JS::ObjectValue(*ms->ModuleRecord());
return true;
@@ -1123,9 +868,35 @@ EnsureModuleResolveHook(JSContext* aCx)
}
void
-nsScriptLoader::ProcessLoadedModuleTree(nsModuleLoadRequest* aRequest)
+ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
+{
+ RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ for (auto childRequest : aRequest->mImports) {
+ ModuleScript* childScript = childRequest->mModuleScript;
+ if (!childScript) {
+ // Load error
+ aRequest->mModuleScript = nullptr;
+ return;
+ } else if (childScript->IsErrored()) {
+ // Script error
+ moduleScript->SetPreInstantiationError(childScript->Error());
+ return;
+ }
+ }
+ }
+}
+
+void
+ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
{
if (aRequest->IsTopLevel()) {
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ if (!InstantiateModuleTree(aRequest)) {
+ aRequest->mModuleScript = nullptr;
+ }
+ }
MaybeMoveToLoadedList(aRequest);
ProcessPendingRequests();
}
@@ -1136,70 +907,45 @@ nsScriptLoader::ProcessLoadedModuleTree(nsModuleLoadRequest* aRequest)
}
bool
-nsScriptLoader::InstantiateModuleTree(nsModuleLoadRequest* aRequest)
+ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
{
- // Perform eager instantiation of the loaded module tree.
+ // Instantiate a top-level module and record any error.
MOZ_ASSERT(aRequest);
+ MOZ_ASSERT(aRequest->IsTopLevel());
- nsModuleScript* ms = aRequest->mModuleScript;
- MOZ_ASSERT(ms);
- if (!ms || !ms->ModuleRecord()) {
- return false;
- }
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ MOZ_ASSERT(moduleScript);
+ MOZ_ASSERT(moduleScript->ModuleRecord());
+ nsAutoMicroTask mt;
AutoJSAPI jsapi;
- if (NS_WARN_IF(!jsapi.Init(ms->ModuleRecord()))) {
+ if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
return false;
}
nsresult rv = EnsureModuleResolveHook(jsapi.cx());
NS_ENSURE_SUCCESS(rv, false);
- JS::Rooted<JSObject*> module(jsapi.cx(), ms->ModuleRecord());
- bool ok = NS_SUCCEEDED(nsJSUtils::ModuleDeclarationInstantiation(jsapi.cx(), module));
+ JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
+ bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
- JS::RootedValue exception(jsapi.cx());
if (!ok) {
MOZ_ASSERT(jsapi.HasException());
+ JS::RootedValue exception(jsapi.cx());
if (!jsapi.StealException(&exception)) {
return false;
}
MOZ_ASSERT(!exception.isUndefined());
- }
-
- // Mark this module and any uninstantiated dependencies found via depth-first
- // search as instantiated and record any error.
-
- mozilla::Vector<nsModuleLoadRequest*, 1> requests;
- if (!requests.append(aRequest)) {
- return false;
- }
-
- while (!requests.empty()) {
- nsModuleLoadRequest* request = requests.popCopy();
- nsModuleScript* ms = request->mModuleScript;
- if (!ms->IsUninstantiated()) {
- continue;
- }
-
- ms->SetInstantiationResult(exception);
-
- for (auto import : request->mImports) {
- if (import->mModuleScript->IsUninstantiated() &&
- !requests.append(import))
- {
- return false;
- }
- }
+ // Ignore the exception. It will be recorded in the module record.
}
return true;
}
nsresult
-nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
- bool aScriptFromHead)
+ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
+ bool aScriptFromHead)
{
MOZ_ASSERT(aRequest->IsLoading());
NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER);
@@ -1212,12 +958,12 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
if (aRequest->IsModuleRequest()) {
// Check whether the module has been fetched or is currently being fetched,
// and if so wait for it.
- nsModuleLoadRequest* request = aRequest->AsModuleRequest();
+ ModuleLoadRequest* request = aRequest->AsModuleRequest();
if (ModuleMapContainsModule(request)) {
WaitForModuleFetch(request)
->Then(AbstractThread::GetCurrent(), __func__, request,
- &nsModuleLoadRequest::ModuleLoaded,
- &nsModuleLoadRequest::LoadFailed);
+ &ModuleLoadRequest::ModuleLoaded,
+ &ModuleLoadRequest::LoadFailed);
return NS_OK;
}
@@ -1330,8 +1076,8 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
mReporter);
}
- RefPtr<nsScriptLoadHandler> handler =
- new nsScriptLoadHandler(this, aRequest, sriDataVerifier.forget());
+ RefPtr<ScriptLoadHandler> handler =
+ new ScriptLoadHandler(this, aRequest, sriDataVerifier.forget());
nsCOMPtr<nsIIncrementalStreamLoader> loader;
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
@@ -1341,22 +1087,22 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
}
bool
-nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
- nsIURI * const &aURI) const
+ScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
+ nsIURI * const &aURI) const
{
bool same;
return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
same;
}
-class nsScriptRequestProcessor : public Runnable
+class ScriptRequestProcessor : public Runnable
{
private:
- RefPtr<nsScriptLoader> mLoader;
- RefPtr<nsScriptLoadRequest> mRequest;
+ RefPtr<ScriptLoader> mLoader;
+ RefPtr<ScriptLoadRequest> mRequest;
public:
- nsScriptRequestProcessor(nsScriptLoader* aLoader,
- nsScriptLoadRequest* aRequest)
+ ScriptRequestProcessor(ScriptLoader* aLoader,
+ ScriptLoadRequest* aRequest)
: mLoader(aLoader)
, mRequest(aRequest)
{}
@@ -1428,24 +1174,23 @@ CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument)
return allowInlineScript;
}
-nsScriptLoadRequest*
-nsScriptLoader::CreateLoadRequest(nsScriptKind aKind,
- nsIScriptElement* aElement,
- uint32_t aVersion, CORSMode aCORSMode,
- const SRIMetadata &aIntegrity)
+ScriptLoadRequest*
+ScriptLoader::CreateLoadRequest(ScriptKind aKind,
+ nsIScriptElement* aElement,
+ uint32_t aVersion, CORSMode aCORSMode,
+ const SRIMetadata &aIntegrity)
{
- if (aKind == nsScriptKind::Classic) {
- return new nsScriptLoadRequest(aKind, aElement, aVersion, aCORSMode,
- aIntegrity);
+ if (aKind == ScriptKind::Classic) {
+ return new ScriptLoadRequest(aKind, aElement, aVersion, aCORSMode,
+ aIntegrity);
}
- MOZ_ASSERT(aKind == nsScriptKind::Module);
- return new nsModuleLoadRequest(aElement, aVersion, aCORSMode, aIntegrity,
- this);
+ MOZ_ASSERT(aKind == ScriptKind::Module);
+ return new ModuleLoadRequest(aElement, aVersion, aCORSMode, aIntegrity, this);
}
bool
-nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
+ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
{
// We need a document to evaluate scripts.
NS_ENSURE_TRUE(mDocument, false);
@@ -1471,10 +1216,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
nsAutoString type;
bool hasType = aElement->GetScriptType(type);
- nsScriptKind scriptKind = nsScriptKind::Classic;
+ ScriptKind scriptKind = ScriptKind::Classic;
if (!type.IsEmpty()) {
if (ModuleScriptsEnabled() && type.LowerCaseEqualsASCII("module")) {
- scriptKind = nsScriptKind::Module;
+ scriptKind = ScriptKind::Module;
} else {
NS_ENSURE_TRUE(ParseTypeAttribute(type, &version), false);
}
@@ -1498,7 +1243,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// "The nomodule attribute must not be specified on module scripts (and will
// be ignored if it is)."
if (ModuleScriptsEnabled() &&
- scriptKind == nsScriptKind::Classic &&
+ scriptKind == ScriptKind::Classic &&
scriptContent->IsHTMLElement() &&
scriptContent->HasAttr(kNameSpaceID_None, nsGkAtoms::nomodule)) {
return false;
@@ -1506,7 +1251,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Step 15. and later in the HTML5 spec
nsresult rv = NS_OK;
- RefPtr<nsScriptLoadRequest> request;
+ RefPtr<ScriptLoadRequest> request;
if (aElement->GetScriptExternal()) {
// external script
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
@@ -1562,7 +1307,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
integrity);
if (!integrity.IsEmpty()) {
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
- ("nsScriptLoader::ProcessScriptElement, integrity=%s",
+ ("ScriptLoader::ProcessScriptElement, integrity=%s",
NS_ConvertUTF16toUTF8(integrity).get()));
nsAutoCString sourceUri;
if (mDocument->GetDocumentURI()) {
@@ -1704,19 +1449,25 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
request->mLineNo = aElement->GetScriptLineNumber();
if (request->IsModuleRequest()) {
- nsModuleLoadRequest* modReq = request->AsModuleRequest();
+ ModuleLoadRequest* modReq = request->AsModuleRequest();
modReq->mBaseURL = mDocument->GetDocBaseURI();
rv = CreateModuleScript(modReq);
- NS_ENSURE_SUCCESS(rv, false);
- StartFetchingModuleDependencies(modReq);
+ MOZ_ASSERT(NS_FAILED(rv) == !modReq->mModuleScript);
+ if (NS_FAILED(rv)) {
+ modReq->LoadFailed();
+ return false;
+ }
if (aElement->GetScriptAsync()) {
mLoadingAsyncRequests.AppendElement(request);
} else {
AddDeferRequest(request);
}
+ if (!modReq->mModuleScript->IsErrored()) {
+ StartFetchingModuleDependencies(modReq);
+ }
return false;
}
- request->mProgress = nsScriptLoadRequest::Progress::Ready;
+ request->mProgress = ScriptLoadRequest::Progress::Ready;
if (aElement->GetParserCreated() == FROM_PARSER_XSLT &&
(!ReadyToExecuteParserBlockingScripts() || !mXSLTRequests.isEmpty())) {
// Need to maintain order for XSLT-inserted scripts
@@ -1728,7 +1479,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (aElement->GetParserCreated() == NOT_FROM_PARSER) {
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"A script-inserted script is inserted without an update batch?");
- nsContentUtils::AddScriptRunner(new nsScriptRequestProcessor(this,
+ nsContentUtils::AddScriptRunner(new ScriptRequestProcessor(this,
request));
return false;
}
@@ -1758,13 +1509,13 @@ namespace {
class NotifyOffThreadScriptLoadCompletedRunnable : public Runnable
{
- RefPtr<nsScriptLoadRequest> mRequest;
- RefPtr<nsScriptLoader> mLoader;
+ RefPtr<ScriptLoadRequest> mRequest;
+ RefPtr<ScriptLoader> mLoader;
void *mToken;
public:
- NotifyOffThreadScriptLoadCompletedRunnable(nsScriptLoadRequest* aRequest,
- nsScriptLoader* aLoader)
+ NotifyOffThreadScriptLoadCompletedRunnable(ScriptLoadRequest* aRequest,
+ ScriptLoader* aLoader)
: mRequest(aRequest), mLoader(aLoader), mToken(nullptr)
{}
@@ -1781,21 +1532,17 @@ public:
} /* anonymous namespace */
nsresult
-nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest)
+ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest)
{
- MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress::Compiling);
+ MOZ_ASSERT(aRequest->mProgress == ScriptLoadRequest::Progress::Compiling);
MOZ_ASSERT(!aRequest->mWasCompiledOMT);
aRequest->mWasCompiledOMT = true;
if (aRequest->IsModuleRequest()) {
MOZ_ASSERT(aRequest->mOffThreadToken);
- nsModuleLoadRequest* request = aRequest->AsModuleRequest();
- nsresult rv = ProcessFetchedModuleSource(request);
- if (NS_FAILED(rv)) {
- request->LoadFailed();
- }
- return rv;
+ ModuleLoadRequest* request = aRequest->AsModuleRequest();
+ return ProcessFetchedModuleSource(request);
}
aRequest->SetReady();
@@ -1837,8 +1584,8 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run()
// We want these to be dropped on the main thread, once we return from this
// function.
- RefPtr<nsScriptLoadRequest> request = mRequest.forget();
- RefPtr<nsScriptLoader> loader = mLoader.forget();
+ RefPtr<ScriptLoadRequest> request = mRequest.forget();
+ RefPtr<ScriptLoader> loader = mLoader.forget();
request->mOffThreadToken = mToken;
nsresult rv = loader->ProcessOffThreadRequest(request);
@@ -1856,7 +1603,7 @@ OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData)
}
nsresult
-nsScriptLoader::AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest)
+ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest)
{
MOZ_ASSERT_IF(!aRequest->IsModuleRequest(), aRequest->IsReadyToRun());
MOZ_ASSERT(!aRequest->mWasCompiledOMT);
@@ -1909,14 +1656,14 @@ nsScriptLoader::AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest)
}
mDocument->BlockOnload();
- aRequest->mProgress = nsScriptLoadRequest::Progress::Compiling;
+ aRequest->mProgress = ScriptLoadRequest::Progress::Compiling;
Unused << runnable.forget();
return NS_OK;
}
nsresult
-nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
+ScriptLoader::CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest)
{
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
"Processing requests when running scripts is unsafe.");
@@ -1934,7 +1681,7 @@ nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
}
SourceBufferHolder
-nsScriptLoader::GetScriptSource(nsScriptLoadRequest* aRequest, nsAutoString& inlineData)
+ScriptLoader::GetScriptSource(ScriptLoadRequest* aRequest, nsAutoString& inlineData)
{
// Return a SourceBufferHolder object holding the script's source text.
// |inlineData| is used to hold the text for inline objects.
@@ -1955,7 +1702,7 @@ nsScriptLoader::GetScriptSource(nsScriptLoadRequest* aRequest, nsAutoString& inl
}
nsresult
-nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
+ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest)
{
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
"Processing requests when running scripts is unsafe.");
@@ -1967,7 +1714,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
if (aRequest->IsModuleRequest() &&
!aRequest->AsModuleRequest()->mModuleScript)
{
- // There was an error parsing a module script. Nothing to do here.
+ // There was an error fetching a module script. Nothing to do here.
FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
return NS_OK;
}
@@ -2055,8 +1802,8 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
}
void
-nsScriptLoader::FireScriptAvailable(nsresult aResult,
- nsScriptLoadRequest* aRequest)
+ScriptLoader::FireScriptAvailable(nsresult aResult,
+ ScriptLoadRequest* aRequest)
{
for (int32_t i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
@@ -2069,8 +1816,8 @@ nsScriptLoader::FireScriptAvailable(nsresult aResult,
}
void
-nsScriptLoader::FireScriptEvaluated(nsresult aResult,
- nsScriptLoadRequest* aRequest)
+ScriptLoader::FireScriptEvaluated(nsresult aResult,
+ ScriptLoadRequest* aRequest)
{
for (int32_t i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
@@ -2082,7 +1829,7 @@ nsScriptLoader::FireScriptEvaluated(nsresult aResult,
}
already_AddRefed<nsIScriptGlobalObject>
-nsScriptLoader::GetScriptGlobalObject()
+ScriptLoader::GetScriptGlobalObject()
{
nsCOMPtr<nsIDocument> master = mDocument->MasterDocument();
nsPIDOMWindowInner *pwin = master->GetInnerWindow();
@@ -2103,10 +1850,10 @@ nsScriptLoader::GetScriptGlobalObject()
}
nsresult
-nsScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
- nsScriptLoadRequest* aRequest,
- JS::Handle<JSObject*> aScopeChain,
- JS::CompileOptions* aOptions)
+ScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
+ ScriptLoadRequest* aRequest,
+ JS::Handle<JSObject*> aScopeChain,
+ JS::CompileOptions* aOptions)
{
// It's very important to use aRequest->mURI, not the final URI of the channel
// aRequest ended up getting script data from, as the script filename.
@@ -2150,7 +1897,7 @@ nsScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
}
nsresult
-nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest)
+ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
{
// We need a document to evaluate scripts.
if (!mDocument) {
@@ -2189,8 +1936,8 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest)
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
nsAutoMicroTask mt;
AutoEntryScript aes(globalObject, "<script> element", true);
- JS::Rooted<JSObject*> global(aes.cx(),
- globalObject->GetGlobalJSObject());
+ JSContext* cx = aes.cx();
+ JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
bool oldProcessingScriptTag = context->GetProcessingScriptTag();
context->SetProcessingScriptTag(true);
@@ -2211,28 +1958,38 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest)
}
if (aRequest->IsModuleRequest()) {
- nsModuleLoadRequest* request = aRequest->AsModuleRequest();
+ rv = EnsureModuleResolveHook(cx);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ModuleLoadRequest* request = aRequest->AsModuleRequest();
MOZ_ASSERT(request->mModuleScript);
MOZ_ASSERT(!request->mOffThreadToken);
- nsModuleScript* ms = request->mModuleScript;
- MOZ_ASSERT(!ms->IsUninstantiated());
- if (ms->InstantiationFailed()) {
- JS::Rooted<JS::Value> exception(aes.cx(), ms->Exception());
- JS_SetPendingException(aes.cx(), exception);
- rv = NS_ERROR_FAILURE;
- } else {
- JS::Rooted<JSObject*> module(aes.cx(), ms->ModuleRecord());
- MOZ_ASSERT(module);
- rv = nsJSUtils::ModuleEvaluation(aes.cx(), module);
+
+ ModuleScript* moduleScript = request->mModuleScript;
+ if (moduleScript->IsErrored()) {
+ // Module has an error status
+ JS::Rooted<JS::Value> error(cx, moduleScript->Error());
+ JS_SetPendingException(cx, error);
+ return NS_OK; // An error is reported by AutoEntryScript.
+ }
+
+ JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
+ MOZ_ASSERT(module);
+
+ rv = nsJSUtils::ModuleEvaluate(cx, module);
+ MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());
+ if (NS_FAILED(rv)) {
+ // Evaluation failed
+ rv = NS_OK; // An error is reported by AutoEntryScript.
}
} else {
- JS::CompileOptions options(aes.cx());
+ JS::CompileOptions options(cx);
rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
if (NS_SUCCEEDED(rv)) {
nsAutoString inlineData;
SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
- rv = nsJSUtils::EvaluateString(aes.cx(), srcBuf, global, options,
+ rv = nsJSUtils::EvaluateString(cx, srcBuf, global, options,
aRequest->OffThreadTokenPtr());
}
}
@@ -2243,7 +2000,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest)
}
void
-nsScriptLoader::ProcessPendingRequestsAsync()
+ScriptLoader::ProcessPendingRequestsAsync()
{
if (mParserBlockingRequest ||
!mXSLTRequests.isEmpty() ||
@@ -2252,14 +2009,14 @@ nsScriptLoader::ProcessPendingRequestsAsync()
!mDeferRequests.isEmpty() ||
!mPendingChildLoaders.IsEmpty()) {
NS_DispatchToCurrentThread(NewRunnableMethod(this,
- &nsScriptLoader::ProcessPendingRequests));
+ &ScriptLoader::ProcessPendingRequests));
}
}
void
-nsScriptLoader::ProcessPendingRequests()
+ScriptLoader::ProcessPendingRequests()
{
- RefPtr<nsScriptLoadRequest> request;
+ RefPtr<ScriptLoadRequest> request;
if (mParserBlockingRequest &&
mParserBlockingRequest->IsReadyToRun() &&
@@ -2311,7 +2068,7 @@ nsScriptLoader::ProcessPendingRequests()
while (!mPendingChildLoaders.IsEmpty() &&
ReadyToExecuteParserBlockingScripts()) {
- RefPtr<nsScriptLoader> child = mPendingChildLoaders[0];
+ RefPtr<ScriptLoader> child = mPendingChildLoaders[0];
mPendingChildLoaders.RemoveElementAt(0);
child->RemoveParserBlockingScriptExecutionBlocker();
}
@@ -2337,7 +2094,7 @@ nsScriptLoader::ProcessPendingRequests()
}
bool
-nsScriptLoader::ReadyToExecuteParserBlockingScripts()
+ScriptLoader::ReadyToExecuteParserBlockingScripts()
{
// Make sure the SelfReadyToExecuteParserBlockingScripts check is first, so
// that we don't block twice on an ancestor.
@@ -2346,7 +2103,7 @@ nsScriptLoader::ReadyToExecuteParserBlockingScripts()
}
for (nsIDocument* doc = mDocument; doc; doc = doc->GetParentDocument()) {
- nsScriptLoader* ancestor = doc->ScriptLoader();
+ ScriptLoader* ancestor = doc->ScriptLoader();
if (!ancestor->SelfReadyToExecuteParserBlockingScripts() &&
ancestor->AddPendingChildLoader(this)) {
AddParserBlockingScriptExecutionBlocker();
@@ -2394,10 +2151,10 @@ nsScriptLoader::ReadyToExecuteParserBlockingScripts()
}
/* static */ nsresult
-nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
- uint32_t aLength, const nsAString& aHintCharset,
- nsIDocument* aDocument,
- char16_t*& aBufOut, size_t& aLengthOut)
+ScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
+ uint32_t aLength, const nsAString& aHintCharset,
+ nsIDocument* aDocument,
+ char16_t*& aBufOut, size_t& aLengthOut)
{
if (!aLength) {
aBufOut = nullptr;
@@ -2474,14 +2231,14 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
}
nsresult
-nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
- nsISupports* aContext,
- nsresult aChannelStatus,
- nsresult aSRIStatus,
- mozilla::Vector<char16_t> &aString,
- mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier)
-{
- nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
+ScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
+ nsISupports* aContext,
+ nsresult aChannelStatus,
+ nsresult aSRIStatus,
+ mozilla::Vector<char16_t> &aString,
+ mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier)
+{
+ ScriptLoadRequest* request = static_cast<ScriptLoadRequest*>(aContext);
NS_ASSERTION(request, "null request in stream complete handler");
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
@@ -2511,7 +2268,7 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
if (loadInfo->GetEnforceSRI()) {
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
- ("nsScriptLoader::OnStreamComplete, required SRI not found"));
+ ("ScriptLoader::OnStreamComplete, required SRI not found"));
nsCOMPtr<nsIContentSecurityPolicy> csp;
loadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(csp));
nsAutoCString violationURISpec;
@@ -2544,29 +2301,29 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
MOZ_ASSERT_IF(request->IsModuleRequest(),
request->AsModuleRequest()->IsTopLevel());
if (request->isInList()) {
- RefPtr<nsScriptLoadRequest> req = mDeferRequests.Steal(request);
+ RefPtr<ScriptLoadRequest> req = mDeferRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsAsync) {
MOZ_ASSERT_IF(request->IsModuleRequest(),
request->AsModuleRequest()->IsTopLevel());
if (request->isInList()) {
- RefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(request);
+ RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsNonAsyncScriptInserted) {
if (request->isInList()) {
- RefPtr<nsScriptLoadRequest> req =
+ RefPtr<ScriptLoadRequest> req =
mNonAsyncExternalScriptInsertedRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsXSLT) {
if (request->isInList()) {
- RefPtr<nsScriptLoadRequest> req = mXSLTRequests.Steal(request);
+ RefPtr<ScriptLoadRequest> req = mXSLTRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->IsModuleRequest()) {
- nsModuleLoadRequest* modReq = request->AsModuleRequest();
+ ModuleLoadRequest* modReq = request->AsModuleRequest();
MOZ_ASSERT(!modReq->IsTopLevel());
MOZ_ASSERT(!modReq->isInList());
modReq->Cancel();
@@ -2597,19 +2354,19 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
}
void
-nsScriptLoader::UnblockParser(nsScriptLoadRequest* aParserBlockingRequest)
+ScriptLoader::UnblockParser(ScriptLoadRequest* aParserBlockingRequest)
{
aParserBlockingRequest->mElement->UnblockParser();
}
void
-nsScriptLoader::ContinueParserAsync(nsScriptLoadRequest* aParserBlockingRequest)
+ScriptLoader::ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest)
{
aParserBlockingRequest->mElement->ContinueParserAsync();
}
uint32_t
-nsScriptLoader::NumberOfProcessors()
+ScriptLoader::NumberOfProcessors()
{
if (mNumberOfProcessors > 0)
return mNumberOfProcessors;
@@ -2621,7 +2378,7 @@ nsScriptLoader::NumberOfProcessors()
}
void
-nsScriptLoader::MaybeMoveToLoadedList(nsScriptLoadRequest* aRequest)
+ScriptLoader::MaybeMoveToLoadedList(ScriptLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->IsReadyToRun());
@@ -2631,17 +2388,17 @@ nsScriptLoader::MaybeMoveToLoadedList(nsScriptLoadRequest* aRequest)
if (aRequest->mIsAsync) {
MOZ_ASSERT(aRequest->isInList());
if (aRequest->isInList()) {
- RefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
+ RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
mLoadedAsyncRequests.AppendElement(req);
}
}
}
nsresult
-nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
- nsIIncrementalStreamLoader* aLoader,
- nsresult aStatus,
- mozilla::Vector<char16_t> &aString)
+ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
+ nsIIncrementalStreamLoader* aLoader,
+ nsresult aStatus,
+ mozilla::Vector<char16_t> &aString)
{
if (NS_FAILED(aStatus)) {
return aStatus;
@@ -2713,7 +2470,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
"aRequest should be pending!");
if (aRequest->IsModuleRequest()) {
- nsModuleLoadRequest* request = aRequest->AsModuleRequest();
+ ModuleLoadRequest* request = aRequest->AsModuleRequest();
// When loading a module, only responses with a JavaScript MIME type are
// acceptable.
@@ -2744,7 +2501,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
MOZ_ASSERT(!aRequest->IsModuleRequest());
nsresult rv = AttemptAsyncScriptCompile(aRequest);
if (rv == NS_OK) {
- MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress::Compiling,
+ MOZ_ASSERT(aRequest->mProgress == ScriptLoadRequest::Progress::Compiling,
"Request should be off-thread compiling now.");
return NS_OK;
}
@@ -2763,7 +2520,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
}
void
-nsScriptLoader::ParsingComplete(bool aTerminated)
+ScriptLoader::ParsingComplete(bool aTerminated)
{
if (mDeferEnabled) {
// Have to check because we apparently get ParsingComplete
@@ -2789,12 +2546,12 @@ nsScriptLoader::ParsingComplete(bool aTerminated)
}
void
-nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
- const nsAString &aType,
- const nsAString &aCrossOrigin,
- const nsAString& aIntegrity,
- bool aScriptFromHead,
- const mozilla::net::ReferrerPolicy aReferrerPolicy)
+ScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
+ const nsAString &aType,
+ const nsAString &aCrossOrigin,
+ const nsAString& aIntegrity,
+ bool aScriptFromHead,
+ const mozilla::net::ReferrerPolicy aReferrerPolicy)
{
NS_ENSURE_TRUE_VOID(mDocument);
// Check to see if scripts has been turned off.
@@ -2810,7 +2567,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
SRIMetadata sriMetadata;
if (!aIntegrity.IsEmpty()) {
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
- ("nsScriptLoader::PreloadURI, integrity=%s",
+ ("ScriptLoader::PreloadURI, integrity=%s",
NS_ConvertUTF16toUTF8(aIntegrity).get()));
nsAutoCString sourceUri;
if (mDocument->GetDocumentURI()) {
@@ -2819,8 +2576,8 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
}
- RefPtr<nsScriptLoadRequest> request =
- CreateLoadRequest(nsScriptKind::Classic, nullptr, 0,
+ RefPtr<ScriptLoadRequest> request =
+ CreateLoadRequest(ScriptKind::Classic, nullptr, 0,
Element::StringToCORSMode(aCrossOrigin), sriMetadata);
request->mURI = aURI;
request->mIsInline = false;
@@ -2837,7 +2594,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
}
void
-nsScriptLoader::AddDeferRequest(nsScriptLoadRequest* aRequest)
+ScriptLoader::AddDeferRequest(ScriptLoadRequest* aRequest)
{
aRequest->mIsDefer = true;
mDeferRequests.AppendElement(aRequest);
@@ -2850,7 +2607,7 @@ nsScriptLoader::AddDeferRequest(nsScriptLoadRequest* aRequest)
}
bool
-nsScriptLoader::MaybeRemovedDeferRequests()
+ScriptLoader::MaybeRemovedDeferRequests()
{
if (mDeferRequests.isEmpty() && mDocument &&
mBlockingDOMContentLoaded) {
@@ -2861,201 +2618,5 @@ nsScriptLoader::MaybeRemovedDeferRequests()
return false;
}
-//////////////////////////////////////////////////////////////
-// nsScriptLoadHandler
-//////////////////////////////////////////////////////////////
-
-nsScriptLoadHandler::nsScriptLoadHandler(nsScriptLoader *aScriptLoader,
- nsScriptLoadRequest *aRequest,
- mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier)
- : mScriptLoader(aScriptLoader),
- mRequest(aRequest),
- mSRIDataVerifier(aSRIDataVerifier),
- mSRIStatus(NS_OK),
- mDecoder(),
- mBuffer()
-{}
-
-nsScriptLoadHandler::~nsScriptLoadHandler()
-{}
-
-NS_IMPL_ISUPPORTS(nsScriptLoadHandler, nsIIncrementalStreamLoaderObserver)
-
-NS_IMETHODIMP
-nsScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
- nsISupports* aContext,
- uint32_t aDataLength,
- const uint8_t* aData,
- uint32_t *aConsumedLength)
-{
- if (mRequest->IsCanceled()) {
- // If request cancelled, ignore any incoming data.
- *aConsumedLength = aDataLength;
- return NS_OK;
- }
-
- if (!EnsureDecoder(aLoader, aData, aDataLength,
- /* aEndOfStream = */ false)) {
- return NS_OK;
- }
-
- // Below we will/shall consume entire data chunk.
- *aConsumedLength = aDataLength;
-
- // Decoder has already been initialized. -- trying to decode all loaded bytes.
- nsresult rv = TryDecodeRawData(aData, aDataLength,
- /* aEndOfStream = */ false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If SRI is required for this load, appending new bytes to the hash.
- if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
- mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
- }
-
- return rv;
-}
-
-nsresult
-nsScriptLoadHandler::TryDecodeRawData(const uint8_t* aData,
- uint32_t aDataLength,
- bool aEndOfStream)
-{
- int32_t srcLen = aDataLength;
- const char* src = reinterpret_cast<const char *>(aData);
- int32_t dstLen;
- nsresult rv =
- mDecoder->GetMaxLength(src, srcLen, &dstLen);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t haveRead = mBuffer.length();
-
- CheckedInt<uint32_t> capacity = haveRead;
- capacity += dstLen;
-
- if (!capacity.isValid() || !mBuffer.reserve(capacity.value())) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- rv = mDecoder->Convert(src,
- &srcLen,
- mBuffer.begin() + haveRead,
- &dstLen);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- haveRead += dstLen;
- MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
- MOZ_ALWAYS_TRUE(mBuffer.resizeUninitialized(haveRead));
-
- return NS_OK;
-}
-
-bool
-nsScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
- const uint8_t* aData,
- uint32_t aDataLength,
- bool aEndOfStream)
-{
- // Check if decoder has already been created.
- if (mDecoder) {
- return true;
- }
-
- nsAutoCString charset;
-
- // JavaScript modules are always UTF-8.
- if (mRequest->IsModuleRequest()) {
- charset = "UTF-8";
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
- }
-
- // Determine if BOM check should be done. This occurs either
- // if end-of-stream has been reached, or at least 3 bytes have
- // been read from input.
- if (!aEndOfStream && (aDataLength < 3)) {
- return false;
- }
-
- // Do BOM detection.
- if (nsContentUtils::CheckForBOM(aData, aDataLength, charset)) {
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
- }
-
- // BOM detection failed, check content stream for charset.
- nsCOMPtr<nsIRequest> req;
- nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
- NS_ASSERTION(req, "StreamLoader's request went away prematurely");
- NS_ENSURE_SUCCESS(rv, false);
-
- nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
-
- if (channel &&
- NS_SUCCEEDED(channel->GetContentCharset(charset)) &&
- EncodingUtils::FindEncodingForLabel(charset, charset)) {
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
- }
-
- // Check the hint charset from the script element or preload
- // request.
- nsAutoString hintCharset;
- if (!mRequest->IsPreload()) {
- mRequest->mElement->GetScriptCharset(hintCharset);
- } else {
- nsTArray<nsScriptLoader::PreloadInfo>::index_type i =
- mScriptLoader->mPreloads.IndexOf(mRequest, 0,
- nsScriptLoader::PreloadRequestComparator());
-
- NS_ASSERTION(i != mScriptLoader->mPreloads.NoIndex,
- "Incorrect preload bookkeeping");
- hintCharset = mScriptLoader->mPreloads[i].mCharset;
- }
-
- if (EncodingUtils::FindEncodingForLabel(hintCharset, charset)) {
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
- }
-
- // Get the charset from the charset of the document.
- if (mScriptLoader->mDocument) {
- charset = mScriptLoader->mDocument->GetDocumentCharacterSet();
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
- }
-
- // Curiously, there are various callers that don't pass aDocument. The
- // fallback in the old code was ISO-8859-1, which behaved like
- // windows-1252. Saying windows-1252 for clarity and for compliance
- // with the Encoding Standard.
- charset = "windows-1252";
- mDecoder = EncodingUtils::DecoderForEncoding(charset);
- return true;
-}
-
-NS_IMETHODIMP
-nsScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
- nsISupports* aContext,
- nsresult aStatus,
- uint32_t aDataLength,
- const uint8_t* aData)
-{
- if (!mRequest->IsCanceled()) {
- DebugOnly<bool> encoderSet =
- EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
- MOZ_ASSERT(encoderSet);
- DebugOnly<nsresult> rv = TryDecodeRawData(aData, aDataLength,
- /* aEndOfStream = */ true);
-
- // If SRI is required for this load, appending new bytes to the hash.
- if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
- mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
- }
- }
-
- // we have to mediate and use mRequest.
- return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus,
- mBuffer, mSRIDataVerifier);
-}
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/base/nsScriptLoader.h b/dom/script/ScriptLoader.h
index a00239be5f..e6b75bf3bb 100644
--- a/dom/base/nsScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -4,12 +4,8 @@
* 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/. */
-/*
- * A class that handles loading and evaluation of <script> elements.
- */
-
-#ifndef __nsScriptLoader_h__
-#define __nsScriptLoader_h__
+#ifndef mozilla_dom_ScriptLoader_h
+#define mozilla_dom_ScriptLoader_h
#include "nsCOMPtr.h"
#include "nsRefPtrHashtable.h"
@@ -25,14 +21,10 @@
#include "mozilla/CORSMode.h"
#include "mozilla/dom/SRIMetadata.h"
#include "mozilla/dom/SRICheck.h"
-#include "mozilla/LinkedList.h"
#include "mozilla/MozPromise.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/Vector.h"
-class nsModuleLoadRequest;
-class nsModuleScript;
-class nsScriptLoadRequestList;
class nsIURI;
namespace JS {
@@ -41,37 +33,39 @@ namespace JS {
namespace mozilla {
namespace dom {
+
class AutoJSAPI;
-} // namespace dom
-} // namespace mozilla
+class ModuleLoadRequest;
+class ModuleScript;
+class ScriptLoadRequestList;
//////////////////////////////////////////////////////////////
// Per-request data structure
//////////////////////////////////////////////////////////////
-enum class nsScriptKind {
+enum class ScriptKind {
Classic,
Module
};
-class nsScriptLoadRequest : public nsISupports,
- private mozilla::LinkedListElement<nsScriptLoadRequest>
+class ScriptLoadRequest : public nsISupports,
+ private mozilla::LinkedListElement<ScriptLoadRequest>
{
- typedef LinkedListElement<nsScriptLoadRequest> super;
+ typedef LinkedListElement<ScriptLoadRequest> super;
- // Allow LinkedListElement<nsScriptLoadRequest> to cast us to itself as needed.
- friend class mozilla::LinkedListElement<nsScriptLoadRequest>;
- friend class nsScriptLoadRequestList;
+ // Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
+ friend class mozilla::LinkedListElement<ScriptLoadRequest>;
+ friend class ScriptLoadRequestList;
protected:
- virtual ~nsScriptLoadRequest();
+ virtual ~ScriptLoadRequest();
public:
- nsScriptLoadRequest(nsScriptKind aKind,
- nsIScriptElement* aElement,
- uint32_t aVersion,
- mozilla::CORSMode aCORSMode,
- const mozilla::dom::SRIMetadata &aIntegrity)
+ ScriptLoadRequest(ScriptKind aKind,
+ nsIScriptElement* aElement,
+ uint32_t aVersion,
+ mozilla::CORSMode aCORSMode,
+ const mozilla::dom::SRIMetadata &aIntegrity)
: mKind(aKind),
mElement(aElement),
mProgress(Progress::Loading),
@@ -95,14 +89,14 @@ public:
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptLoadRequest)
+ NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest)
bool IsModuleRequest() const
{
- return mKind == nsScriptKind::Module;
+ return mKind == ScriptKind::Module;
}
- nsModuleLoadRequest* AsModuleRequest();
+ ModuleLoadRequest* AsModuleRequest();
void FireScriptAvailable(nsresult aResult)
{
@@ -154,7 +148,7 @@ public:
using super::getNext;
using super::isInList;
- const nsScriptKind mKind;
+ const ScriptKind mKind;
nsCOMPtr<nsIScriptElement> mElement;
Progress mProgress; // Are we still waiting for a load to complete?
bool mIsInline; // Is the script inline or loaded?
@@ -179,23 +173,23 @@ public:
mozilla::net::ReferrerPolicy mReferrerPolicy;
};
-class nsScriptLoadRequestList : private mozilla::LinkedList<nsScriptLoadRequest>
+class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
{
- typedef mozilla::LinkedList<nsScriptLoadRequest> super;
+ typedef mozilla::LinkedList<ScriptLoadRequest> super;
public:
- ~nsScriptLoadRequestList();
+ ~ScriptLoadRequestList();
void Clear();
#ifdef DEBUG
- bool Contains(nsScriptLoadRequest* aElem) const;
+ bool Contains(ScriptLoadRequest* aElem) const;
#endif // DEBUG
using super::getFirst;
using super::isEmpty;
- void AppendElement(nsScriptLoadRequest* aElem)
+ void AppendElement(ScriptLoadRequest* aElem)
{
MOZ_ASSERT(!aElem->isInList());
NS_ADDREF(aElem);
@@ -203,36 +197,37 @@ public:
}
MOZ_MUST_USE
- already_AddRefed<nsScriptLoadRequest> Steal(nsScriptLoadRequest* aElem)
+ already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem)
{
aElem->removeFrom(*this);
return dont_AddRef(aElem);
}
MOZ_MUST_USE
- already_AddRefed<nsScriptLoadRequest> StealFirst()
+ already_AddRefed<ScriptLoadRequest> StealFirst()
{
MOZ_ASSERT(!isEmpty());
return Steal(getFirst());
}
- void Remove(nsScriptLoadRequest* aElem)
+ void Remove(ScriptLoadRequest* aElem)
{
aElem->removeFrom(*this);
NS_RELEASE(aElem);
}
};
+class ScriptLoadHandler;
//////////////////////////////////////////////////////////////
// Script loader implementation
//////////////////////////////////////////////////////////////
-class nsScriptLoader final : public nsISupports
+class ScriptLoader final : public nsISupports
{
class MOZ_STACK_CLASS AutoCurrentScriptUpdater
{
public:
- AutoCurrentScriptUpdater(nsScriptLoader* aScriptLoader,
+ AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
nsIScriptElement* aCurrentScript)
: mOldScript(aScriptLoader->mCurrentScript)
, mScriptLoader(aScriptLoader)
@@ -245,19 +240,19 @@ class nsScriptLoader final : public nsISupports
}
private:
nsCOMPtr<nsIScriptElement> mOldScript;
- nsScriptLoader* mScriptLoader;
+ ScriptLoader* mScriptLoader;
};
- friend class nsModuleLoadRequest;
- friend class nsScriptRequestProcessor;
- friend class nsScriptLoadHandler;
+ friend class ModuleLoadRequest;
+ friend class ScriptRequestProcessor;
+ friend class ScriptLoadHandler;
friend class AutoCurrentScriptUpdater;
public:
- explicit nsScriptLoader(nsIDocument* aDocument);
+ explicit ScriptLoader(nsIDocument* aDocument);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptLoader)
+ NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
/**
* The loader maintains a weak reference to the document with
@@ -395,7 +390,7 @@ public:
/**
* Handle the completion of a stream. This is called by the
- * nsScriptLoadHandler object which observes the IncrementalStreamLoader
+ * ScriptLoadHandler object which observes the IncrementalStreamLoader
* loading the script.
*/
nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
@@ -463,17 +458,17 @@ public:
* Process a request that was deferred so that the script could be compiled
* off thread.
*/
- nsresult ProcessOffThreadRequest(nsScriptLoadRequest *aRequest);
+ nsresult ProcessOffThreadRequest(ScriptLoadRequest *aRequest);
- bool AddPendingChildLoader(nsScriptLoader* aChild) {
+ bool AddPendingChildLoader(ScriptLoader* aChild) {
return mPendingChildLoaders.AppendElement(aChild) != nullptr;
}
private:
- virtual ~nsScriptLoader();
+ virtual ~ScriptLoader();
- nsScriptLoadRequest* CreateLoadRequest(
- nsScriptKind aKind,
+ ScriptLoadRequest* CreateLoadRequest(
+ ScriptKind aKind,
nsIScriptElement* aElement,
uint32_t aVersion,
mozilla::CORSMode aCORSMode,
@@ -482,12 +477,12 @@ private:
/**
* Unblocks the creator parser of the parser-blocking scripts.
*/
- void UnblockParser(nsScriptLoadRequest* aParserBlockingRequest);
+ void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
/**
* Asynchronously resumes the creator parser of the parser-blocking scripts.
*/
- void ContinueParserAsync(nsScriptLoadRequest* aParserBlockingRequest);
+ void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
/**
@@ -502,7 +497,7 @@ private:
/**
* Start a load for aRequest's URI.
*/
- nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
+ nsresult StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
bool aScriptFromHead);
/**
@@ -539,83 +534,84 @@ private:
return mEnabled && !mBlockerCount;
}
- nsresult AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest);
- nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
- nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest);
+ nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
+ nsresult ProcessRequest(ScriptLoadRequest* aRequest);
+ nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
void FireScriptAvailable(nsresult aResult,
- nsScriptLoadRequest* aRequest);
+ ScriptLoadRequest* aRequest);
void FireScriptEvaluated(nsresult aResult,
- nsScriptLoadRequest* aRequest);
- nsresult EvaluateScript(nsScriptLoadRequest* aRequest);
+ ScriptLoadRequest* aRequest);
+ nsresult EvaluateScript(ScriptLoadRequest* aRequest);
already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
nsresult FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI& jsapi,
- nsScriptLoadRequest* aRequest,
+ ScriptLoadRequest* aRequest,
JS::Handle<JSObject*> aScopeChain,
JS::CompileOptions* aOptions);
uint32_t NumberOfProcessors();
- nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
+ nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
nsIIncrementalStreamLoader* aLoader,
nsresult aStatus,
mozilla::Vector<char16_t> &aString);
- void AddDeferRequest(nsScriptLoadRequest* aRequest);
+ void AddDeferRequest(ScriptLoadRequest* aRequest);
bool MaybeRemovedDeferRequests();
- void MaybeMoveToLoadedList(nsScriptLoadRequest* aRequest);
+ void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
- JS::SourceBufferHolder GetScriptSource(nsScriptLoadRequest* aRequest,
+ JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
nsAutoString& inlineData);
bool ModuleScriptsEnabled();
- void SetModuleFetchStarted(nsModuleLoadRequest *aRequest);
- void SetModuleFetchFinishedAndResumeWaitingRequests(nsModuleLoadRequest *aRequest,
+ void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
+ void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
nsresult aResult);
- bool IsFetchingModule(nsModuleLoadRequest *aRequest) const;
+ bool IsFetchingModule(ModuleLoadRequest *aRequest) const;
- bool ModuleMapContainsModule(nsModuleLoadRequest *aRequest) const;
- RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsModuleLoadRequest *aRequest);
- nsModuleScript* GetFetchedModule(nsIURI* aURL) const;
+ bool ModuleMapContainsModule(ModuleLoadRequest *aRequest) const;
+ RefPtr<mozilla::GenericPromise> WaitForModuleFetch(ModuleLoadRequest *aRequest);
+ ModuleScript* GetFetchedModule(nsIURI* aURL) const;
friend bool
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp);
- nsresult CreateModuleScript(nsModuleLoadRequest* aRequest);
- nsresult ProcessFetchedModuleSource(nsModuleLoadRequest* aRequest);
- void ProcessLoadedModuleTree(nsModuleLoadRequest* aRequest);
- bool InstantiateModuleTree(nsModuleLoadRequest* aRequest);
- void StartFetchingModuleDependencies(nsModuleLoadRequest* aRequest);
+ nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
+ nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
+ void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
+ void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
+ bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
+ void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
RefPtr<mozilla::GenericPromise>
- StartFetchingModuleAndDependencies(nsModuleLoadRequest* aRequest, nsIURI* aURI);
+ StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest, nsIURI* aURI);
nsIDocument* mDocument; // [WEAK]
nsCOMArray<nsIScriptLoaderObserver> mObservers;
- nsScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
+ ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
// mLoadingAsyncRequests holds async requests while they're loading; when they
// have been loaded they are moved to mLoadedAsyncRequests.
- nsScriptLoadRequestList mLoadingAsyncRequests;
- nsScriptLoadRequestList mLoadedAsyncRequests;
- nsScriptLoadRequestList mDeferRequests;
- nsScriptLoadRequestList mXSLTRequests;
- RefPtr<nsScriptLoadRequest> mParserBlockingRequest;
+ ScriptLoadRequestList mLoadingAsyncRequests;
+ ScriptLoadRequestList mLoadedAsyncRequests;
+ ScriptLoadRequestList mDeferRequests;
+ ScriptLoadRequestList mXSLTRequests;
+ RefPtr<ScriptLoadRequest> mParserBlockingRequest;
// In mRequests, the additional information here is stored by the element.
struct PreloadInfo {
- RefPtr<nsScriptLoadRequest> mRequest;
+ RefPtr<ScriptLoadRequest> mRequest;
nsString mCharset;
};
- friend void ImplCycleCollectionUnlink(nsScriptLoader::PreloadInfo& aField);
+ friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- nsScriptLoader::PreloadInfo& aField,
+ ScriptLoader::PreloadInfo& aField,
const char* aName, uint32_t aFlags);
struct PreloadRequestComparator {
- bool Equals(const PreloadInfo &aPi, nsScriptLoadRequest * const &aRequest)
+ bool Equals(const PreloadInfo &aPi, ScriptLoadRequest * const &aRequest)
const
{
return aRequest == aPi.mRequest;
@@ -628,7 +624,7 @@ private:
nsCOMPtr<nsIScriptElement> mCurrentScript;
nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
- nsTArray< RefPtr<nsScriptLoader> > mPendingChildLoaders;
+ nsTArray< RefPtr<ScriptLoader> > mPendingChildLoaders;
uint32_t mParserBlockingBlockerCount;
uint32_t mBlockerCount;
uint32_t mNumberOfProcessors;
@@ -639,58 +635,11 @@ private:
// Module map
nsRefPtrHashtable<nsURIHashKey, mozilla::GenericPromise::Private> mFetchingModules;
- nsRefPtrHashtable<nsURIHashKey, nsModuleScript> mFetchedModules;
+ nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
nsCOMPtr<nsIConsoleReportCollector> mReporter;
};
-class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
-{
-public:
- explicit nsScriptLoadHandler(nsScriptLoader* aScriptLoader,
- nsScriptLoadRequest *aRequest,
- mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
-
-private:
- virtual ~nsScriptLoadHandler();
-
- /*
- * Try to decode some raw data.
- */
- nsresult TryDecodeRawData(const uint8_t* aData, uint32_t aDataLength,
- bool aEndOfStream);
-
- /*
- * Discover the charset by looking at the stream data, the script
- * tag, and other indicators. Returns true if charset has been
- * discovered.
- */
- bool EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
- const uint8_t* aData, uint32_t aDataLength,
- bool aEndOfStream);
-
- // ScriptLoader which will handle the parsed script.
- RefPtr<nsScriptLoader> mScriptLoader;
-
- // The nsScriptLoadRequest for this load.
- RefPtr<nsScriptLoadRequest> mRequest;
-
- // SRI data verifier.
- nsAutoPtr<mozilla::dom::SRICheckDataVerifier> mSRIDataVerifier;
-
- // Status of SRI data operations.
- nsresult mSRIStatus;
-
- // Unicode decoder for charset.
- nsCOMPtr<nsIUnicodeDecoder> mDecoder;
-
- // Accumulated decoded char buffer.
- mozilla::Vector<char16_t> mBuffer;
-};
-
class nsAutoScriptLoaderDisabler
{
public:
@@ -711,7 +660,10 @@ public:
}
bool mWasEnabled;
- RefPtr<nsScriptLoader> mLoader;
+ RefPtr<ScriptLoader> mLoader;
};
-#endif //__nsScriptLoader_h__
+} // namespace dom
+} // namespace mozilla
+
+#endif //mozilla_dom_ScriptLoader_h
diff --git a/dom/base/ScriptSettings.cpp b/dom/script/ScriptSettings.cpp
index d67f2167ae..92ab221c95 100644
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/script/ScriptSettings.cpp
@@ -485,7 +485,13 @@ AutoJSAPI::Init(nsIGlobalObject* aGlobalObject)
bool
AutoJSAPI::Init(JSObject* aObject)
{
- return Init(xpc::NativeGlobal(aObject));
+ nsIGlobalObject* global = nullptr;
+ if (aObject)
+ global = xpc::NativeGlobal(aObject);
+ if (global)
+ return Init(global);
+ else
+ return false;
}
bool
diff --git a/dom/base/ScriptSettings.h b/dom/script/ScriptSettings.h
index 05e62f55e2..05e62f55e2 100644
--- a/dom/base/ScriptSettings.h
+++ b/dom/script/ScriptSettings.h
diff --git a/dom/script/moz.build b/dom/script/moz.build
new file mode 100644
index 0000000000..280850ed4a
--- /dev/null
+++ b/dom/script/moz.build
@@ -0,0 +1,36 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# 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/.
+
+XPIDL_SOURCES += [
+ 'nsIScriptLoaderObserver.idl',
+]
+
+XPIDL_MODULE = 'dom'
+
+EXPORTS += ['nsIScriptElement.h']
+
+EXPORTS.mozilla.dom += [
+ 'ScriptElement.h',
+ 'ScriptLoader.h',
+ 'ScriptSettings.h',
+]
+
+SOURCES += [
+ 'ModuleLoadRequest.cpp',
+ 'ModuleScript.cpp',
+ 'ScriptElement.cpp',
+ 'ScriptLoader.cpp',
+ 'ScriptLoadHandler.cpp',
+ 'ScriptSettings.cpp',
+]
+
+LOCAL_INCLUDES += [
+ '/dom/base',
+ '/dom/workers',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
diff --git a/dom/base/nsIScriptElement.h b/dom/script/nsIScriptElement.h
index 470d51c948..470d51c948 100644
--- a/dom/base/nsIScriptElement.h
+++ b/dom/script/nsIScriptElement.h
diff --git a/dom/base/nsIScriptLoaderObserver.idl b/dom/script/nsIScriptLoaderObserver.idl
index ed71965255..ed71965255 100644
--- a/dom/base/nsIScriptLoaderObserver.idl
+++ b/dom/script/nsIScriptLoaderObserver.idl
diff --git a/dom/svg/SVGScriptElement.cpp b/dom/svg/SVGScriptElement.cpp
index ffc049c212..f2fb3ff5c8 100644
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -42,7 +42,7 @@ NS_IMPL_ISUPPORTS_INHERITED(SVGScriptElement, SVGScriptElementBase,
SVGScriptElement::SVGScriptElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: SVGScriptElementBase(aNodeInfo)
- , nsScriptElement(aFromParser)
+ , ScriptElement(aFromParser)
{
AddMutationObserver(this);
}
@@ -168,7 +168,7 @@ SVGScriptElement::FreezeUriAsyncDefer()
}
//----------------------------------------------------------------------
-// nsScriptElement methods
+// ScriptElement methods
bool
SVGScriptElement::HasScriptContent()
diff --git a/dom/svg/SVGScriptElement.h b/dom/svg/SVGScriptElement.h
index 620a1bcde0..9f098e0479 100644
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -10,7 +10,7 @@
#include "nsSVGElement.h"
#include "nsCOMPtr.h"
#include "nsSVGString.h"
-#include "nsScriptElement.h"
+#include "mozilla/dom/ScriptElement.h"
class nsIDocument;
@@ -24,7 +24,7 @@ namespace dom {
typedef nsSVGElement SVGScriptElementBase;
class SVGScriptElement final : public SVGScriptElementBase,
- public nsScriptElement
+ public ScriptElement
{
protected:
friend nsresult (::NS_NewSVGScriptElement(nsIContent **aResult,
@@ -47,7 +47,7 @@ public:
virtual void FreezeUriAsyncDefer() override;
virtual CORSMode GetCORSMode() const override;
- // nsScriptElement
+ // ScriptElement
virtual bool HasScriptContent() override;
// nsIContent specializations:
diff --git a/dom/tests/mochitest/fetch/file_fetch_observer.html b/dom/tests/mochitest/fetch/file_fetch_observer.html
new file mode 100644
index 0000000000..668e609ec4
--- /dev/null
+++ b/dom/tests/mochitest/fetch/file_fetch_observer.html
@@ -0,0 +1,146 @@
+<script>
+function ok(a, msg) {
+ parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function testObserver() {
+ ok("FetchObserver" in self, "We have a FetchObserver prototype");
+
+ fetch('http://mochi.test:8888/tests/dom/tests/mochitest/fetch/slow.sjs', { observe: o => {
+ ok(!!o, "We have an observer");
+ ok(o instanceof FetchObserver, "The correct object has been passed");
+ is(o.state, "requesting", "By default the state is requesting");
+ next();
+ }});
+}
+
+function testObserveAbort() {
+ var fc = new AbortController();
+
+ fetch('http://mochi.test:8888/tests/dom/tests/mochitest/fetch/slow.sjs', {
+ signal: fc.signal,
+ observe: o => {
+ o.onstatechange = () => {
+ ok(true, "StateChange event dispatched");
+ if (o.state == "aborted") {
+ ok(true, "Aborted!");
+ next();
+ }
+ }
+ fc.abort();
+ }
+ });
+}
+
+function testObserveComplete() {
+ var fc = new AbortController();
+
+ fetch('http://mochi.test:8888/tests/dom/tests/mochitest/fetch/slow.sjs', {
+ signal: fc.signal,
+ observe: o => {
+ o.onstatechange = () => {
+ ok(true, "StateChange event dispatched");
+ if (o.state == "complete") {
+ ok(true, "Operation completed");
+ next();
+ }
+ }
+ }
+ });
+}
+
+function testObserveErrored() {
+ var fc = new AbortController();
+
+ fetch('foo: bar', {
+ signal: fc.signal,
+ observe: o => {
+ o.onstatechange = () => {
+ ok(true, "StateChange event dispatched");
+ if (o.state == "errored") {
+ ok(true, "Operation completed");
+ next();
+ }
+ }
+ }
+ });
+}
+
+function testObserveResponding() {
+ var fc = new AbortController();
+
+ fetch('http://mochi.test:8888/tests/dom/tests/mochitest/fetch/slow.sjs', {
+ signal: fc.signal,
+ observe: o => {
+ o.onstatechange = () => {
+ if (o.state == "responding") {
+ ok(true, "We have responding events");
+ next();
+ }
+ }
+ }
+ });
+}
+
+function workify(worker) {
+ function methods() {
+ function ok(a, msg) {
+ postMessage( { type: 'check', state: !!a, message: msg });
+ };
+ function is(a, b, msg) {
+ postMessage( { type: 'check', state: a === b, message: msg });
+ };
+ function next() {
+ postMessage( { type: 'finish' });
+ };
+ }
+
+ var str = methods.toString();
+ var methodsContent = str.substring(0, str.length - 1).split('\n').splice(1).join('\n');
+
+ str = worker.toString();
+ var workerContent = str.substring(0, str.length - 1).split('\n').splice(1).join('\n');
+
+ var content = methodsContent + workerContent;
+ var url = URL.createObjectURL(new Blob([content], { type: "application/javascript" }));
+ var w = new Worker(url);
+ w.onmessage = e => {
+ if (e.data.type == 'check') {
+ ok(e.data.state, "WORKER: " + e.data.message);
+ } else if (e.data.type == 'finish') {
+ next();
+ } else {
+ ok(false, "Something went wrong");
+ }
+ }
+}
+
+var steps = [
+ testObserver,
+ testObserveAbort,
+ function() { workify(testObserveAbort); },
+ testObserveComplete,
+ function() { workify(testObserveComplete); },
+ testObserveErrored,
+ function() { workify(testObserveErrored); },
+ testObserveResponding,
+ function() { workify(testObserveResponding); },
+];
+
+function next() {
+ if (!steps.length) {
+ parent.postMessage({ type: "finish" }, "*");
+ return;
+ }
+
+ var step = steps.shift();
+ step();
+}
+
+next();
+
+</script>
diff --git a/dom/tests/mochitest/fetch/mochitest.ini b/dom/tests/mochitest/fetch/mochitest.ini
index cf4477463c..a9447d0d91 100644
--- a/dom/tests/mochitest/fetch/mochitest.ini
+++ b/dom/tests/mochitest/fetch/mochitest.ini
@@ -4,6 +4,7 @@ support-files =
test_fetch_basic.js
test_fetch_basic_http.js
test_fetch_cors.js
+ file_fetch_observer.html
test_formdataparsing.js
test_headers_common.js
test_request.js
@@ -15,6 +16,7 @@ support-files =
reroute.html
reroute.js
reroute.js^headers^
+ slow.sjs
sw_reroute.js
empty.js
empty.js^headers^
@@ -47,6 +49,7 @@ skip-if = toolkit == 'android' # Bug 1210282
skip-if = toolkit == 'android' # Bug 1210282
[test_fetch_cors_sw_empty_reroute.html]
skip-if = toolkit == 'android' # Bug 1210282
+[test_fetch_observer.html]
[test_formdataparsing.html]
[test_formdataparsing_sw_reroute.html]
[test_request.html]
diff --git a/dom/tests/mochitest/fetch/slow.sjs b/dom/tests/mochitest/fetch/slow.sjs
new file mode 100644
index 0000000000..feab0f1fce
--- /dev/null
+++ b/dom/tests/mochitest/fetch/slow.sjs
@@ -0,0 +1,11 @@
+function handleRequest(request, response)
+{
+ response.processAsync();
+
+ timer = Components.classes["@mozilla.org/timer;1"].
+ createInstance(Components.interfaces.nsITimer);
+ timer.init(function() {
+ response.write("Here the content. But slowly.");
+ response.finish();
+ }, 1000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/dom/tests/mochitest/fetch/test_fetch_observer.html b/dom/tests/mochitest/fetch/test_fetch_observer.html
new file mode 100644
index 0000000000..2af86977c0
--- /dev/null
+++ b/dom/tests/mochitest/fetch/test_fetch_observer.html
@@ -0,0 +1,41 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test FetchObserver</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ],
+ ["dom.fetchController.enabled", true ]]}, () => {
+ let ifr = document.createElement('iframe');
+ ifr.src = "file_fetch_observer.html";
+ document.body.appendChild(ifr);
+
+ onmessage = function(e) {
+ if (e.data.type == "finish") {
+ SimpleTest.finish();
+ return;
+ }
+
+ if (e.data.type == "check") {
+ ok(e.data.status, e.data.message);
+ return;
+ }
+
+ ok(false, "Something when wrong.");
+ }
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini
index 496f7ea4d0..f05140c57d 100644
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -46,3 +46,4 @@ support-files =
[test_style_fallback_content.html]
[test_unresolved_pseudo_class.html]
[test_link_prefetch.html]
+[test_bug1269155.html]
diff --git a/dom/tests/mochitest/webcomponents/test_bug1269155.html b/dom/tests/mochitest/webcomponents/test_bug1269155.html
new file mode 100644
index 0000000000..f280ae1d2a
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_bug1269155.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1269155
+-->
+<head>
+ <title>Test for Bug 1269155</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.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=1269155">Mozilla Bug 1269155</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1269155 **/
+var host = document.querySelector('#content');
+ var root = host.createShadowRoot();
+
+ var header1 = document.createElement('h1');
+ header1.textContent = 'Shadow Header1';
+
+ var paragraph1 = document.createElement('p');
+ paragraph1.textContent = 'shadow text paragraph1';
+
+ root.appendChild(header1);
+ root.appendChild(paragraph1);
+
+var root2 = paragraph1.createShadowRoot();
+var header2 = document.createElement('h2');
+header2.textContent = 'Shadow Header2';
+
+var paragraph2 = document.createElement('p');
+paragraph2.textContent = 'shadow text paragraph2';
+root2.appendChild(header2);
+root2.appendChild(paragraph2);
+
+
+var frag = document.createDocumentFragment();
+var paragraph3 = document.createElement('p');
+paragraph3.textContent = 'fragment paragraph3';
+frag.appendChild(paragraph3);
+
+var root3 = paragraph3.createShadowRoot();
+var header4 = document.createElement('h2');
+header4.textContent = 'Shadow Header3';
+
+var paragraph4 = document.createElement('p');
+paragraph4.textContent = 'shadow text paragraph4';
+
+root3.appendChild(header4);
+root3.appendChild(paragraph4);
+
+//shadow dom without compose
+is(root.getRootNode(), root, "root.getRootNode() should be root.");
+is(root2.getRootNode(), root2, "root2.getRootNode() should be root.");
+is(root3.getRootNode(), root3, "root3.getRootNode() should be root.");
+is(header1.getRootNode(), root, "header1.getRootNode() should be root.");
+is(header2.getRootNode(), root2, "header1.getRootNode() should be root2.");
+is(header4.getRootNode(), root3, "header1.getRootNode() should be root3.");
+//shadow dom with compose
+is(root.getRootNode({ composed: true }), document, "root.getRootNode() with composed flag should be document.");
+is(root2.getRootNode({ composed: true }), document, "root2.getRootNode() with composed flag should be document.");
+is(root3.getRootNode({ composed: true }), frag, "root3.getRootNode() with composed flag should be frag.");
+is(header1.getRootNode({ composed: true }) , document, "header1.getRootNode() with composed flag should be document.");
+is(header2.getRootNode({ composed: true }) , document, "header2.getRootNode() with composed flag should be document.");
+is(header4.getRootNode({ composed: true }) , frag, "head4.getRootNode() with composed flag should be frag.");
+//dom without compose
+is(host.getRootNode(), document, "host.getRootNode() should be document.");
+is(header1.getRootNode(), root, "header1.getRootNode() should be root.");
+is(paragraph1.getRootNode(), root, "paragraph1.getRootNode() should be root.");
+is(frag.getRootNode(), frag, "frag.getRootNode() should be frag.");
+//dom with compose
+is(host.getRootNode({ composed: true }) , document, "host.getRootNode() with composed flag should be document.");
+is(header1.getRootNode({ composed: true }) , document, "header1.getRootNode() with composed flag should be document.");
+is(paragraph1.getRootNode({ composed: true }) , document, "paragraph1.getRootNode() with composed flag should be document.");
+is(frag.getRootNode({ composed: true }) , frag, "frag.getRootNode() with composed flag should be frag.");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/webidl/AbortController.webidl b/dom/webidl/AbortController.webidl
new file mode 100644
index 0000000000..4e91240751
--- /dev/null
+++ b/dom/webidl/AbortController.webidl
@@ -0,0 +1,13 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+[Constructor(), Exposed=(Window,Worker),
+ Func="AbortController::IsEnabled"]
+interface AbortController {
+ readonly attribute AbortSignal signal;
+
+ void abort();
+};
diff --git a/dom/webidl/AbortSignal.webidl b/dom/webidl/AbortSignal.webidl
new file mode 100644
index 0000000000..b4b03bb7e1
--- /dev/null
+++ b/dom/webidl/AbortSignal.webidl
@@ -0,0 +1,13 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+[Exposed=(Window,Worker),
+ Func="AbortController::IsEnabled"]
+interface AbortSignal : EventTarget {
+ readonly attribute boolean aborted;
+
+ attribute EventHandler onabort;
+};
diff --git a/dom/webidl/FetchObserver.webidl b/dom/webidl/FetchObserver.webidl
new file mode 100644
index 0000000000..eecd67e668
--- /dev/null
+++ b/dom/webidl/FetchObserver.webidl
@@ -0,0 +1,27 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+callback interface ObserverCallback {
+ void handleEvent(FetchObserver observer);
+};
+
+enum FetchState {
+ // Pending states
+ "requesting", "responding",
+ // Final states
+ "aborted", "errored", "complete"
+};
+
+[Exposed=(Window,Worker),
+ Func="FetchObserver::IsEnabled"]
+interface FetchObserver : EventTarget {
+ readonly attribute FetchState state;
+
+ // Events
+ attribute EventHandler onstatechange;
+ attribute EventHandler onrequestprogress;
+ attribute EventHandler onresponseprogress;
+};
diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl
index 7d18899b03..0a14e36245 100644
--- a/dom/webidl/Node.webidl
+++ b/dom/webidl/Node.webidl
@@ -38,8 +38,8 @@ interface Node : EventTarget {
readonly attribute boolean isConnected;
[Pure]
readonly attribute Document? ownerDocument;
- [Pure, Pref="dom.node.rootNode.enabled"]
- readonly attribute Node rootNode;
+ [Pure]
+ Node getRootNode(optional GetRootNodeOptions options);
[Pure]
readonly attribute Node? parentNode;
[Pure]
@@ -113,3 +113,8 @@ interface Node : EventTarget {
readonly attribute AccessibleNode? accessibleNode;
#endif
};
+
+dictionary GetRootNodeOptions {
+ boolean composed = false;
+};
+
diff --git a/dom/webidl/Request.webidl b/dom/webidl/Request.webidl
index e29c084d00..fe6a63ec0d 100644
--- a/dom/webidl/Request.webidl
+++ b/dom/webidl/Request.webidl
@@ -47,6 +47,12 @@ dictionary RequestInit {
RequestCache cache;
RequestRedirect redirect;
DOMString integrity;
+
+ [Func="AbortController::IsEnabled"]
+ AbortSignal signal;
+
+ [Func="FetchObserver::IsEnabled"]
+ ObserverCallback observe;
};
// Gecko currently does not ship RequestContext, so please don't use it in IDL
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index 5e913585ee..d8309c2650 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -17,6 +17,8 @@ PREPROCESSED_WEBIDL_FILES = [
]
WEBIDL_FILES = [
+ 'AbortController.webidl',
+ 'AbortSignal.webidl',
'AbstractWorker.webidl',
'AnalyserNode.webidl',
'Animatable.webidl',
@@ -142,6 +144,7 @@ WEBIDL_FILES = [
'FakePluginTagInit.webidl',
'Fetch.webidl',
'FetchEvent.webidl',
+ 'FetchObserver.webidl',
'File.webidl',
'FileList.webidl',
'FileMode.webidl',
diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
index 56b18441e5..bcec94dcb4 100644
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -34,7 +34,6 @@
#include "nsIPipe.h"
#include "nsIOutputStream.h"
#include "nsPrintfCString.h"
-#include "nsScriptLoader.h"
#include "nsString.h"
#include "nsStreamUtils.h"
#include "nsTArray.h"
@@ -58,6 +57,7 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/Response.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SRILogHelper.h"
#include "mozilla/UniquePtr.h"
@@ -1075,14 +1075,14 @@ private:
// May be null.
nsIDocument* parentDoc = mWorkerPrivate->GetDocument();
- // Use the regular nsScriptLoader for this grunt work! Should be just fine
+ // Use the regular ScriptLoader for this grunt work! Should be just fine
// because we're running on the main thread.
// Unlike <script> tags, Worker scripts are always decoded as UTF-8,
// per spec. So we explicitly pass in the charset hint.
- rv = nsScriptLoader::ConvertToUTF16(aLoadInfo.mChannel, aString, aStringLen,
- NS_LITERAL_STRING("UTF-8"), parentDoc,
- aLoadInfo.mScriptTextBuf,
- aLoadInfo.mScriptTextLength);
+ rv = ScriptLoader::ConvertToUTF16(aLoadInfo.mChannel, aString, aStringLen,
+ NS_LITERAL_STRING("UTF-8"), parentDoc,
+ aLoadInfo.mScriptTextBuf,
+ aLoadInfo.mScriptTextLength);
if (NS_FAILED(rv)) {
return rv;
}
@@ -1289,10 +1289,10 @@ private:
MOZ_ASSERT(!loadInfo.mScriptTextBuf);
nsresult rv =
- nsScriptLoader::ConvertToUTF16(nullptr, aString, aStringLen,
- NS_LITERAL_STRING("UTF-8"), parentDoc,
- loadInfo.mScriptTextBuf,
- loadInfo.mScriptTextLength);
+ ScriptLoader::ConvertToUTF16(nullptr, aString, aStringLen,
+ NS_LITERAL_STRING("UTF-8"), parentDoc,
+ loadInfo.mScriptTextBuf,
+ loadInfo.mScriptTextLength);
if (NS_SUCCEEDED(rv) && IsMainWorkerScript()) {
nsCOMPtr<nsIURI> finalURI;
rv = NS_NewURI(getter_AddRefs(finalURI), loadInfo.mFullURL, nullptr, nullptr);
diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
index a8f191f2e6..306ef6b235 100644
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -22,7 +22,6 @@
#include "nsITimer.h"
#include "nsIUploadChannel2.h"
#include "nsPIDOMWindow.h"
-#include "nsScriptLoader.h"
#include "nsServiceManagerUtils.h"
#include "nsDebug.h"
#include "nsISupportsPrimitives.h"
@@ -44,6 +43,7 @@
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/Request.h"
#include "mozilla/dom/RootedDictionary.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp
index f44bb673c8..707b689e8a 100644
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -11,6 +11,7 @@
#include "mozilla/dom/cache/Cache.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseWorkerProxy.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsICacheInfoChannel.h"
@@ -23,7 +24,6 @@
#include "nsIScriptError.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
-#include "nsScriptLoader.h"
#include "ServiceWorkerManager.h"
#include "Workers.h"
#include "nsStringStream.h"
@@ -801,9 +801,9 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
char16_t* buffer = nullptr;
size_t len = 0;
- rv = nsScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
- NS_LITERAL_STRING("UTF-8"), nullptr,
- buffer, len);
+ rv = ScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
+ NS_LITERAL_STRING("UTF-8"), nullptr,
+ buffer, len);
if (NS_WARN_IF(NS_FAILED(rv))) {
mManager->NetworkFinished(rv);
return rv;
@@ -855,9 +855,9 @@ CompareCache::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext,
char16_t* buffer = nullptr;
size_t len = 0;
- nsresult rv = nsScriptLoader::ConvertToUTF16(nullptr, aString, aLen,
- NS_LITERAL_STRING("UTF-8"),
- nullptr, buffer, len);
+ nsresult rv = ScriptLoader::ConvertToUTF16(nullptr, aString, aLen,
+ NS_LITERAL_STRING("UTF-8"),
+ nullptr, buffer, len);
if (NS_WARN_IF(NS_FAILED(rv))) {
mManager->CacheFinished(rv, false);
return rv;
diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h
index 9a1be4801f..b552d89561 100644
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -39,6 +39,8 @@ WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
+WORKER_SIMPLE_PREF("dom.abortController.enabled", AbortControllerEnabled, ABORTCONTROLLER_ENABLED)
+WORKER_SIMPLE_PREF("dom.fetchObserver.enabled", FetchObserverEnabled, FETCHOBSERVER_ENABLED)
WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)
diff --git a/dom/worklet/Worklet.cpp b/dom/worklet/Worklet.cpp
index 19a877ea8f..1b71916abf 100644
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -12,11 +12,11 @@
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/RegisterWorkletBindings.h"
#include "mozilla/dom/Response.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsIInputStreamPump.h"
#include "nsIThreadRetargetableRequest.h"
#include "nsNetUtil.h"
-#include "nsScriptLoader.h"
#include "xpcprivate.h"
namespace mozilla {
@@ -171,9 +171,9 @@ public:
char16_t* scriptTextBuf;
size_t scriptTextLength;
nsresult rv =
- nsScriptLoader::ConvertToUTF16(nullptr, aString, aStringLen,
- NS_LITERAL_STRING("UTF-8"), nullptr,
- scriptTextBuf, scriptTextLength);
+ ScriptLoader::ConvertToUTF16(nullptr, aString, aStringLen,
+ NS_LITERAL_STRING("UTF-8"), nullptr,
+ scriptTextBuf, scriptTextLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
RejectPromises(rv);
return NS_OK;
diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp
index 7c9d308fd6..daf1dbf271 100644
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -35,7 +35,6 @@
#include "nsRect.h"
#include "nsIWebNavigation.h"
#include "nsIScriptElement.h"
-#include "nsScriptLoader.h"
#include "nsStyleLinkElement.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
@@ -62,6 +61,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/ProcessingInstruction.h"
+#include "mozilla/dom/ScriptLoader.h"
using namespace mozilla;
using namespace mozilla::dom;
diff --git a/dom/xml/nsXMLFragmentContentSink.cpp b/dom/xml/nsXMLFragmentContentSink.cpp
index 7fa815c84a..7d9f869879 100644
--- a/dom/xml/nsXMLFragmentContentSink.cpp
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -24,10 +24,10 @@
#include "nsTArray.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocShell.h"
-#include "nsScriptLoader.h"
#include "mozilla/css/Loader.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/ProcessingInstruction.h"
+#include "mozilla/dom/ScriptLoader.h"
using namespace mozilla::dom;
diff --git a/dom/xslt/xslt/txMozillaXMLOutput.cpp b/dom/xslt/xslt/txMozillaXMLOutput.cpp
index 069413d976..704d8ac110 100644
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -7,7 +7,6 @@
#include "nsIDocument.h"
#include "nsIDocShell.h"
-#include "nsScriptLoader.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentType.h"
#include "nsIScriptElement.h"
@@ -31,6 +30,7 @@
#include "mozilla/css/Loader.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "nsContentUtils.h"
#include "txXMLUtils.h"
#include "nsContentSink.h"
@@ -230,7 +230,7 @@ txMozillaXMLOutput::endDocument(nsresult aResult)
MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
nsIDocument::READYSTATE_LOADING, "Bad readyState");
mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
- nsScriptLoader* loader = mDocument->ScriptLoader();
+ ScriptLoader* loader = mDocument->ScriptLoader();
if (loader) {
loader->ParsingComplete(false);
}
@@ -416,7 +416,7 @@ txMozillaXMLOutput::startDocument()
}
if (mCreatingNewDocument) {
- nsScriptLoader* loader = mDocument->ScriptLoader();
+ ScriptLoader* loader = mDocument->ScriptLoader();
if (loader) {
loader->BeginDeferringScripts();
}
@@ -857,7 +857,7 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID
}
// Set up script loader of the result document.
- nsScriptLoader *loader = mDocument->ScriptLoader();
+ ScriptLoader *loader = mDocument->ScriptLoader();
if (mNotifier) {
loader->AddObserver(mNotifier);
}
diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp
index 1dcb55aee4..36481f9896 100644
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -3337,10 +3337,10 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
!mOffThreadCompileStringBuf),
"XULDocument can't load multiple scripts at once");
- rv = nsScriptLoader::ConvertToUTF16(channel, string, stringLen,
- EmptyString(), this,
- mOffThreadCompileStringBuf,
- mOffThreadCompileStringLength);
+ rv = ScriptLoader::ConvertToUTF16(channel, string, stringLen,
+ EmptyString(), this,
+ mOffThreadCompileStringBuf,
+ mOffThreadCompileStringLength);
if (NS_SUCCEEDED(rv)) {
// Attempt to give ownership of the buffer to the JS engine. If
// we hit offthread compilation, however, we will have to take it
diff --git a/dom/xul/XULDocument.h b/dom/xul/XULDocument.h
index 06abb797f0..e72edfeed0 100644
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -21,13 +21,13 @@
#include "nsCOMArray.h"
#include "nsIURI.h"
#include "nsIXULDocument.h"
-#include "nsScriptLoader.h"
#include "nsIStreamListener.h"
#include "nsIStreamLoader.h"
#include "nsICSSLoaderObserver.h"
#include "nsIXULStore.h"
#include "mozilla/Attributes.h"
+#include "mozilla/dom/ScriptLoader.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
diff --git a/dom/xul/nsXULContentSink.cpp b/dom/xul/nsXULContentSink.cpp
index edeee87280..94560e70db 100644
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -881,7 +881,7 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
isJavaScript = false;
}
} else if (key.EqualsLiteral("language")) {
- // Language is deprecated, and the impl in nsScriptLoader ignores the
+ // Language is deprecated, and the impl in ScriptLoader ignores the
// various version strings anyway. So we make no attempt to support
// languages other than JS for language=
nsAutoString lang(aAttributes[1]);