Skip to content

Commit eeff111

Browse files
Add JSSending.receive(...) to receive multiple objects at once
1 parent 4fe37e7 commit eeff111

File tree

11 files changed

+688
-143
lines changed

11 files changed

+688
-143
lines changed

Examples/OffscrenCanvas/Sources/MyApp/main.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ protocol CanvasRenderer {
1111
struct BackgroundRenderer: CanvasRenderer {
1212
func render(canvas: JSObject, size: Int) async throws {
1313
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
14-
let transfer = JSTransferring(canvas)
14+
let transfer = JSSending.transfer(canvas)
1515
let renderingTask = Task(executorPreference: executor) {
1616
let canvas = try await transfer.receive()
1717
try await renderAnimation(canvas: canvas, size: size)

Runtime/src/index.ts

+40-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import * as JSValue from "./js-value.js";
1212
import { Memory } from "./memory.js";
1313
import { deserializeError, MainToWorkerMessage, MessageBroker, ResponseMessage, ITCInterface, serializeError, SwiftRuntimeThreadChannel, WorkerToMainMessage } from "./itc.js";
14+
import { decodeObjectRefs } from "./js-value.js";
1415

1516
export type SwiftRuntimeOptions = {
1617
/**
@@ -208,7 +209,7 @@ export class SwiftRuntime {
208209
} catch (error) {
209210
responseMessage.data.response = {
210211
ok: false,
211-
error: serializeError(new TypeError(`Failed to serialize response message: ${error}`))
212+
error: serializeError(new TypeError(`Failed to serialize message: ${error}`))
212213
};
213214
newBroker.reply(responseMessage);
214215
}
@@ -648,24 +649,56 @@ export class SwiftRuntime {
648649
// Main thread's tid is always -1
649650
return this.tid || -1;
650651
},
651-
swjs_request_transferring_object: (
652-
object_ref: ref,
652+
swjs_request_sending_object: (
653+
sending_object: ref,
654+
transferring_objects: pointer,
655+
transferring_objects_count: number,
653656
object_source_tid: number,
654-
transferring: pointer,
657+
sending_context: pointer,
655658
) => {
656659
if (!this.options.threadChannel) {
657660
throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects.");
658661
}
659662
const broker = getMessageBroker(this.options.threadChannel);
663+
const memory = this.memory;
664+
const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, memory);
665+
broker.request({
666+
type: "request",
667+
data: {
668+
sourceTid: this.tid ?? MAIN_THREAD_TID,
669+
targetTid: object_source_tid,
670+
context: sending_context,
671+
request: {
672+
method: "send",
673+
parameters: [sending_object, transferringObjects, sending_context],
674+
}
675+
}
676+
})
677+
},
678+
swjs_request_sending_objects: (
679+
sending_objects: pointer,
680+
sending_objects_count: number,
681+
transferring_objects: pointer,
682+
transferring_objects_count: number,
683+
object_source_tid: number,
684+
sending_context: pointer,
685+
) => {
686+
if (!this.options.threadChannel) {
687+
throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects.");
688+
}
689+
const broker = getMessageBroker(this.options.threadChannel);
690+
const memory = this.memory;
691+
const sendingObjects = decodeObjectRefs(sending_objects, sending_objects_count, memory);
692+
const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, memory);
660693
broker.request({
661694
type: "request",
662695
data: {
663696
sourceTid: this.tid ?? MAIN_THREAD_TID,
664697
targetTid: object_source_tid,
665-
context: transferring,
698+
context: sending_context,
666699
request: {
667-
method: "transfer",
668-
parameters: [object_ref, transferring],
700+
method: "sendObjects",
701+
parameters: [sendingObjects, transferringObjects, sending_context],
669702
}
670703
}
671704
})

Runtime/src/itc.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,16 @@ export type SwiftRuntimeThreadChannel =
8585
export class ITCInterface {
8686
constructor(private memory: Memory) {}
8787

88-
transfer(objectRef: ref, transferring: pointer): { object: any, transferring: pointer, transfer: Transferable[] } {
89-
const object = this.memory.getObject(objectRef);
90-
return { object, transferring, transfer: [object] };
88+
send(sendingObject: ref, transferringObjects: ref[], sendingContext: pointer): { object: any, sendingContext: pointer, transfer: Transferable[] } {
89+
const object = this.memory.getObject(sendingObject);
90+
const transfer = transferringObjects.map(ref => this.memory.getObject(ref));
91+
return { object, sendingContext, transfer };
92+
}
93+
94+
sendObjects(sendingObjects: ref[], transferringObjects: ref[], sendingContext: pointer): { object: any[], sendingContext: pointer, transfer: Transferable[] } {
95+
const objects = sendingObjects.map(ref => this.memory.getObject(ref));
96+
const transfer = transferringObjects.map(ref => this.memory.getObject(ref));
97+
return { object: objects, sendingContext, transfer };
9198
}
9299

93100
release(objectRef: ref): { object: undefined, transfer: Transferable[] } {

Runtime/src/js-value.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Memory } from "./memory.js";
2-
import { assertNever, JavaScriptValueKindAndFlags, pointer } from "./types.js";
2+
import { assertNever, JavaScriptValueKindAndFlags, pointer, ref } from "./types.js";
33

44
export const enum Kind {
55
Boolean = 0,
@@ -142,3 +142,11 @@ export const writeAndReturnKindBits = (
142142
}
143143
throw new Error("Unreachable");
144144
};
145+
146+
export function decodeObjectRefs(ptr: pointer, length: number, memory: Memory): ref[] {
147+
const result: ref[] = new Array(length);
148+
for (let i = 0; i < length; i++) {
149+
result[i] = memory.readUint32(ptr + 4 * i);
150+
}
151+
return result;
152+
}

Runtime/src/types.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,20 @@ export interface ImportedFunctions {
115115
swjs_listen_message_from_worker_thread: (tid: number) => void;
116116
swjs_terminate_worker_thread: (tid: number) => void;
117117
swjs_get_worker_thread_id: () => number;
118-
swjs_request_transferring_object: (
119-
object_ref: ref,
118+
swjs_request_sending_object: (
119+
sending_object: ref,
120+
transferring_objects: pointer,
121+
transferring_objects_count: number,
120122
object_source_tid: number,
121-
transferring: pointer,
123+
sending_context: pointer,
124+
) => void;
125+
swjs_request_sending_objects: (
126+
sending_objects: pointer,
127+
sending_objects_count: number,
128+
transferring_objects: pointer,
129+
transferring_objects_count: number,
130+
object_source_tid: number,
131+
sending_context: pointer,
122132
) => void;
123133
}
124134

0 commit comments

Comments
 (0)