mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 08:18:41 +09:00
Add same-thread stream transfer support
This commit is contained in:
parent
8c4ece641e
commit
58e0e6a192
3 changed files with 313 additions and 0 deletions
|
|
@ -138,6 +138,120 @@ StructuredCloneCallbacksError(JSContext* aCx,
|
|||
NS_WARNING("Failed to clone data.");
|
||||
}
|
||||
|
||||
struct SameThreadStreamTransferData
|
||||
{
|
||||
SameThreadStreamTransferData(JSContext* aCx, JS::HandleObject aRecord)
|
||||
: mRecord(aCx, aRecord)
|
||||
{}
|
||||
|
||||
~SameThreadStreamTransferData()
|
||||
{
|
||||
mRecord.reset();
|
||||
}
|
||||
|
||||
JS::PersistentRootedObject mRecord;
|
||||
};
|
||||
|
||||
bool
|
||||
CallStreamTransferHelper(JSContext* aCx,
|
||||
const char* aHelperName,
|
||||
JS::HandleValue aArgument,
|
||||
JS::MutableHandleValue aResult)
|
||||
{
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!global) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve the stream extras lazily before looking up the internal helper.
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
if (!JS_GetProperty(aCx, global, "WritableStream", &ignored)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> helper(aCx);
|
||||
if (!JS_GetProperty(aCx, global, aHelperName, &helper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!helper.isObject() || !JS::IsCallable(&helper.toObject())) {
|
||||
aResult.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> argument(aCx, aArgument);
|
||||
if (!JS_WrapValue(aCx, &argument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS::Call(aCx, JS::UndefinedHandleValue, helper,
|
||||
JS::HandleValueArray(argument), aResult);
|
||||
}
|
||||
|
||||
bool
|
||||
TryWriteSameThreadStreamTransfer(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
const char* aHelperName,
|
||||
uint32_t aTransferTag,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData,
|
||||
bool* aHandled)
|
||||
{
|
||||
*aHandled = false;
|
||||
|
||||
JS::Rooted<JS::Value> argument(aCx, JS::ObjectValue(*aObj));
|
||||
JS::Rooted<JS::Value> transferRecord(aCx);
|
||||
if (!CallStreamTransferHelper(aCx, aHelperName, argument, &transferRecord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transferRecord.isUndefined()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transferRecord.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> record(aCx, &transferRecord.toObject());
|
||||
SameThreadStreamTransferData* data =
|
||||
new SameThreadStreamTransferData(aCx, record);
|
||||
|
||||
*aTag = aTransferTag;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
*aContent = data;
|
||||
*aExtraData = 0;
|
||||
*aHandled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadSameThreadStreamTransfer(JSContext* aCx,
|
||||
void* aContent,
|
||||
const char* aHelperName,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
MOZ_ASSERT(aContent);
|
||||
SameThreadStreamTransferData* data =
|
||||
static_cast<SameThreadStreamTransferData*>(aContent);
|
||||
|
||||
JS::Rooted<JS::Value> record(aCx, JS::ObjectValue(*data->mRecord));
|
||||
JS::Rooted<JS::Value> result(aCx);
|
||||
if (!CallStreamTransferHelper(aCx, aHelperName, record, &result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!result.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aReturnObject.set(&result.toObject());
|
||||
delete data;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
const JSStructuredCloneCallbacks StructuredCloneHolder::sCallbacks = {
|
||||
|
|
@ -1375,6 +1489,20 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_WRITABLESTREAM) {
|
||||
return ReadSameThreadStreamTransfer(aCx, aContent,
|
||||
"__uxpReceiveWritableStreamTransfer",
|
||||
aReturnObject);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM) {
|
||||
return ReadSameThreadStreamTransfer(aCx, aContent,
|
||||
"__uxpReceiveReadableStreamTransfer",
|
||||
aReturnObject);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1443,6 +1571,31 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
bool handled = false;
|
||||
if (!TryWriteSameThreadStreamTransfer(aCx, obj,
|
||||
"__uxpTransferWritableStream",
|
||||
SCTAG_DOM_TRANSFERRED_WRITABLESTREAM,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryWriteSameThreadStreamTransfer(aCx, obj,
|
||||
"__uxpTransferReadableStream",
|
||||
SCTAG_DOM_TRANSFERRED_READABLESTREAM,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1480,6 +1633,16 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
|
|||
delete data;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((aTag == SCTAG_DOM_TRANSFERRED_WRITABLESTREAM ||
|
||||
aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM) &&
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
MOZ_ASSERT(aContent);
|
||||
SameThreadStreamTransferData* data =
|
||||
static_cast<SameThreadStreamTransferData*>(aContent);
|
||||
delete data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue