From 438cdbd913109771d695093c5cb5d5106c613663 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 09:56:33 +0800 Subject: [PATCH 01/10] Issue #2197 - Part 1a: postMessages should have transferable as [] by default Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336020 --- dom/base/nsGlobalWindow.cpp | 9 +++--- dom/base/nsGlobalWindow.h | 2 +- dom/messagechannel/MessagePort.cpp | 15 +++++----- dom/messagechannel/MessagePort.h | 2 +- dom/webidl/Client.webidl | 2 +- dom/webidl/DedicatedWorkerGlobalScope.webidl | 2 +- dom/webidl/MessagePort.webidl | 2 +- dom/webidl/ServiceWorker.webidl | 2 +- dom/webidl/Window.webidl | 2 +- dom/webidl/Worker.webidl | 2 +- dom/workers/ServiceWorker.cpp | 2 +- dom/workers/ServiceWorker.h | 2 +- dom/workers/ServiceWorkerClient.cpp | 10 +++---- dom/workers/ServiceWorkerClient.h | 2 +- dom/workers/ServiceWorkerPrivate.cpp | 2 +- dom/workers/ServiceWorkerPrivate.h | 2 +- dom/workers/SharedWorker.cpp | 2 +- dom/workers/SharedWorker.h | 2 +- dom/workers/WorkerPrivate.cpp | 30 +++++++++----------- dom/workers/WorkerPrivate.h | 12 ++++---- dom/workers/WorkerScope.cpp | 2 +- dom/workers/WorkerScope.h | 2 +- 22 files changed, 52 insertions(+), 58 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index b9bb459eba..307ec495ca 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -8888,18 +8888,17 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, void nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, const nsAString& aTargetOrigin, - const Optional>& aTransfer, + const Sequence& aTransfer, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError) { JS::Rooted transferArray(aCx, JS::UndefinedValue()); - if (aTransfer.WasPassed()) { - const Sequence& values = aTransfer.Value(); - + if (!aTransfer.IsEmpty()) { // The input sequence only comes from the generated bindings code, which // ensures it is rooted. JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(values.Length(), values.Elements()); + JS::HandleValueArray::fromMarkedLocation(aTransfer.Length(), + aTransfer.Elements()); transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx, elements)); if (transferArray.isNull()) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index e42835a0b2..f4829ccac8 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -933,7 +933,7 @@ public: void Print(mozilla::ErrorResult& aError); void PostMessageMoz(JSContext* aCx, JS::Handle aMessage, const nsAString& aTargetOrigin, - const mozilla::dom::Optional >& aTransfer, + const mozilla::dom::Sequence& aTransfer, nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError); int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction, diff --git a/dom/messagechannel/MessagePort.cpp b/dom/messagechannel/MessagePort.cpp index 6f7a1abc19..515a0f3ef1 100644 --- a/dom/messagechannel/MessagePort.cpp +++ b/dom/messagechannel/MessagePort.cpp @@ -394,20 +394,19 @@ MessagePort::WrapObject(JSContext* aCx, JS::Handle aGivenProto) } void -MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, +MessagePort::PostMessage(JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, ErrorResult& aRv) { // We *must* clone the data here, or the JS::Value could be modified // by script JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (aTransferable.WasPassed()) { - const Sequence& realTransferable = aTransferable.Value(); - + if (!aTransferable.IsEmpty()) { // Here we want to check if the transerable object list contains // this port. No other checks are done. - for (const JS::Value& value : realTransferable) { + for (const JS::Value& value : aTransferable) { if (!value.isObject()) { continue; } @@ -429,8 +428,8 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, // The input sequence only comes from the generated bindings code, which // ensures it is rooted. JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), - realTransferable.Elements()); + JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), + aTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); diff --git a/dom/messagechannel/MessagePort.h b/dom/messagechannel/MessagePort.h index 0ed2af11c1..2c012925a4 100644 --- a/dom/messagechannel/MessagePort.h +++ b/dom/messagechannel/MessagePort.h @@ -62,7 +62,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void Start(); diff --git a/dom/webidl/Client.webidl b/dom/webidl/Client.webidl index 3e79c6a635..df73a79d79 100644 --- a/dom/webidl/Client.webidl +++ b/dom/webidl/Client.webidl @@ -15,7 +15,7 @@ interface Client { readonly attribute DOMString id; [Throws] - void postMessage(any message, optional sequence transfer); + void postMessage(any message, optional sequence transfer = []); }; [Exposed=ServiceWorker] diff --git a/dom/webidl/DedicatedWorkerGlobalScope.webidl b/dom/webidl/DedicatedWorkerGlobalScope.webidl index 26dca58dab..75a4032676 100644 --- a/dom/webidl/DedicatedWorkerGlobalScope.webidl +++ b/dom/webidl/DedicatedWorkerGlobalScope.webidl @@ -16,7 +16,7 @@ Exposed=DedicatedWorker] interface DedicatedWorkerGlobalScope : WorkerGlobalScope { [Throws] - void postMessage(any message, optional sequence transfer); + void postMessage(any message, optional sequence transfer = []); attribute EventHandler onmessage; }; diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl index 59c61a7149..aef7e4bd11 100644 --- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -10,7 +10,7 @@ [Exposed=(Window,Worker,System)] interface MessagePort : EventTarget { [Throws] - void postMessage(any message, optional sequence transferable); + void postMessage(any message, optional sequence transferable = []); void start(); void close(); diff --git a/dom/webidl/ServiceWorker.webidl b/dom/webidl/ServiceWorker.webidl index 8c3749e940..17fc903dcb 100644 --- a/dom/webidl/ServiceWorker.webidl +++ b/dom/webidl/ServiceWorker.webidl @@ -21,7 +21,7 @@ interface ServiceWorker : EventTarget { // FIXME(catalinb): Should inherit this from Worker. [Throws] - void postMessage(any message, optional sequence transferable); + void postMessage(any message, optional sequence transferable = []); }; ServiceWorker implements AbstractWorker; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 1b98042473..199a846bd1 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -80,7 +80,7 @@ typedef any Transferable; [Throws, UnsafeInPrerendering] void print(); [Throws, CrossOriginCallable, NeedsSubjectPrincipal] - void postMessage(any message, DOMString targetOrigin, optional sequence transfer); + void postMessage(any message, DOMString targetOrigin, optional sequence transfer = []); // also has obsolete members }; diff --git a/dom/webidl/Worker.webidl b/dom/webidl/Worker.webidl index 158a502d60..4bc79e9e15 100644 --- a/dom/webidl/Worker.webidl +++ b/dom/webidl/Worker.webidl @@ -19,7 +19,7 @@ interface Worker : EventTarget { void terminate(); [Throws] - void postMessage(any message, optional sequence transfer); + void postMessage(any message, optional sequence transfer = []); attribute EventHandler onmessage; }; diff --git a/dom/workers/ServiceWorker.cpp b/dom/workers/ServiceWorker.cpp index 16dd28b8ad..257c2ba007 100644 --- a/dom/workers/ServiceWorker.cpp +++ b/dom/workers/ServiceWorker.cpp @@ -77,7 +77,7 @@ ServiceWorker::GetScriptURL(nsString& aURL) const void ServiceWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { if (State() == ServiceWorkerState::Redundant) { diff --git a/dom/workers/ServiceWorker.h b/dom/workers/ServiceWorker.h index 3a3cce8260..ac3c2abe1d 100644 --- a/dom/workers/ServiceWorker.h +++ b/dom/workers/ServiceWorker.h @@ -63,7 +63,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); private: diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp index 1f845a947b..9b9e43b2b6 100644 --- a/dom/workers/ServiceWorkerClient.cpp +++ b/dom/workers/ServiceWorkerClient.cpp @@ -190,7 +190,7 @@ private: void ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); @@ -198,12 +198,10 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, workerPrivate->AssertIsOnWorkerThread(); JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (aTransferable.WasPassed()) { - const Sequence& realTransferable = aTransferable.Value(); - + if (!aTransferable.IsEmpty()) { JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), - realTransferable.Elements()); + JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), + aTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); if (!array) { diff --git a/dom/workers/ServiceWorkerClient.h b/dom/workers/ServiceWorkerClient.h index 46bcdbc4c4..bbf7ddf489 100644 --- a/dom/workers/ServiceWorkerClient.h +++ b/dom/workers/ServiceWorkerClient.h @@ -91,7 +91,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp index 2f5b8f7500..acb666415d 100644 --- a/dom/workers/ServiceWorkerPrivate.cpp +++ b/dom/workers/ServiceWorkerPrivate.cpp @@ -141,7 +141,7 @@ NS_IMPL_ISUPPORTS0(MessageWaitUntilHandler) nsresult ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo) { ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr)); diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h index 8ce021c8cf..bd55749277 100644 --- a/dom/workers/ServiceWorkerPrivate.h +++ b/dom/workers/ServiceWorkerPrivate.h @@ -74,7 +74,7 @@ public: nsresult SendMessageEvent(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo); // This is used to validate the worker script and continue the installation diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 97df0f57fd..7ef96c281e 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -142,7 +142,7 @@ SharedWorker::Close() void SharedWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { AssertIsOnMainThread(); diff --git a/dom/workers/SharedWorker.h b/dom/workers/SharedWorker.h index 4820b4e7c1..2b4862f9db 100644 --- a/dom/workers/SharedWorker.h +++ b/dom/workers/SharedWorker.h @@ -95,7 +95,7 @@ private: // Only called by MessagePort. void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); }; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index cf270703e0..6a95544704 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3009,7 +3009,7 @@ void WorkerPrivateParent::PostMessageInternal( JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv) @@ -3024,14 +3024,12 @@ WorkerPrivateParent::PostMessageInternal( } JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (aTransferable.WasPassed()) { - const Sequence& realTransferable = aTransferable.Value(); - + if (!aTransferable.IsEmpty()) { // The input sequence only comes from the generated bindings code, which // ensures it is rooted. JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), - realTransferable.Elements()); + JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), + aTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); @@ -3083,8 +3081,9 @@ WorkerPrivateParent::PostMessageInternal( template void WorkerPrivateParent::PostMessage( - JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, ErrorResult& aRv) { PostMessageInternal(aCx, aMessage, aTransferable, nullptr, nullptr, aRv); @@ -3093,8 +3092,9 @@ WorkerPrivateParent::PostMessage( template void WorkerPrivateParent::PostMessageToServiceWorker( - JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv) @@ -5677,20 +5677,18 @@ void WorkerPrivate::PostMessageToParentInternal( JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { AssertIsOnWorkerThread(); JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (aTransferable.WasPassed()) { - const Sequence& realTransferable = aTransferable.Value(); - + if (!aTransferable.IsEmpty()) { // The input sequence only comes from the generated bindings code, which // ensures it is rooted. JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), - realTransferable.Elements()); + JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), + aTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); if (!array) { diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index b638c1ef11..dd0f990ba8 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -287,7 +287,7 @@ private: void PostMessageInternal(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv); @@ -400,12 +400,12 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void PostMessageToServiceWorker(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv); @@ -1161,7 +1161,7 @@ public: void PostMessageToParent(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { PostMessageToParentInternal(aCx, aMessage, aTransferable, aRv); @@ -1171,7 +1171,7 @@ public: PostMessageToParentMessagePort( JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void @@ -1471,7 +1471,7 @@ private: void PostMessageToParentInternal(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index ec42364b52..3b9215a8e9 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -535,7 +535,7 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx, void DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { mWorkerPrivate->AssertIsOnWorkerThread(); diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 8d06152da2..a8062298e9 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -215,7 +215,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional>& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); IMPL_EVENT_HANDLER(message) From 47147d58b0c07d7834f6a220f211cb40ecb7dab0 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 12:04:38 +0800 Subject: [PATCH 02/10] Issue #2197 - Part 1b: Transferables should be arrays of objects Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336020 --- dom/base/nsContentUtils.cpp | 30 +++++++++++ dom/base/nsContentUtils.h | 5 ++ dom/base/nsGlobalWindow.cpp | 25 ++++----- dom/base/nsGlobalWindow.h | 4 +- dom/messagechannel/MessagePort.cpp | 52 +++++++----------- dom/messagechannel/MessagePort.h | 2 +- dom/webidl/Client.webidl | 2 +- dom/webidl/DedicatedWorkerGlobalScope.webidl | 2 +- dom/webidl/MessagePort.webidl | 2 +- dom/webidl/ServiceWorker.webidl | 3 +- dom/webidl/Window.webidl | 3 +- dom/webidl/Worker.webidl | 2 +- dom/workers/ServiceWorker.cpp | 2 +- dom/workers/ServiceWorker.h | 2 +- dom/workers/ServiceWorkerClient.cpp | 19 +++---- dom/workers/ServiceWorkerClient.h | 2 +- dom/workers/ServiceWorkerPrivate.cpp | 2 +- dom/workers/ServiceWorkerPrivate.h | 2 +- dom/workers/SharedWorker.cpp | 2 +- dom/workers/SharedWorker.h | 5 +- dom/workers/WorkerPrivate.cpp | 56 +++++++------------- dom/workers/WorkerPrivate.h | 19 ++++--- dom/workers/WorkerScope.cpp | 2 +- dom/workers/WorkerScope.h | 2 +- 24 files changed, 118 insertions(+), 129 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index de3beb2938..ded37bd4c8 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -9993,3 +9993,33 @@ nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement) } return e; } + +/* static */ nsresult +nsContentUtils::CreateJSValueFromSequenceOfObject(JSContext* aCx, + const Sequence& aTransfer, + JS::MutableHandle aValue) +{ + if (aTransfer.IsEmpty()) { + return NS_OK; + } + + JS::Rooted array(aCx, JS_NewArrayObject(aCx, aTransfer.Length())); + if (!array) { + return NS_ERROR_OUT_OF_MEMORY; + } + + for (uint32_t i = 0; i < aTransfer.Length(); ++i) { + JS::Rooted object(aCx, aTransfer[i]); + if (!object) { + continue; + } + + if (NS_WARN_IF(!JS_DefineElement(aCx, array, i, object, + JSPROP_ENUMERATE))) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + aValue.setObject(*array); + return NS_OK; +} diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index f2ba5cb490..62f8451555 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2812,6 +2812,11 @@ public: static bool IsCustomElementsEnabled() { return sIsCustomElementsEnabled; } + static nsresult + CreateJSValueFromSequenceOfObject(JSContext* aCx, + const mozilla::dom::Sequence& aTransfer, + JS::MutableHandle aValue); + private: static bool InitializeEventTable(); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 307ec495ca..7c0256a2b7 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -8886,29 +8886,22 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, } void -nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, +nsGlobalWindow::PostMessageMoz(JSContext* aCx, + JS::Handle aMessage, const nsAString& aTargetOrigin, - const Sequence& aTransfer, + const Sequence& aTransfer, nsIPrincipal& aSubjectPrincipal, - ErrorResult& aError) + ErrorResult& aRv) { JS::Rooted transferArray(aCx, JS::UndefinedValue()); - if (!aTransfer.IsEmpty()) { - // The input sequence only comes from the generated bindings code, which - // ensures it is rooted. - JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(aTransfer.Length(), - aTransfer.Elements()); - - transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx, elements)); - if (transferArray.isNull()) { - aError.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } + aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer, + &transferArray); + if (NS_WARN_IF(aRv.Failed())) { + return; } PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, - aSubjectPrincipal, aError); + aSubjectPrincipal, aRv); } class nsCloseEvent : public Runnable { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index f4829ccac8..8c961e2014 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -933,9 +933,9 @@ public: void Print(mozilla::ErrorResult& aError); void PostMessageMoz(JSContext* aCx, JS::Handle aMessage, const nsAString& aTargetOrigin, - const mozilla::dom::Sequence& aTransfer, + const mozilla::dom::Sequence& aTransfer, nsIPrincipal& aSubjectPrincipal, - mozilla::ErrorResult& aError); + mozilla::ErrorResult& aRv); int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction, int32_t aTimeout, const mozilla::dom::Sequence& aArguments, diff --git a/dom/messagechannel/MessagePort.cpp b/dom/messagechannel/MessagePort.cpp index 515a0f3ef1..a63c84b2b0 100644 --- a/dom/messagechannel/MessagePort.cpp +++ b/dom/messagechannel/MessagePort.cpp @@ -396,49 +396,37 @@ MessagePort::WrapObject(JSContext* aCx, JS::Handle aGivenProto) void MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { // We *must* clone the data here, or the JS::Value could be modified // by script - JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (!aTransferable.IsEmpty()) { - // Here we want to check if the transerable object list contains - // this port. No other checks are done. - for (const JS::Value& value : aTransferable) { - if (!value.isObject()) { - continue; - } - - JS::Rooted object(aCx, &value.toObject()); - - MessagePort* port = nullptr; - nsresult rv = UNWRAP_OBJECT(MessagePort, &object, port); - if (NS_FAILED(rv)) { - continue; - } - - if (port == this) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); - return; - } + // Here we want to check if the transferable object list contains + // this port. + for (uint32_t i = 0; i < aTransferable.Length(); ++i) { + JSObject* rawObject = aTransferable[i]; + if (!rawObject) { + continue; } - // The input sequence only comes from the generated bindings code, which - // ensures it is rooted. - JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), - aTransferable.Elements()); + JS::Rooted object(aCx, rawObject); - JSObject* array = - JS_NewArrayObject(aCx, elements); - if (!array) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + MessagePort* port = nullptr; + nsresult rv = UNWRAP_OBJECT(MessagePort, &object, port); + if (NS_SUCCEEDED(rv) && port == this) { + aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } + } - transferable.setObject(*array); + JS::Rooted transferable(aCx, JS::UndefinedValue()); + + aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, + aTransferable, + &transferable); + if (NS_WARN_IF(aRv.Failed())) { + return; } RefPtr data = new SharedMessagePortMessage(); diff --git a/dom/messagechannel/MessagePort.h b/dom/messagechannel/MessagePort.h index 2c012925a4..e635c532a3 100644 --- a/dom/messagechannel/MessagePort.h +++ b/dom/messagechannel/MessagePort.h @@ -62,7 +62,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void Start(); diff --git a/dom/webidl/Client.webidl b/dom/webidl/Client.webidl index df73a79d79..7abb65ab12 100644 --- a/dom/webidl/Client.webidl +++ b/dom/webidl/Client.webidl @@ -15,7 +15,7 @@ interface Client { readonly attribute DOMString id; [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, optional sequence transfer = []); }; [Exposed=ServiceWorker] diff --git a/dom/webidl/DedicatedWorkerGlobalScope.webidl b/dom/webidl/DedicatedWorkerGlobalScope.webidl index 75a4032676..ad3125fa31 100644 --- a/dom/webidl/DedicatedWorkerGlobalScope.webidl +++ b/dom/webidl/DedicatedWorkerGlobalScope.webidl @@ -16,7 +16,7 @@ Exposed=DedicatedWorker] interface DedicatedWorkerGlobalScope : WorkerGlobalScope { [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, optional sequence transfer = []); attribute EventHandler onmessage; }; diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl index aef7e4bd11..6495b5616d 100644 --- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -10,7 +10,7 @@ [Exposed=(Window,Worker,System)] interface MessagePort : EventTarget { [Throws] - void postMessage(any message, optional sequence transferable = []); + void postMessage(any message, optional sequence transferable = []); void start(); void close(); diff --git a/dom/webidl/ServiceWorker.webidl b/dom/webidl/ServiceWorker.webidl index 17fc903dcb..6dab46a16b 100644 --- a/dom/webidl/ServiceWorker.webidl +++ b/dom/webidl/ServiceWorker.webidl @@ -19,9 +19,8 @@ interface ServiceWorker : EventTarget { attribute EventHandler onstatechange; - // FIXME(catalinb): Should inherit this from Worker. [Throws] - void postMessage(any message, optional sequence transferable = []); + void postMessage(any message, optional sequence transferable = []); }; ServiceWorker implements AbstractWorker; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 199a846bd1..73d5843a16 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -22,7 +22,6 @@ interface IID; interface nsIBrowserDOMWindow; interface nsIMessageBroadcaster; interface nsIDOMCrypto; -typedef any Transferable; // http://www.whatwg.org/specs/web-apps/current-work/ [PrimaryGlobal, LegacyUnenumerableNamedProperties, NeedResolve] @@ -80,7 +79,7 @@ typedef any Transferable; [Throws, UnsafeInPrerendering] void print(); [Throws, CrossOriginCallable, NeedsSubjectPrincipal] - void postMessage(any message, DOMString targetOrigin, optional sequence transfer = []); + void postMessage(any message, DOMString targetOrigin, optional sequence transfer = []); // also has obsolete members }; diff --git a/dom/webidl/Worker.webidl b/dom/webidl/Worker.webidl index 4bc79e9e15..44f406d8ce 100644 --- a/dom/webidl/Worker.webidl +++ b/dom/webidl/Worker.webidl @@ -19,7 +19,7 @@ interface Worker : EventTarget { void terminate(); [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, optional sequence transfer = []); attribute EventHandler onmessage; }; diff --git a/dom/workers/ServiceWorker.cpp b/dom/workers/ServiceWorker.cpp index 257c2ba007..87b86c4805 100644 --- a/dom/workers/ServiceWorker.cpp +++ b/dom/workers/ServiceWorker.cpp @@ -77,7 +77,7 @@ ServiceWorker::GetScriptURL(nsString& aURL) const void ServiceWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { if (State() == ServiceWorkerState::Redundant) { diff --git a/dom/workers/ServiceWorker.h b/dom/workers/ServiceWorker.h index ac3c2abe1d..d85d055aab 100644 --- a/dom/workers/ServiceWorker.h +++ b/dom/workers/ServiceWorker.h @@ -63,7 +63,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); private: diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp index 9b9e43b2b6..eb4e676ffa 100644 --- a/dom/workers/ServiceWorkerClient.cpp +++ b/dom/workers/ServiceWorkerClient.cpp @@ -190,7 +190,7 @@ private: void ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); @@ -198,18 +198,11 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, workerPrivate->AssertIsOnWorkerThread(); JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (!aTransferable.IsEmpty()) { - JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), - aTransferable.Elements()); - - JSObject* array = JS_NewArrayObject(aCx, elements); - if (!array) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - - transferable.setObject(*array); + aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, + aTransferable, + &transferable); + if (NS_WARN_IF(aRv.Failed())) { + return; } RefPtr runnable = diff --git a/dom/workers/ServiceWorkerClient.h b/dom/workers/ServiceWorkerClient.h index bbf7ddf489..4d8759c408 100644 --- a/dom/workers/ServiceWorkerClient.h +++ b/dom/workers/ServiceWorkerClient.h @@ -91,7 +91,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp index acb666415d..fe6ec138b7 100644 --- a/dom/workers/ServiceWorkerPrivate.cpp +++ b/dom/workers/ServiceWorkerPrivate.cpp @@ -141,7 +141,7 @@ NS_IMPL_ISUPPORTS0(MessageWaitUntilHandler) nsresult ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo) { ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr)); diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h index bd55749277..c2d5abfd6c 100644 --- a/dom/workers/ServiceWorkerPrivate.h +++ b/dom/workers/ServiceWorkerPrivate.h @@ -74,7 +74,7 @@ public: nsresult SendMessageEvent(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo); // This is used to validate the worker script and continue the installation diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 7ef96c281e..03c45c96a1 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -142,7 +142,7 @@ SharedWorker::Close() void SharedWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { AssertIsOnMainThread(); diff --git a/dom/workers/SharedWorker.h b/dom/workers/SharedWorker.h index 2b4862f9db..6b328811d5 100644 --- a/dom/workers/SharedWorker.h +++ b/dom/workers/SharedWorker.h @@ -94,8 +94,9 @@ private: // Only called by MessagePort. void - PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, ErrorResult& aRv); }; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 6a95544704..2c3d439bd8 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3006,13 +3006,12 @@ WorkerPrivateParent::ForgetMainThreadObjects( template void -WorkerPrivateParent::PostMessageInternal( - JSContext* aCx, - JS::Handle aMessage, - const Sequence& aTransferable, - UniquePtr&& aClientInfo, - PromiseNativeHandler* aHandler, - ErrorResult& aRv) +WorkerPrivateParent::PostMessageInternal(JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, + UniquePtr&& aClientInfo, + PromiseNativeHandler* aHandler, + ErrorResult& aRv) { AssertIsOnParentThread(); @@ -3024,20 +3023,11 @@ WorkerPrivateParent::PostMessageInternal( } JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (!aTransferable.IsEmpty()) { - // The input sequence only comes from the generated bindings code, which - // ensures it is rooted. - JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), - aTransferable.Elements()); - - JSObject* array = - JS_NewArrayObject(aCx, elements); - if (!array) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - transferable.setObject(*array); + aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, + aTransferable, + &transferable); + if (NS_WARN_IF(aRv.Failed())) { + return; } RefPtr runnable = @@ -3083,7 +3073,7 @@ void WorkerPrivateParent::PostMessage( JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { PostMessageInternal(aCx, aMessage, aTransferable, nullptr, nullptr, aRv); @@ -3094,7 +3084,7 @@ void WorkerPrivateParent::PostMessageToServiceWorker( JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv) @@ -5677,25 +5667,17 @@ void WorkerPrivate::PostMessageToParentInternal( JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { AssertIsOnWorkerThread(); JS::Rooted transferable(aCx, JS::UndefinedValue()); - if (!aTransferable.IsEmpty()) { - // The input sequence only comes from the generated bindings code, which - // ensures it is rooted. - JS::HandleValueArray elements = - JS::HandleValueArray::fromMarkedLocation(aTransferable.Length(), - aTransferable.Elements()); - - JSObject* array = JS_NewArrayObject(aCx, elements); - if (!array) { - aRv = NS_ERROR_OUT_OF_MEMORY; - return; - } - transferable.setObject(*array); + aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, + aTransferable, + &transferable); + if (NS_WARN_IF(aRv.Failed())) { + return; } RefPtr runnable = diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index dd0f990ba8..cf1a3c22fc 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -287,7 +287,7 @@ private: void PostMessageInternal(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv); @@ -400,12 +400,12 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void PostMessageToServiceWorker(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, UniquePtr&& aClientInfo, PromiseNativeHandler* aHandler, ErrorResult& aRv); @@ -1161,18 +1161,17 @@ public: void PostMessageToParent(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { PostMessageToParentInternal(aCx, aMessage, aTransferable, aRv); } void - PostMessageToParentMessagePort( - JSContext* aCx, - JS::Handle aMessage, - const Sequence& aTransferable, - ErrorResult& aRv); + PostMessageToParentMessagePort(JSContext* aCx, + JS::Handle aMessage, + const Sequence& aTransferable, + ErrorResult& aRv); void EnterDebuggerEventLoop(); @@ -1471,7 +1470,7 @@ private: void PostMessageToParentInternal(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); void diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 3b9215a8e9..5469b876c7 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -535,7 +535,7 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx, void DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv) { mWorkerPrivate->AssertIsOnWorkerThread(); diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index a8062298e9..8c41d5d279 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -215,7 +215,7 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Sequence& aTransferable, + const Sequence& aTransferable, ErrorResult& aRv); IMPL_EVENT_HANDLER(message) From fd982fd29816d75f2c5602262e804a970c935f15 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 15:55:27 +0800 Subject: [PATCH 03/10] Issue #2197 - Part 2a: Implement StructuredSerializeOptions for MessagePort Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1502802 --- dom/messagechannel/MessagePort.cpp | 8 ++++++++ dom/messagechannel/MessagePort.h | 6 ++++++ dom/webidl/MessagePort.webidl | 9 ++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dom/messagechannel/MessagePort.cpp b/dom/messagechannel/MessagePort.cpp index a63c84b2b0..5fbd1e9bb9 100644 --- a/dom/messagechannel/MessagePort.cpp +++ b/dom/messagechannel/MessagePort.cpp @@ -495,6 +495,14 @@ MessagePort::PostMessage(JSContext* aCx, mActor->SendPostMessages(messages); } +void +MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessage(aCx, aMessage, aOptions.mTransfer, aRv); +} + void MessagePort::Start() { diff --git a/dom/messagechannel/MessagePort.h b/dom/messagechannel/MessagePort.h index e635c532a3..b832872e1f 100644 --- a/dom/messagechannel/MessagePort.h +++ b/dom/messagechannel/MessagePort.h @@ -26,6 +26,7 @@ class MessagePortIdentifier; class MessagePortMessage; class PostMessageRunnable; class SharedMessagePortMessage; +struct StructuredSerializeOptions; namespace workers { class WorkerHolder; @@ -65,6 +66,11 @@ public: const Sequence& aTransferable, ErrorResult& aRv); + void + PostMessage(JSContext* aCx, JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); + void Start(); void Close(); diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl index 6495b5616d..0b36c47d94 100644 --- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -10,7 +10,9 @@ [Exposed=(Window,Worker,System)] interface MessagePort : EventTarget { [Throws] - void postMessage(any message, optional sequence transferable = []); + void postMessage(any message, sequence transferable); + [Throws] + void postMessage(any message, optional StructuredSerializeOptions options); void start(); void close(); @@ -19,3 +21,8 @@ interface MessagePort : EventTarget { attribute EventHandler onmessage; }; // MessagePort implements Transferable; + +// Used to declare which objects should be transferred. +dictionary StructuredSerializeOptions { + sequence transfer = []; +}; \ No newline at end of file From 158784cbedea222187f13b5964b248f48abace7f Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 16:30:32 +0800 Subject: [PATCH 04/10] Issue #2197 - Part 2b: Implement StructuredSerializeOptions for Worker Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1502802 --- dom/webidl/DedicatedWorkerGlobalScope.webidl | 4 +++- dom/webidl/Worker.webidl | 4 +++- dom/workers/SharedWorker.cpp | 10 ++++++++++ dom/workers/SharedWorker.h | 6 ++++++ dom/workers/WorkerPrivate.cpp | 11 +++++++++++ dom/workers/WorkerPrivate.h | 7 +++++++ dom/workers/WorkerScope.cpp | 9 +++++++++ dom/workers/WorkerScope.h | 7 +++++++ 8 files changed, 56 insertions(+), 2 deletions(-) diff --git a/dom/webidl/DedicatedWorkerGlobalScope.webidl b/dom/webidl/DedicatedWorkerGlobalScope.webidl index ad3125fa31..80c7c8decb 100644 --- a/dom/webidl/DedicatedWorkerGlobalScope.webidl +++ b/dom/webidl/DedicatedWorkerGlobalScope.webidl @@ -16,7 +16,9 @@ Exposed=DedicatedWorker] interface DedicatedWorkerGlobalScope : WorkerGlobalScope { [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, sequence transfer); + [Throws] + void postMessage(any message, optional StructuredSerializeOptions options); attribute EventHandler onmessage; }; diff --git a/dom/webidl/Worker.webidl b/dom/webidl/Worker.webidl index 44f406d8ce..c13357cd7e 100644 --- a/dom/webidl/Worker.webidl +++ b/dom/webidl/Worker.webidl @@ -19,7 +19,9 @@ interface Worker : EventTarget { void terminate(); [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, sequence transfer); + [Throws] + void postMessage(any message, optional StructuredSerializeOptions options); attribute EventHandler onmessage; }; diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 03c45c96a1..2fae19f291 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -22,6 +22,7 @@ using mozilla::dom::Optional; using mozilla::dom::Sequence; using mozilla::dom::MessagePort; +using mozilla::dom::StructuredSerializeOptions; using namespace mozilla; USING_WORKERS_NAMESPACE @@ -152,6 +153,15 @@ SharedWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv); } +void +SharedWorker::PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessage(aCx, aMessage, aOptions.mTransfer, aRv); +} + NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper) diff --git a/dom/workers/SharedWorker.h b/dom/workers/SharedWorker.h index 6b328811d5..e85fc2609a 100644 --- a/dom/workers/SharedWorker.h +++ b/dom/workers/SharedWorker.h @@ -98,6 +98,12 @@ private: JS::Handle aMessage, const Sequence& aTransferable, ErrorResult& aRv); + + void + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); }; END_WORKERS_NAMESPACE diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 2c3d439bd8..a7a4929f3b 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3079,6 +3079,17 @@ WorkerPrivateParent::PostMessage( PostMessageInternal(aCx, aMessage, aTransferable, nullptr, nullptr, aRv); } +template +void +WorkerPrivateParent::PostMessage( + JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessageInternal(aCx, aMessage, aOptions.mTransfer, nullptr, nullptr, aRv); +} + template void WorkerPrivateParent::PostMessageToServiceWorker( diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index cf1a3c22fc..0a71420047 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -68,6 +68,7 @@ class PromiseNativeHandler; class StructuredCloneHolder; class WorkerDebuggerGlobalScope; class WorkerGlobalScope; +struct StructuredSerializeOptions; } // namespace dom namespace ipc { class PrincipalInfo; @@ -403,6 +404,12 @@ public: const Sequence& aTransferable, ErrorResult& aRv); + void + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); + void PostMessageToServiceWorker(JSContext* aCx, JS::Handle aMessage, const Sequence& aTransferable, diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 5469b876c7..4019123c0b 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -542,6 +542,15 @@ DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx, mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv); } +void +DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessage(aCx, aMessage, aOptions.mTransfer, aRv); +} + SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsCString& aName) : WorkerGlobalScope(aWorkerPrivate), mName(aName) diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 8c41d5d279..2b055038fc 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -24,6 +24,7 @@ class Function; class IDBFactory; enum class ImageBitmapFormat : uint32_t; class Performance; +struct StructuredSerializeOptions; class Promise; class RequestOrUSVString; class ServiceWorkerRegistration; @@ -218,6 +219,12 @@ public: const Sequence& aTransferable, ErrorResult& aRv); + void + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); + IMPL_EVENT_HANDLER(message) }; From 4d58139fe16baf7aa8742a2a6605890fa39da58d Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 16:39:41 +0800 Subject: [PATCH 05/10] Issue #2197 - Part 2c: Implement StructuredSerializeOptions for ServiceWorker Partially based on https://bugzilla.mozilla.org/show_bug.cgi?id=1502802 --- dom/webidl/Client.webidl | 4 +++- dom/webidl/ServiceWorker.webidl | 4 +++- dom/workers/ServiceWorker.cpp | 10 ++++++++++ dom/workers/ServiceWorker.h | 8 ++++++++ dom/workers/ServiceWorkerClient.cpp | 9 +++++++++ dom/workers/ServiceWorkerClient.h | 6 ++++++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/dom/webidl/Client.webidl b/dom/webidl/Client.webidl index 7abb65ab12..c961c2b31f 100644 --- a/dom/webidl/Client.webidl +++ b/dom/webidl/Client.webidl @@ -15,7 +15,9 @@ interface Client { readonly attribute DOMString id; [Throws] - void postMessage(any message, optional sequence transfer = []); + void postMessage(any message, sequence transferable); + [Throws] + void postMessage(any message, optional StructuredSerializeOptions options); }; [Exposed=ServiceWorker] diff --git a/dom/webidl/ServiceWorker.webidl b/dom/webidl/ServiceWorker.webidl index 6dab46a16b..ff80fafc21 100644 --- a/dom/webidl/ServiceWorker.webidl +++ b/dom/webidl/ServiceWorker.webidl @@ -20,7 +20,9 @@ interface ServiceWorker : EventTarget { attribute EventHandler onstatechange; [Throws] - void postMessage(any message, optional sequence transferable = []); + void postMessage(any message, sequence transferable); + [Throws] + void postMessage(any message, optional StructuredSerializeOptions options); }; ServiceWorker implements AbstractWorker; diff --git a/dom/workers/ServiceWorker.cpp b/dom/workers/ServiceWorker.cpp index 87b86c4805..f2a39ea9c2 100644 --- a/dom/workers/ServiceWorker.cpp +++ b/dom/workers/ServiceWorker.cpp @@ -14,6 +14,7 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" #ifdef XP_WIN @@ -97,6 +98,15 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle aMessage, aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, Move(clientInfo)); } +void +ServiceWorker::PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessage(aCx, aMessage, aOptions.mTransfer, aRv); +} + } // namespace workers } // namespace dom } // namespace mozilla diff --git a/dom/workers/ServiceWorker.h b/dom/workers/ServiceWorker.h index d85d055aab..eb14fc4293 100644 --- a/dom/workers/ServiceWorker.h +++ b/dom/workers/ServiceWorker.h @@ -15,6 +15,8 @@ class nsPIDOMWindowInner; namespace mozilla { namespace dom { +struct StructuredSerializeOptions; + namespace workers { class ServiceWorkerInfo; @@ -66,6 +68,12 @@ public: const Sequence& aTransferable, ErrorResult& aRv); + void + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); + private: // This class can only be created from ServiceWorkerInfo::GetOrCreateInstance(). ServiceWorker(nsPIDOMWindowInner* aWindow, ServiceWorkerInfo* aInfo); diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp index eb4e676ffa..e8b8341e21 100644 --- a/dom/workers/ServiceWorkerClient.cpp +++ b/dom/workers/ServiceWorkerClient.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/Navigator.h" #include "mozilla/dom/ServiceWorkerMessageEvent.h" #include "mozilla/dom/ServiceWorkerMessageEventBinding.h" +#include "mozilla/dom/MessagePortBinding.h" #include "nsGlobalWindow.h" #include "nsIBrowserDOMWindow.h" #include "nsIDocument.h" @@ -220,3 +221,11 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, } } +void +ServiceWorkerClient::PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv) +{ + PostMessage(aCx, aMessage, aOptions.mTransfer, aRv); +} diff --git a/dom/workers/ServiceWorkerClient.h b/dom/workers/ServiceWorkerClient.h index 4d8759c408..7f89ee611a 100644 --- a/dom/workers/ServiceWorkerClient.h +++ b/dom/workers/ServiceWorkerClient.h @@ -94,6 +94,12 @@ public: const Sequence& aTransferable, ErrorResult& aRv); + void + PostMessage(JSContext* aCx, + JS::Handle aMessage, + const StructuredSerializeOptions& aOptions, + ErrorResult& aRv); + JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; protected: From 4174037d8a39b465ccd8afd91632596dc26a9a1d Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 16:02:34 +0800 Subject: [PATCH 06/10] Issue #2197 - Part 2d: Implement PostMessageOptions for Window Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1502802 --- dom/base/nsGlobalWindow.cpp | 11 +++++++++++ dom/base/nsGlobalWindow.h | 6 ++++++ .../mochitest/whatwg/test_postMessage_origin.xhtml | 7 ------- dom/webidl/Window.webidl | 6 ++++++ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 7c0256a2b7..c2aa8137f6 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -8904,6 +8904,17 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, aSubjectPrincipal, aRv); } +void +nsGlobalWindow::PostMessageMoz(JSContext* aCx, + JS::Handle aMessage, + const WindowPostMessageOptions& aOptions, + nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) +{ + PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, aOptions.mTransfer, + aSubjectPrincipal, aRv); +} + class nsCloseEvent : public Runnable { RefPtr mWindow; diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 8c961e2014..9a97a5e92a 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -135,6 +135,7 @@ class TabGroup; class Timeout; class U2F; class WakeLock; +struct WindowPostMessageOptions; class Worklet; namespace cache { class CacheStorage; @@ -936,6 +937,11 @@ public: const mozilla::dom::Sequence& aTransfer, nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aRv); + void PostMessageMoz(JSContext* aCx, + JS::Handle aMessage, + const mozilla::dom::WindowPostMessageOptions& aOptions, + nsIPrincipal& aSubjectPrincipal, + mozilla::ErrorResult& aError); int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction, int32_t aTimeout, const mozilla::dom::Sequence& aArguments, diff --git a/dom/tests/mochitest/whatwg/test_postMessage_origin.xhtml b/dom/tests/mochitest/whatwg/test_postMessage_origin.xhtml index f6a9198968..e48bee136d 100644 --- a/dom/tests/mochitest/whatwg/test_postMessage_origin.xhtml +++ b/dom/tests/mochitest/whatwg/test_postMessage_origin.xhtml @@ -383,13 +383,6 @@ var tests = hasWrongReturnOriginBug: true }, - // 55 - { - args: ["NOT-RECEIVED", undefined], - source: "sameDomain", - name: "SyntaxError", - code: DOMException.SYNTAX_ERR - }, ]; function allTests(callback) diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 73d5843a16..59cc9689c2 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -80,6 +80,8 @@ interface nsIDOMCrypto; [Throws, CrossOriginCallable, NeedsSubjectPrincipal] void postMessage(any message, DOMString targetOrigin, optional sequence transfer = []); + [Throws, CrossOriginCallable, NeedsSubjectPrincipal] + void postMessage(any message, optional WindowPostMessageOptions options); // also has obsolete members }; @@ -485,3 +487,7 @@ callback IdleRequestCallback = void (IdleDeadline deadline); partial interface Window { [ChromeOnly] readonly attribute boolean isSecureContextIfOpenerIgnored; }; + +dictionary WindowPostMessageOptions : StructuredSerializeOptions { + USVString targetOrigin = "/"; +}; From ef6b8db1d57c589ed570bb1b0401f1626f828cf1 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 15:50:18 +0800 Subject: [PATCH 07/10] Issue #2197 - Part 3: Implement self.structuredClone() Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1722576 --- dom/base/nsGlobalWindow.cpp | 42 +++++++++++++++++++++ dom/base/nsGlobalWindow.h | 4 ++ dom/webidl/WindowOrWorkerGlobalScope.webidl | 4 ++ dom/workers/WorkerScope.cpp | 40 ++++++++++++++++++++ dom/workers/WorkerScope.h | 5 +++ 5 files changed, 95 insertions(+) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index c2aa8137f6..1000f89a70 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -192,6 +192,7 @@ #include "mozilla/dom/IDBFactory.h" #include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/MessagePort.h" #ifdef MOZ_GAMEPAD #include "mozilla/dom/Gamepad.h" @@ -14644,6 +14645,47 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage, } } +// https://html.spec.whatwg.org/#structured-cloning +void +nsGlobalWindow::StructuredClone(JSContext* aCx, + JS::Handle aValue, + const StructuredSerializeOptions& aOptions, + JS::MutableHandle aRetval, + ErrorResult& aError) +{ + JS::Rooted transferArray(aCx, JS::UndefinedValue()); + aError = nsContentUtils::CreateJSValueFromSequenceOfObject( + aCx, aOptions.mTransfer, &transferArray); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + // FIXME: Uncomment once bug 1609990 and bug 1611855 lands. + //JS::CloneDataPolicy clonePolicy; + //clonePolicy.allowIntraClusterClonableSharedObjects(); + //clonePolicy.allowSharedMemoryObjects(); + + StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, + StructuredCloneHolder::TransferringSupported, + JS::StructuredCloneScope::SameProcessDifferentThread); + holder.Write(aCx, aValue, transferArray, clonePolicy, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + // TODO: Stop casting to nsISupports once bug 1585284 lands. + nsISupports* windowAsSupports = static_cast(this); + // TODO: Pass clonePolicy. + //holder.Read(this, aCx, aRetval, clonePolicy, aError); + holder.Read(windowAsSupports, aCx, aRetval, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + nsTArray> ports = holder.TakeTransferredPorts(); + Unused << ports; +} + // Helper called by methods that move/resize the window, // to ensure the presContext (if any) is aware of resolution // change that may happen in multi-monitor configuration. diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 9a97a5e92a..141a14e727 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1183,6 +1183,10 @@ public: const mozilla::dom::Sequence& aLayout, mozilla::ErrorResult& aRv); + void StructuredClone(JSContext* aCx, JS::Handle aValue, + const mozilla::dom::StructuredSerializeOptions& aOptions, + JS::MutableHandle aRetval, + mozilla::ErrorResult& aError); // ChromeWindow bits. Do NOT call these unless your window is in // fact an nsGlobalChromeWindow. diff --git a/dom/webidl/WindowOrWorkerGlobalScope.webidl b/dom/webidl/WindowOrWorkerGlobalScope.webidl index 652a46ffcb..9e639db5f4 100644 --- a/dom/webidl/WindowOrWorkerGlobalScope.webidl +++ b/dom/webidl/WindowOrWorkerGlobalScope.webidl @@ -44,6 +44,10 @@ interface WindowOrWorkerGlobalScope { Promise createImageBitmap(ImageBitmapSource aImage); [Throws] Promise createImageBitmap(ImageBitmapSource aImage, long aSx, long aSy, long aSw, long aSh); + + // structured cloning + [Throws] + any structuredClone(any value, optional StructuredSerializeOptions options); }; // https://fetch.spec.whatwg.org/#fetch-method diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 4019123c0b..1c49e38f18 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -7,6 +7,7 @@ #include "jsapi.h" #include "mozilla/EventListenerManager.h" +#include "mozilla/Unused.h" #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/Console.h" #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h" @@ -492,6 +493,45 @@ WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage, } } +// https://html.spec.whatwg.org/#structured-cloning +void WorkerGlobalScope::StructuredClone(JSContext* aCx, + JS::Handle aValue, + const StructuredSerializeOptions& aOptions, + JS::MutableHandle aRetval, + ErrorResult& aError) { + JS::Rooted transferArray(aCx, JS::UndefinedValue()); + aError = nsContentUtils::CreateJSValueFromSequenceOfObject( + aCx, aOptions.mTransfer, &transferArray); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + // FIXME: Uncomment once bug 1609990 and bug 1611855 lands. + //JS::CloneDataPolicy clonePolicy; + //clonePolicy.allowIntraClusterClonableSharedObjects(); + //clonePolicy.allowSharedMemoryObjects(); + + StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, + StructuredCloneHolder::TransferringSupported, + JS::StructuredCloneScope::SameProcessDifferentThread); + holder.Write(aCx, aValue, transferArray, clonePolicy, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + // TODO: Stop casting to nsISupports once bug 1585284 lands. + nsISupports* workerAsSupports = static_cast(this); + // TODO: Pass clonePolicy. + //holder.Read(this, aCx, aRetval, clonePolicy, aError); + holder.Read(workerAsSupports, aCx, aRetval, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + nsTArray> ports = holder.TakeTransferredPorts(); + Unused << ports; +} + DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate) : WorkerGlobalScope(aWorkerPrivate) { diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 2b055038fc..31b4d6d850 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -183,6 +183,11 @@ public: const mozilla::dom::Sequence& aLayout, mozilla::ErrorResult& aRv); + void StructuredClone(JSContext* aCx, JS::Handle aValue, + const StructuredSerializeOptions& aOptions, + JS::MutableHandle aRetval, + ErrorResult& aError); + bool WindowInteractionAllowed() const { From bbcfb62753bcb16494d90d79a03b7e050ef93ef4 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 21:45:15 +0800 Subject: [PATCH 08/10] Issue #2197 - Part 4: Expose structuredClone in Sandbox Partially based on https://bugzilla.mozilla.org/show_bug.cgi?id=1734320 --- dom/base/nsContentUtils.cpp | 39 ++++++++++++++++ dom/base/nsContentUtils.h | 13 ++++++ dom/base/nsGlobalWindow.cpp | 35 +-------------- dom/base/nsGlobalWindow.h | 2 +- dom/workers/WorkerScope.cpp | 34 +------------- dom/workers/WorkerScope.h | 2 +- js/xpconnect/src/Sandbox.cpp | 44 +++++++++++++++++++ js/xpconnect/src/xpcprivate.h | 1 + .../tests/unit/test_structuredClone.js | 25 +++++++++++ js/xpconnect/tests/unit/xpcshell.ini | 1 + 10 files changed, 129 insertions(+), 67 deletions(-) create mode 100644 js/xpconnect/tests/unit/test_structuredClone.js diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index ded37bd4c8..50cc781efc 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -47,6 +47,7 @@ #include "mozilla/dom/HTMLTemplateElement.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/dom/ipc/BlobParent.h" +#include "mozilla/dom/MessagePort.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TabParent.h" @@ -10023,3 +10024,41 @@ nsContentUtils::CreateJSValueFromSequenceOfObject(JSContext* aCx, aValue.setObject(*array); return NS_OK; } + +/* static */ +void nsContentUtils::StructuredClone(JSContext* aCx, + nsIGlobalObject* aGlobal, + JS::Handle aValue, + const StructuredSerializeOptions& aOptions, + JS::MutableHandle aRv, + ErrorResult& aError) { + JS::Rooted transferArray(aCx, JS::UndefinedValue()); + aError = nsContentUtils::CreateJSValueFromSequenceOfObject( + aCx, aOptions.mTransfer, &transferArray); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + JS::CloneDataPolicy clonePolicy; + // FIXME: Uncomment once bug 1609990 and bug 1611855 lands. + //clonePolicy.allowIntraClusterClonableSharedObjects(); + //clonePolicy.allowSharedMemoryObjects(); + + StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, + StructuredCloneHolder::TransferringSupported, + JS::StructuredCloneScope::SameProcessDifferentThread); + holder.Write(aCx, aValue, transferArray, clonePolicy, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + // TODO: Pass clonePolicy. + //holder.Read(this, aCx, aRv, clonePolicy, aError); + holder.Read(aGlobal, aCx, aRv, aError); + if (NS_WARN_IF(aError.Failed())) { + return; + } + + nsTArray> ports = holder.TakeTransferredPorts(); + Unused << ports; +} diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 62f8451555..c0e44b3be4 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -132,6 +132,7 @@ class nsIContentParent; class TabChild; class Selection; class TabParent; +struct StructuredSerializeOptions; } // namespace dom namespace ipc { @@ -2817,6 +2818,18 @@ public: const mozilla::dom::Sequence& aTransfer, JS::MutableHandle aValue); + /** + * This implements the structured cloning algorithm as described by + * https://html.spec.whatwg.org/#structured-cloning. + */ + static void + StructuredClone(JSContext* aCx, + nsIGlobalObject* aGlobal, + JS::Handle aValue, + const mozilla::dom::StructuredSerializeOptions& aOptions, + JS::MutableHandle aRv, + mozilla::ErrorResult& aError); + private: static bool InitializeEventTable(); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 1000f89a70..b53ad29769 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -192,7 +192,6 @@ #include "mozilla/dom/IDBFactory.h" #include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/Promise.h" -#include "mozilla/dom/MessagePort.h" #ifdef MOZ_GAMEPAD #include "mozilla/dom/Gamepad.h" @@ -14650,40 +14649,10 @@ void nsGlobalWindow::StructuredClone(JSContext* aCx, JS::Handle aValue, const StructuredSerializeOptions& aOptions, - JS::MutableHandle aRetval, + JS::MutableHandle aRv, ErrorResult& aError) { - JS::Rooted transferArray(aCx, JS::UndefinedValue()); - aError = nsContentUtils::CreateJSValueFromSequenceOfObject( - aCx, aOptions.mTransfer, &transferArray); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - // FIXME: Uncomment once bug 1609990 and bug 1611855 lands. - //JS::CloneDataPolicy clonePolicy; - //clonePolicy.allowIntraClusterClonableSharedObjects(); - //clonePolicy.allowSharedMemoryObjects(); - - StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, - StructuredCloneHolder::TransferringSupported, - JS::StructuredCloneScope::SameProcessDifferentThread); - holder.Write(aCx, aValue, transferArray, clonePolicy, aError); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - // TODO: Stop casting to nsISupports once bug 1585284 lands. - nsISupports* windowAsSupports = static_cast(this); - // TODO: Pass clonePolicy. - //holder.Read(this, aCx, aRetval, clonePolicy, aError); - holder.Read(windowAsSupports, aCx, aRetval, aError); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - nsTArray> ports = holder.TakeTransferredPorts(); - Unused << ports; + nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRv, aError); } // Helper called by methods that move/resize the window, diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 141a14e727..bc989ea2e4 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1185,7 +1185,7 @@ public: void StructuredClone(JSContext* aCx, JS::Handle aValue, const mozilla::dom::StructuredSerializeOptions& aOptions, - JS::MutableHandle aRetval, + JS::MutableHandle aRv, mozilla::ErrorResult& aError); // ChromeWindow bits. Do NOT call these unless your window is in diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 1c49e38f18..637e441732 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -497,39 +497,9 @@ WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage, void WorkerGlobalScope::StructuredClone(JSContext* aCx, JS::Handle aValue, const StructuredSerializeOptions& aOptions, - JS::MutableHandle aRetval, + JS::MutableHandle aRv, ErrorResult& aError) { - JS::Rooted transferArray(aCx, JS::UndefinedValue()); - aError = nsContentUtils::CreateJSValueFromSequenceOfObject( - aCx, aOptions.mTransfer, &transferArray); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - // FIXME: Uncomment once bug 1609990 and bug 1611855 lands. - //JS::CloneDataPolicy clonePolicy; - //clonePolicy.allowIntraClusterClonableSharedObjects(); - //clonePolicy.allowSharedMemoryObjects(); - - StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, - StructuredCloneHolder::TransferringSupported, - JS::StructuredCloneScope::SameProcessDifferentThread); - holder.Write(aCx, aValue, transferArray, clonePolicy, aError); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - // TODO: Stop casting to nsISupports once bug 1585284 lands. - nsISupports* workerAsSupports = static_cast(this); - // TODO: Pass clonePolicy. - //holder.Read(this, aCx, aRetval, clonePolicy, aError); - holder.Read(workerAsSupports, aCx, aRetval, aError); - if (NS_WARN_IF(aError.Failed())) { - return; - } - - nsTArray> ports = holder.TakeTransferredPorts(); - Unused << ports; + nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRv, aError); } DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate) diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 31b4d6d850..01bae5cc11 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -185,7 +185,7 @@ public: void StructuredClone(JSContext* aCx, JS::Handle aValue, const StructuredSerializeOptions& aOptions, - JS::MutableHandle aRetval, + JS::MutableHandle aRv, ErrorResult& aError); bool diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index b8a4859a46..c3b740e7e5 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -326,6 +326,45 @@ SandboxCreateFetch(JSContext* cx, HandleObject obj) dom::HeadersBinding::GetConstructorObject(cx); } +static bool SandboxStructuredClone(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + if (!args.requireAtLeast(cx, "structuredClone", 1)) { + return false; + } + + RootedDictionary options(cx); + if (!options.Init(cx, args.hasDefined(1) ? args[1] : JS::NullHandleValue, + "Argument 2", false)) { + return false; + } + + nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx)); + if (!global) { + JS_ReportErrorASCII(cx, "structuredClone: Missing global"); + return false; + } + + JS::Rooted result(cx); + ErrorResult rv; + nsContentUtils::StructuredClone(cx, global, args[0], options, &result, rv); + if (rv.MaybeSetPendingException(cx)) { + return false; + } + + MOZ_ASSERT_IF(result.isGCThing(), + !JS::GCThingIsMarkedGray(result.toGCCellPtr())); + args.rval().set(result); + return true; +} + +static bool SandboxCreateStructuredClone(JSContext* cx, HandleObject obj) { + MOZ_ASSERT(JS_IsGlobalObject(obj)); + + return JS_DefineFunction(cx, obj, "structuredClone", SandboxStructuredClone, + 1, 0); +} + static bool SandboxIsProxy(JSContext* cx, unsigned argc, Value* vp) { @@ -931,6 +970,8 @@ xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) #endif } else if (!strcmp(name.ptr(), "fetch")) { fetch = true; + } else if (!strcmp(name.ptr(), "structuredClone")) { + structuredClone = true; } else if (!strcmp(name.ptr(), "caches")) { caches = true; } else if (!strcmp(name.ptr(), "FileReader")) { @@ -1006,6 +1047,9 @@ xpc::GlobalProperties::Define(JSContext* cx, JS::HandleObject obj) if (fetch && !SandboxCreateFetch(cx, obj)) return false; + if (structuredClone && !SandboxCreateStructuredClone(cx, obj)) + return false; + if (caches && !dom::cache::CacheStorage::DefineCaches(cx, obj)) return false; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 724c8db3a9..6c2711210a 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2879,6 +2879,7 @@ struct GlobalProperties { bool crypto : 1; bool rtcIdentityProvider : 1; bool fetch : 1; + bool structuredClone : 1; bool caches : 1; bool fileReader: 1; private: diff --git a/js/xpconnect/tests/unit/test_structuredClone.js b/js/xpconnect/tests/unit/test_structuredClone.js new file mode 100644 index 0000000000..6b9b2d776a --- /dev/null +++ b/js/xpconnect/tests/unit/test_structuredClone.js @@ -0,0 +1,25 @@ +function run_test() { + var sb = new Cu.Sandbox('http://www.example.com', + { wantGlobalProperties: ["structuredClone"] }); + + sb.equal = equal; + + sb.testing = Components.utils.cloneInto({xyz: 123}, sb); + Cu.evalInSandbox(` + equal(structuredClone("abc"), "abc"); + + var obj = {a: 1}; + obj.self = obj; + var clone = structuredClone(obj); + equal(clone.a, 1); + equal(clone.self, clone); + + var ab = new ArrayBuffer(1); + clone = structuredClone(ab, {transfer: [ab]}); + equal(clone.byteLength, 1); + equal(ab.byteLength, 0); + + clone = structuredClone(testing); + equal(clone.xyz, 123); + `, sb); +} diff --git a/js/xpconnect/tests/unit/xpcshell.ini b/js/xpconnect/tests/unit/xpcshell.ini index 12648d3ecc..b13d8d455f 100644 --- a/js/xpconnect/tests/unit/xpcshell.ini +++ b/js/xpconnect/tests/unit/xpcshell.ini @@ -114,6 +114,7 @@ skip-if = os == "android" # native test components aren't available on Android [test_css.js] [test_rtcIdentityProvider.js] [test_sandbox_atob.js] +[test_structuredClone.js] [test_isProxy.js] [test_getObjectPrincipal.js] [test_sandbox_name.js] From 8e6d7304638fb1b7500f5ce8a5f2f4716ddbefed Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sat, 8 Apr 2023 08:13:48 +0800 Subject: [PATCH 09/10] Issue #2197 - Follow-up: Remove GC debug assertion on sandbox There's no way to access GC from here. --- js/xpconnect/src/Sandbox.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index c3b740e7e5..9e46f2dae0 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -352,8 +352,6 @@ static bool SandboxStructuredClone(JSContext* cx, unsigned argc, Value* vp) { return false; } - MOZ_ASSERT_IF(result.isGCThing(), - !JS::GCThingIsMarkedGray(result.toGCCellPtr())); args.rval().set(result); return true; } From 31283d993ba169f90cfad66d772bf119a9dede75 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sun, 26 Mar 2023 18:34:04 +0800 Subject: [PATCH 10/10] Issue #595 - Implement window.event This MSIE extension is still technically part of the standard*, although its use is discouraged. This API will also likely never go away based on some comments at this issue on MDN content**. Note that this uses a different approach for getting the inner window. * https://dom.spec.whatwg.org/#interface-window-extensions ** https://github.com/mdn/content/issues/21848 Spec PR: https://github.com/whatwg/dom/pull/407 Spec discussion: https://github.com/whatwg/dom/issues/334 Partially based on https://bugzilla.mozilla.org/show_bug.cgi?id=218415 --- dom/base/FragmentOrElement.cpp | 4 +++ dom/base/nsGlobalWindow.cpp | 13 ++++++++- dom/base/nsGlobalWindow.h | 1 + dom/base/nsPIDOMWindow.h | 15 ++++++++++ dom/events/EventDispatcher.cpp | 15 +++++++++- dom/events/EventDispatcher.h | 8 ++++++ dom/events/EventListenerManager.cpp | 44 ++++++++++++++++++++++++++++- dom/events/EventListenerManager.h | 12 ++++++-- dom/webidl/Window.webidl | 1 + modules/libpref/init/all.js | 3 ++ 10 files changed, 110 insertions(+), 6 deletions(-) diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 38be731811..6aea6820ef 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -824,6 +824,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) aVisitor.mCanHandle = true; aVisitor.mMayHaveListenerManager = HasListenerManager(); + if (IsInShadowTree()) { + aVisitor.mItemInShadowTree = true; + } + // Don't propagate mouseover and mouseout events when mouse is moving // inside chrome access only content. bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree(); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index b53ad29769..c5ed38dc27 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -909,7 +909,8 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow) mOuterWindow(aOuterWindow), // Make sure no actual window ends up with mWindowID == 0 mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false), - mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false) + mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false), + mEvent(nullptr) {} template @@ -5245,6 +5246,16 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle aOpener, SetOpenerWindow(outer, false); } +void +nsGlobalWindow::GetEvent(JSContext* aCx, JS::MutableHandle aRetval) +{ + if (mEvent) { + Unused << nsContentUtils::WrapNative(aCx, mEvent, aRetval); + } else { + aRetval.setUndefined(); + } +} + void nsGlobalWindow::GetStatusOuter(nsAString& aStatus) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index bc989ea2e4..63bb574dd4 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -846,6 +846,7 @@ public: already_AddRefed GetOpener() override; void SetOpener(JSContext* aCx, JS::Handle aOpener, mozilla::ErrorResult& aError); + void GetEvent(JSContext* aCx, JS::MutableHandle aRetval); already_AddRefed GetParentOuter(); already_AddRefed GetParent(mozilla::ErrorResult& aError); already_AddRefed GetParent() override; diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 21eb4cff7f..ffebf6570d 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -194,6 +194,10 @@ protected: // we have what it takes to do so. void MaybeCreateDoc(); + // The event dispatch code sets and unsets this while keeping + // the event object alive. + nsIDOMEvent* mEvent; + public: inline bool IsLoadingOrRunningTimeout() const; @@ -789,6 +793,17 @@ public: return mInnerObjectsFreed; } + // Sets the event for window.event. Does NOT take ownership, so + // the caller is responsible for clearing the event before the + // event gets deallocated. Pass nullptr to set window.event to + // undefined. Returns the previous value. + nsIDOMEvent* SetEvent(nsIDOMEvent* aEvent) + { + nsIDOMEvent* old = mEvent; + mEvent = aEvent; + return old; + } + /** * Check whether this window is a secure context. */ diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index e2b5699241..001b458cf3 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -264,6 +264,16 @@ public: return mFlags.mRootOfClosedTree; } + void SetItemInShadowTree(bool aSet) + { + mFlags.mItemInShadowTree = aSet; + } + + bool IsItemInShadowTree() + { + return mFlags.mItemInShadowTree; + } + void SetIsSlotInClosedTree(bool aSet) { mFlags.mIsSlotInClosedTree = aSet; @@ -351,7 +361,8 @@ public: mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent, &aVisitor.mDOMEvent, CurrentTarget(), - &aVisitor.mEventStatus); + &aVisitor.mEventStatus, + IsItemInShadowTree()); NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr, "CurrentTarget should be null!"); } @@ -384,6 +395,7 @@ private: bool mWantsPreHandleEvent : 1; bool mPreHandleEventOnly : 1; bool mRootOfClosedTree : 1; + bool mItemInShadowTree : 1; bool mIsSlotInClosedTree : 1; bool mIsChromeHandler : 1; private: @@ -433,6 +445,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor) SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent); SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle); SetRootOfClosedTree(aVisitor.mRootOfClosedTree); + SetItemInShadowTree(aVisitor.mItemInShadowTree); SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget); mItemFlags = aVisitor.mItemFlags; mItemData = aVisitor.mItemData; diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h index 403c472c5c..9eaa124137 100644 --- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -125,6 +125,7 @@ public: , mMayHaveListenerManager(true) , mWantsPreHandleEvent(false) , mRootOfClosedTree(false) + , mItemInShadowTree(false) , mParentIsSlotInClosedTree(false) , mParentIsChromeHandler(false) , mRelatedTargetRetargetedInCurrentScope(false) @@ -147,6 +148,7 @@ public: mMayHaveListenerManager = true; mWantsPreHandleEvent = false; mRootOfClosedTree = false; + mItemInShadowTree = false; mParentIsSlotInClosedTree = false; mParentIsChromeHandler = false; // Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly, @@ -236,6 +238,12 @@ public: */ bool mRootOfClosedTree; + /** + * If target is node and its root is a shadow root. + * https://dom.spec.whatwg.org/#event-path-item-in-shadow-tree + */ + bool mItemInShadowTree; + /** * True if mParentTarget is HTMLSlotElement in a closed shadow tree and the * current target is assigned to that slot. diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 221b464773..af268f24bb 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -1120,6 +1120,38 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const } } +already_AddRefed +EventListenerManager::WindowFromListener(Listener* aListener, + bool aItemInShadowTree) +{ + nsCOMPtr innerWindow; + if (!aItemInShadowTree) { + if (aListener->mListener.HasWebIDLCallback()) { + CallbackObject* callback = aListener->mListener.GetWebIDLCallback(); + nsGlobalWindow* win; + if (callback) { + // Find the real underlying callback. + JSObject* realCallback = + js::UncheckedUnwrap(callback->CallbackPreserveColor()); + // Get the global for this callback. + win = mIsMainThreadELM ? + xpc::WindowGlobalOrNull(realCallback) : + nullptr; + } + if (win && win->IsInnerWindow()) { + innerWindow = win->AsInner(); // Can be nullptr + } + } else { + // Can't get the global from + // listener->mListener.GetXPCOMCallback(). + // In most cases, it would be the same as for + // the target, so let's do that. + innerWindow = GetInnerWindowForTarget(); // Can be nullptr + } + } + return innerWindow.forget(); +} + /** * Causes a check for event listeners and processing by them if they exist. * @param an event listener @@ -1130,7 +1162,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext, WidgetEvent* aEvent, nsIDOMEvent** aDOMEvent, EventTarget* aCurrentTarget, - nsEventStatus* aEventStatus) + nsEventStatus* aEventStatus, + bool aItemInShadowTree) { //Set the value of the internal PreventDefault flag properly based on aEventStatus if (!aEvent->DefaultPrevented() && @@ -1222,9 +1255,18 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext, listener = listenerHolder.ptr(); hasRemovedListener = true; } + nsCOMPtr innerWindow = + WindowFromListener(listener, aItemInShadowTree); + nsIDOMEvent* oldWindowEvent = nullptr; + if (innerWindow) { + oldWindowEvent = innerWindow->SetEvent(*aDOMEvent); + } if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) { aEvent->mFlags.mExceptionWasRaised = true; } + if (innerWindow) { + Unused << innerWindow->SetEvent(oldWindowEvent); + } aEvent->mFlags.mInPassiveListener = false; if (needsEndEventMarker) { diff --git a/dom/events/EventListenerManager.h b/dom/events/EventListenerManager.h index 51373317d4..decd305f5e 100644 --- a/dom/events/EventListenerManager.h +++ b/dom/events/EventListenerManager.h @@ -350,7 +350,8 @@ public: WidgetEvent* aEvent, nsIDOMEvent** aDOMEvent, dom::EventTarget* aCurrentTarget, - nsEventStatus* aEventStatus) + nsEventStatus* aEventStatus, + bool aItemInShadowTree) { if (mListeners.IsEmpty() || aEvent->PropagationStopped()) { return; @@ -371,7 +372,7 @@ public: return; } HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget, - aEventStatus); + aEventStatus, aItemInShadowTree); } /** @@ -482,7 +483,8 @@ protected: WidgetEvent* aEvent, nsIDOMEvent** aDOMEvent, dom::EventTarget* aCurrentTarget, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus, + bool aItemInShadowTree); nsresult HandleEventSubType(Listener* aListener, nsIDOMEvent* aDOMEvent, @@ -573,6 +575,10 @@ public: return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr; } +private: + already_AddRefed WindowFromListener(Listener* aListener, + bool aItemInShadowTree); + protected: /** * Helper method for implementing the various Get*EventHandler above. Will diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 59cc9689c2..2ba9f4f124 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -50,6 +50,7 @@ interface nsIDOMCrypto; [Throws] void stop(); [Throws, CrossOriginCallable, UnsafeInPrerendering] void focus(); [Throws, CrossOriginCallable] void blur(); + [Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event; // other browsing contexts [Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 51296a21ac..aad7c119d9 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5244,6 +5244,9 @@ pref("prompts.content_handling_dialog_modal.enabled", false); // Whether module scripts (