mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1609916 - Callback from SC to DOM on SAB cloning. r=luke
When structured clone reads a SAB and creates a new SAB object, or when it serializes a SAB onto a channel, call a callback that lets the embedder know. The embedder can then adjust its policy. Concretely, we want to allow the browser to serialize threads in a process that uses JS shared memory. Note, for WebAssembly.Memory, reading and writing are delegated to the cloning operations for SAB, so no special handling is needed. Differential Revision: https://phabricator.services.mozilla.com/D61455 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6b517ceeb5
commit
5dd2428621
@ -148,7 +148,7 @@ const JSStructuredCloneCallbacks StructuredCloneHolder::sCallbacks = {
|
||||
StructuredCloneCallbacksRead, StructuredCloneCallbacksWrite,
|
||||
StructuredCloneCallbacksError, StructuredCloneCallbacksReadTransfer,
|
||||
StructuredCloneCallbacksWriteTransfer, StructuredCloneCallbacksFreeTransfer,
|
||||
StructuredCloneCallbacksCanTransfer,
|
||||
StructuredCloneCallbacksCanTransfer, nullptr,
|
||||
};
|
||||
|
||||
// StructuredCloneHolderBase class
|
||||
|
@ -419,13 +419,10 @@ bool CopyingStructuredCloneWriteCallback(JSContext* aCx,
|
||||
|
||||
nsresult GetAddInfoCallback(JSContext* aCx, void* aClosure) {
|
||||
static const JSStructuredCloneCallbacks kStructuredCloneCallbacks = {
|
||||
nullptr /* read */,
|
||||
StructuredCloneWriteCallback /* write */,
|
||||
nullptr /* reportError */,
|
||||
nullptr /* readTransfer */,
|
||||
nullptr /* writeTransfer */,
|
||||
nullptr /* freeTransfer */,
|
||||
nullptr /* canTransfer */
|
||||
nullptr /* read */, StructuredCloneWriteCallback /* write */,
|
||||
nullptr /* reportError */, nullptr /* readTransfer */,
|
||||
nullptr /* writeTransfer */, nullptr /* freeTransfer */,
|
||||
nullptr /* canTransfer */, nullptr /* sabCloned */
|
||||
};
|
||||
|
||||
MOZ_ASSERT(aCx);
|
||||
@ -1062,6 +1059,7 @@ bool IDBObjectStore::DeserializeValue(JSContext* aCx,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
|
||||
// FIXME: Consider to use StructuredCloneHolder here and in other
|
||||
@ -1219,6 +1217,7 @@ class DeserializeIndexValueHelper final : public Runnable {
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
|
||||
if (!JS_ReadStructuredClone(
|
||||
@ -1325,6 +1324,7 @@ class DeserializeUpgradeValueHelper final : public Runnable {
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
|
||||
if (!JS_ReadStructuredClone(
|
||||
@ -2571,7 +2571,8 @@ bool IDBObjectStore::ValueWrapper::Clone(JSContext* aCx) {
|
||||
nullptr /* readTransfer */,
|
||||
nullptr /* writeTransfer */,
|
||||
nullptr /* freeTransfer */,
|
||||
nullptr /* canTransfer */
|
||||
nullptr /* canTransfer */,
|
||||
nullptr /* sabCloned */
|
||||
};
|
||||
|
||||
StructuredCloneInfo cloneInfo;
|
||||
|
@ -330,6 +330,19 @@ typedef bool (*CanTransferStructuredCloneOp)(JSContext* cx,
|
||||
bool* sameProcessScopeRequired,
|
||||
void* closure);
|
||||
|
||||
/**
|
||||
* Called when a SharedArrayBuffer (including one owned by a Wasm memory object)
|
||||
* has been processed in context `cx` by structured cloning. If `receiving` is
|
||||
* true then the SAB has been received from a channel and a new SAB object has
|
||||
* been created; if false then an existing SAB has been serialized onto a
|
||||
* channel.
|
||||
*
|
||||
* If the callback returns false then the clone operation (read or write) will
|
||||
* signal a failure.
|
||||
*/
|
||||
typedef bool (*SharedArrayBufferClonedOp)(JSContext* cx, bool receiving,
|
||||
void* closure);
|
||||
|
||||
struct JSStructuredCloneCallbacks {
|
||||
ReadStructuredCloneOp read;
|
||||
WriteStructuredCloneOp write;
|
||||
@ -338,6 +351,7 @@ struct JSStructuredCloneCallbacks {
|
||||
TransferStructuredCloneOp writeTransfer;
|
||||
FreeTransferStructuredCloneOp freeTransfer;
|
||||
CanTransferStructuredCloneOp canTransfer;
|
||||
SharedArrayBufferClonedOp sabCloned;
|
||||
};
|
||||
|
||||
enum OwnTransferablePolicy {
|
||||
|
@ -470,6 +470,8 @@ struct JSStructuredCloneWriter {
|
||||
const JSStructuredCloneCallbacks* cb,
|
||||
void* cbClosure, const Value& tVal)
|
||||
: out(cx, scope),
|
||||
callbacks(cb),
|
||||
closure(cbClosure),
|
||||
objs(out.context()),
|
||||
counts(out.context()),
|
||||
objectEntries(out.context()),
|
||||
@ -528,6 +530,13 @@ struct JSStructuredCloneWriter {
|
||||
|
||||
SCOutput out;
|
||||
|
||||
// The user defined callbacks that will be used to signal cloning, in some
|
||||
// cases.
|
||||
const JSStructuredCloneCallbacks* callbacks;
|
||||
|
||||
// Any value passed to the callbacks.
|
||||
void* closure;
|
||||
|
||||
// Vector of objects with properties remaining to be written.
|
||||
//
|
||||
// NB: These can span multiple compartments, so the compartment must be
|
||||
@ -1328,10 +1337,19 @@ bool JSStructuredCloneWriter::writeSharedArrayBuffer(HandleObject obj) {
|
||||
|
||||
intptr_t p = reinterpret_cast<intptr_t>(rawbuf);
|
||||
uint32_t byteLength = sharedArrayBuffer->byteLength();
|
||||
return out.writePair(SCTAG_SHARED_ARRAY_BUFFER_OBJECT,
|
||||
static_cast<uint32_t>(sizeof(p))) &&
|
||||
out.writeBytes(&byteLength, sizeof(byteLength)) &&
|
||||
out.writeBytes(&p, sizeof(p));
|
||||
if (!(out.writePair(SCTAG_SHARED_ARRAY_BUFFER_OBJECT,
|
||||
static_cast<uint32_t>(sizeof(p))) &&
|
||||
out.writeBytes(&byteLength, sizeof(byteLength)) &&
|
||||
out.writeBytes(&p, sizeof(p)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callbacks && callbacks->sabCloned &&
|
||||
!callbacks->sabCloned(context(), /*receiving=*/false, closure)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSStructuredCloneWriter::writeSharedWasmMemory(HandleObject obj) {
|
||||
@ -2307,12 +2325,20 @@ bool JSStructuredCloneReader::readSharedArrayBuffer(MutableHandleValue vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject* obj = SharedArrayBufferObject::New(context(), rawbuf, byteLength);
|
||||
RootedObject obj(context(),
|
||||
SharedArrayBufferObject::New(context(), rawbuf, byteLength));
|
||||
if (!obj) {
|
||||
rawbuf->dropReference();
|
||||
return false;
|
||||
}
|
||||
|
||||
// `rawbuf` is now owned by `obj`.
|
||||
|
||||
if (callbacks && callbacks->sabCloned &&
|
||||
!callbacks->sabCloned(context(), /*receiving=*/true, closure)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vp.setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user