From 518cc7ad584693a4f00be28c8200c33363950a07 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Wed, 16 Aug 2023 12:06:34 +0000 Subject: [PATCH] Bug 1848875 - Throw InvalidStateError when cloning OffscreenCanvas with context. r=gfx-reviewers,lsalzman This patch makes us follow the standard and pass WPT tests regarding the cloning of OffscreenCanvas with a context. It also makes us throw a less generic message when attempting to clone an OffscreenCanvas that has already been cloned/transferred to a worker. Differential Revision: https://phabricator.services.mozilla.com/D186265 --- dom/base/StructuredCloneHolder.cpp | 7 ++--- dom/canvas/OffscreenCanvas.cpp | 26 ++++++++++++++++--- dom/canvas/OffscreenCanvas.h | 3 ++- .../offscreencanvas.transferrable.html.ini | 3 --- .../offscreencanvas.transferrable.w.html.ini | 8 ------ 5 files changed, 28 insertions(+), 19 deletions(-) delete mode 100644 testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html.ini delete mode 100644 testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index aa6af050b478..8040ad057b00 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -1472,16 +1472,17 @@ StructuredCloneHolder::CustomWriteTransferHandler( if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(canvas); - if (!canvas->MayNeuter()) { + UniquePtr clonedCanvas = + canvas->ToCloneData(aCx); + if (!clonedCanvas) { return false; } *aExtraData = 0; *aTag = SCTAG_DOM_CANVAS; - *aContent = canvas->ToCloneData(); + *aContent = clonedCanvas.release(); MOZ_ASSERT(*aContent); *aOwnership = JS::SCTAG_TMO_CUSTOM; - canvas->SetNeutered(); return true; } diff --git a/dom/canvas/OffscreenCanvas.cpp b/dom/canvas/OffscreenCanvas.cpp index df8fc96cb9f0..09e58fedff8c 100644 --- a/dom/canvas/OffscreenCanvas.cpp +++ b/dom/canvas/OffscreenCanvas.cpp @@ -305,10 +305,28 @@ void OffscreenCanvas::CommitFrameToCompositor() { mDisplay->CommitFrameToCompositor(mCurrentContext, mTextureType, update); } -OffscreenCanvasCloneData* OffscreenCanvas::ToCloneData() { - return new OffscreenCanvasCloneData(mDisplay, mWidth, mHeight, - mCompositorBackendType, mTextureType, - mNeutered, mIsWriteOnly, mExpandedReader); +UniquePtr OffscreenCanvas::ToCloneData( + JSContext* aCx) { + if (NS_WARN_IF(mNeutered)) { + ErrorResult rv; + rv.ThrowDataCloneError( + "Cannot clone placeholder canvas that is already transferred."); + MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(aCx)); + return nullptr; + } + + if (NS_WARN_IF(mCurrentContext)) { + ErrorResult rv; + rv.ThrowInvalidStateError("Cannot clone canvas with context."); + MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(aCx)); + return nullptr; + } + + auto cloneData = MakeUnique( + mDisplay, mWidth, mHeight, mCompositorBackendType, mTextureType, + mNeutered, mIsWriteOnly, mExpandedReader); + SetNeutered(); + return cloneData; } already_AddRefed OffscreenCanvas::TransferToImageBitmap( diff --git a/dom/canvas/OffscreenCanvas.h b/dom/canvas/OffscreenCanvas.h index 30f4ea5940e8..0e1fc682379c 100644 --- a/dom/canvas/OffscreenCanvas.h +++ b/dom/canvas/OffscreenCanvas.h @@ -15,6 +15,7 @@ #include "mozilla/layers/LayersTypes.h" #include "mozilla/Maybe.h" #include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" #include "nsCycleCollectionParticipant.h" struct JSContext; @@ -124,7 +125,7 @@ class OffscreenCanvas final : public DOMEventTargetHelper, // on worker thread. static bool PrefEnabledOnWorkerThread(JSContext* aCx, JSObject* aObj); - OffscreenCanvasCloneData* ToCloneData(); + UniquePtr ToCloneData(JSContext* aCx); void UpdateDisplayData(const OffscreenCanvasDisplayData& aData); diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html.ini deleted file mode 100644 index 2269d23a1e8b..000000000000 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[offscreencanvas.transferrable.html] - [Test that transfer an OffscreenCanvas that already have a 2d context throws exception.] - expected: FAIL diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini deleted file mode 100644 index 1c6cb7cd8eb8..000000000000 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[offscreencanvas.transferrable.w.html] - expected: - if (os == "linux") and not debug and fission: [OK, CRASH] - [Test that transfer an OffscreenCanvas that has a webgl context throws exception in a worker.] - expected: FAIL - - [Test that transfer an OffscreenCanvas that has a 2d context throws exception in a worker.] - expected: FAIL