mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-25 16:59:01 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
20b787a4df
37 changed files with 523 additions and 153 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -9993,3 +9994,71 @@ nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement)
|
|||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsContentUtils::CreateJSValueFromSequenceOfObject(JSContext* aCx,
|
||||
const Sequence<JSObject*>& aTransfer,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
if (aTransfer.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> 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<JSObject*> 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;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsContentUtils::StructuredClone(JSContext* aCx,
|
||||
nsIGlobalObject* aGlobal,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
ErrorResult& aError) {
|
||||
JS::Rooted<JS::Value> 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<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
|
||||
Unused << ports;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ class nsIContentParent;
|
|||
class TabChild;
|
||||
class Selection;
|
||||
class TabParent;
|
||||
struct StructuredSerializeOptions;
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
|
|
@ -2812,6 +2813,23 @@ public:
|
|||
static bool
|
||||
IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
|
||||
|
||||
static nsresult
|
||||
CreateJSValueFromSequenceOfObject(JSContext* aCx,
|
||||
const mozilla::dom::Sequence<JSObject*>& aTransfer,
|
||||
JS::MutableHandle<JS::Value> 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<JS::Value> aValue,
|
||||
const mozilla::dom::StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
|
|
|||
|
|
@ -909,7 +909,8 @@ nsPIDOMWindow<T>::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<class T>
|
||||
|
|
@ -5245,6 +5246,16 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
|||
SetOpenerWindow(outer, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
if (mEvent) {
|
||||
Unused << nsContentUtils::WrapNative(aCx, mEvent, aRetval);
|
||||
} else {
|
||||
aRetval.setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
|
||||
{
|
||||
|
|
@ -8886,30 +8897,33 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
nsGlobalWindow::PostMessageMoz(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
const Optional<Sequence<JS::Value>>& aTransfer,
|
||||
const Sequence<JSObject*>& aTransfer,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aError)
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
|
||||
if (aTransfer.WasPassed()) {
|
||||
const Sequence<JS::Value >& values = aTransfer.Value();
|
||||
|
||||
// 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());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::PostMessageMoz(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const WindowPostMessageOptions& aOptions,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, aOptions.mTransfer,
|
||||
aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
class nsCloseEvent : public Runnable {
|
||||
|
|
@ -14641,6 +14655,17 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
|||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#structured-cloning
|
||||
void
|
||||
nsGlobalWindow::StructuredClone(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRv, aError);
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ class TabGroup;
|
|||
class Timeout;
|
||||
class U2F;
|
||||
class WakeLock;
|
||||
struct WindowPostMessageOptions;
|
||||
class Worklet;
|
||||
namespace cache {
|
||||
class CacheStorage;
|
||||
|
|
@ -845,6 +846,7 @@ public:
|
|||
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
|
||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
|
||||
|
|
@ -933,7 +935,12 @@ public:
|
|||
void Print(mozilla::ErrorResult& aError);
|
||||
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
|
||||
const mozilla::dom::Sequence<JSObject*>& aTransfer,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
mozilla::ErrorResult& aRv);
|
||||
void PostMessageMoz(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const mozilla::dom::WindowPostMessageOptions& aOptions,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
|
||||
|
|
@ -1177,6 +1184,10 @@ public:
|
|||
const mozilla::dom::Sequence<mozilla::dom::ChannelPixelLayout>& aLayout,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void StructuredClone(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
const mozilla::dom::StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
// ChromeWindow bits. Do NOT call these unless your window is in
|
||||
// fact an nsGlobalChromeWindow.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,38 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsPIDOMWindowInner>
|
||||
EventListenerManager::WindowFromListener(Listener* aListener,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> 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
|
||||
|
|
@ -1131,7 +1163,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() &&
|
||||
|
|
@ -1223,9 +1256,18 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
|||
listener = listenerHolder.ptr();
|
||||
hasRemovedListener = true;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowInner> 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) {
|
||||
|
|
|
|||
|
|
@ -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<nsPIDOMWindowInner> WindowFromListener(Listener* aListener,
|
||||
bool aItemInShadowTree);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Helper method for implementing the various Get*EventHandler above. Will
|
||||
|
|
|
|||
|
|
@ -394,52 +394,39 @@ MessagePort::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
}
|
||||
|
||||
void
|
||||
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
MessagePort::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// We *must* clone the data here, or the JS::Value could be modified
|
||||
// by script
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
// Here we want to check if the transerable object list contains
|
||||
// this port. No other checks are done.
|
||||
for (const JS::Value& value : realTransferable) {
|
||||
if (!value.isObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> 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(realTransferable.Length(),
|
||||
realTransferable.Elements());
|
||||
JS::Rooted<JSObject*> 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<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
|
||||
aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx,
|
||||
aTransferable,
|
||||
&transferable);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
|
||||
|
|
@ -508,6 +495,14 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
mActor->SendPostMessages(messages);
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
MessagePort::Start()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class MessagePortIdentifier;
|
|||
class MessagePortMessage;
|
||||
class PostMessageRunnable;
|
||||
class SharedMessagePortMessage;
|
||||
struct StructuredSerializeOptions;
|
||||
|
||||
namespace workers {
|
||||
class WorkerHolder;
|
||||
|
|
@ -62,7 +63,12 @@ public:
|
|||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void Start();
|
||||
|
|
|
|||
|
|
@ -383,13 +383,6 @@ var tests =
|
|||
|
||||
hasWrongReturnOriginBug: true
|
||||
},
|
||||
// 55
|
||||
{
|
||||
args: ["NOT-RECEIVED", undefined],
|
||||
source: "sameDomain",
|
||||
name: "SyntaxError",
|
||||
code: DOMException.SYNTAX_ERR
|
||||
},
|
||||
];
|
||||
|
||||
function allTests(callback)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ interface Client {
|
|||
readonly attribute DOMString id;
|
||||
|
||||
[Throws]
|
||||
void postMessage(any message, optional sequence<Transferable> transfer);
|
||||
void postMessage(any message, sequence<object> transferable);
|
||||
[Throws]
|
||||
void postMessage(any message, optional StructuredSerializeOptions options);
|
||||
};
|
||||
|
||||
[Exposed=ServiceWorker]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
Exposed=DedicatedWorker]
|
||||
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
||||
[Throws]
|
||||
void postMessage(any message, optional sequence<any> transfer);
|
||||
void postMessage(any message, sequence<object> transfer);
|
||||
[Throws]
|
||||
void postMessage(any message, optional StructuredSerializeOptions options);
|
||||
|
||||
attribute EventHandler onmessage;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
[Exposed=(Window,Worker,System)]
|
||||
interface MessagePort : EventTarget {
|
||||
[Throws]
|
||||
void postMessage(any message, optional sequence<Transferable> transferable);
|
||||
void postMessage(any message, sequence<object> 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<object> transfer = [];
|
||||
};
|
||||
|
|
@ -19,9 +19,10 @@ interface ServiceWorker : EventTarget {
|
|||
|
||||
attribute EventHandler onstatechange;
|
||||
|
||||
// FIXME(catalinb): Should inherit this from Worker.
|
||||
[Throws]
|
||||
void postMessage(any message, optional sequence<Transferable> transferable);
|
||||
void postMessage(any message, sequence<object> transferable);
|
||||
[Throws]
|
||||
void postMessage(any message, optional StructuredSerializeOptions options);
|
||||
};
|
||||
|
||||
ServiceWorker implements AbstractWorker;
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
@ -51,6 +50,7 @@ typedef any Transferable;
|
|||
[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;
|
||||
|
|
@ -80,7 +80,9 @@ typedef any Transferable;
|
|||
[Throws, UnsafeInPrerendering] void print();
|
||||
|
||||
[Throws, CrossOriginCallable, NeedsSubjectPrincipal]
|
||||
void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
|
||||
void postMessage(any message, DOMString targetOrigin, optional sequence<object> transfer = []);
|
||||
[Throws, CrossOriginCallable, NeedsSubjectPrincipal]
|
||||
void postMessage(any message, optional WindowPostMessageOptions options);
|
||||
|
||||
// also has obsolete members
|
||||
};
|
||||
|
|
@ -486,3 +488,7 @@ callback IdleRequestCallback = void (IdleDeadline deadline);
|
|||
partial interface Window {
|
||||
[ChromeOnly] readonly attribute boolean isSecureContextIfOpenerIgnored;
|
||||
};
|
||||
|
||||
dictionary WindowPostMessageOptions : StructuredSerializeOptions {
|
||||
USVString targetOrigin = "/";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ interface WindowOrWorkerGlobalScope {
|
|||
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource aImage);
|
||||
[Throws]
|
||||
Promise<ImageBitmap> 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
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ interface Worker : EventTarget {
|
|||
void terminate();
|
||||
|
||||
[Throws]
|
||||
void postMessage(any message, optional sequence<any> transfer);
|
||||
void postMessage(any message, sequence<object> transfer);
|
||||
[Throws]
|
||||
void postMessage(any message, optional StructuredSerializeOptions options);
|
||||
|
||||
attribute EventHandler onmessage;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -77,7 +78,7 @@ ServiceWorker::GetScriptURL(nsString& aURL) const
|
|||
|
||||
void
|
||||
ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (State() == ServiceWorkerState::Redundant) {
|
||||
|
|
@ -97,6 +98,15 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, Move(clientInfo));
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorker::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
|
||||
}
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ class nsPIDOMWindowInner;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct StructuredSerializeOptions;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerInfo;
|
||||
|
|
@ -63,7 +65,13 @@ public:
|
|||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -190,7 +191,7 @@ private:
|
|||
|
||||
void
|
||||
ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
|
|
@ -198,20 +199,11 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
JS::HandleValueArray elements =
|
||||
JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
|
||||
realTransferable.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<ServiceWorkerClientPostMessageRunnable> runnable =
|
||||
|
|
@ -229,3 +221,11 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerClient::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,13 @@ public:
|
|||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ NS_IMPL_ISUPPORTS0(MessageWaitUntilHandler)
|
|||
nsresult
|
||||
ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
||||
{
|
||||
ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr));
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
nsresult
|
||||
SendMessageEvent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo);
|
||||
|
||||
// This is used to validate the worker script and continue the installation
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -142,7 +143,7 @@ SharedWorker::Close()
|
|||
|
||||
void
|
||||
SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
|
@ -152,6 +153,15 @@ SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorker::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper)
|
||||
|
||||
|
|
|
|||
|
|
@ -94,8 +94,15 @@ private:
|
|||
|
||||
// Only called by MessagePort.
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3006,13 +3006,12 @@ WorkerPrivateParent<Derived>::ForgetMainThreadObjects(
|
|||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageInternal(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
PromiseNativeHandler* aHandler,
|
||||
ErrorResult& aRv)
|
||||
WorkerPrivateParent<Derived>::PostMessageInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
PromiseNativeHandler* aHandler,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
|
|
@ -3024,22 +3023,11 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
|||
}
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
// 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());
|
||||
|
||||
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<MessageEventRunnable> runnable =
|
||||
|
|
@ -3083,18 +3071,31 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
|||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessage(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, nullptr, nullptr, aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessage(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageInternal(aCx, aMessage, aOptions.mTransfer, nullptr, nullptr, aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageToServiceWorker(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
PromiseNativeHandler* aHandler,
|
||||
ErrorResult& aRv)
|
||||
|
|
@ -5677,27 +5678,17 @@ void
|
|||
WorkerPrivate::PostMessageToParentInternal(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
// 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());
|
||||
|
||||
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<MessageEventRunnable> runnable =
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class PromiseNativeHandler;
|
|||
class StructuredCloneHolder;
|
||||
class WorkerDebuggerGlobalScope;
|
||||
class WorkerGlobalScope;
|
||||
struct StructuredSerializeOptions;
|
||||
} // namespace dom
|
||||
namespace ipc {
|
||||
class PrincipalInfo;
|
||||
|
|
@ -287,7 +288,7 @@ private:
|
|||
|
||||
void
|
||||
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
PromiseNativeHandler* aHandler,
|
||||
ErrorResult& aRv);
|
||||
|
|
@ -400,12 +401,18 @@ public:
|
|||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessageToServiceWorker(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
PromiseNativeHandler* aHandler,
|
||||
ErrorResult& aRv);
|
||||
|
|
@ -1161,18 +1168,17 @@ public:
|
|||
void
|
||||
PostMessageToParent(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageToParentInternal(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
PostMessageToParentMessagePort(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
PostMessageToParentMessagePort(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
EnterDebuggerEventLoop();
|
||||
|
|
@ -1471,7 +1477,7 @@ private:
|
|||
void
|
||||
PostMessageToParentInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -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,15 @@ WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
|
|||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#structured-cloning
|
||||
void WorkerGlobalScope::StructuredClone(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
ErrorResult& aError) {
|
||||
nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRv, aError);
|
||||
}
|
||||
|
||||
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerGlobalScope(aWorkerPrivate)
|
||||
{
|
||||
|
|
@ -535,13 +545,22 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
|
|||
void
|
||||
DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
|
||||
}
|
||||
|
||||
SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
|
||||
const nsCString& aName)
|
||||
: WorkerGlobalScope(aWorkerPrivate), mName(aName)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class Function;
|
|||
class IDBFactory;
|
||||
enum class ImageBitmapFormat : uint32_t;
|
||||
class Performance;
|
||||
struct StructuredSerializeOptions;
|
||||
class Promise;
|
||||
class RequestOrUSVString;
|
||||
class ServiceWorkerRegistration;
|
||||
|
|
@ -182,6 +183,11 @@ public:
|
|||
const mozilla::dom::Sequence<mozilla::dom::ChannelPixelLayout>& aLayout,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void StructuredClone(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
JS::MutableHandle<JS::Value> aRv,
|
||||
ErrorResult& aError);
|
||||
|
||||
bool
|
||||
WindowInteractionAllowed() const
|
||||
{
|
||||
|
|
@ -215,7 +221,13 @@ public:
|
|||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const StructuredSerializeOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
|
|
|
|||
|
|
@ -326,6 +326,43 @@ 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<dom::StructuredSerializeOptions> 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<JS::Value> result(cx);
|
||||
ErrorResult rv;
|
||||
nsContentUtils::StructuredClone(cx, global, args[0], options, &result, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 +968,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 +1045,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
25
js/xpconnect/tests/unit/test_structuredClone.js
Normal file
25
js/xpconnect/tests/unit/test_structuredClone.js
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -5252,6 +5252,9 @@ pref("prompts.content_handling_dialog_modal.enabled", false);
|
|||
// Whether module scripts (<script type="module">) are enabled for content.
|
||||
pref("dom.moduleScripts.enabled", true);
|
||||
|
||||
// Whether read-only Window property event is enabled for content.
|
||||
pref("dom.window.event.enabled", false);
|
||||
|
||||
// Report details when a media source error occurs?
|
||||
// Enabled by default in debug builds, otherwise should be explicitly enabled
|
||||
// by the user to prevent XO leaking of the response status (CVE-2020-15666)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue