From ef6b8db1d57c589ed570bb1b0401f1626f828cf1 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Fri, 7 Apr 2023 15:50:18 +0800 Subject: [PATCH] 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 {