first commit

This commit is contained in:
Andreas Gammelgaard Damsbo 2024-01-11 09:43:23 +01:00
commit 6333bcee61
208 changed files with 413695 additions and 0 deletions

View file

@ -0,0 +1,21 @@
import { SharedBufferChannelMain, SharedBufferChannelWorker } from './channel-shared';
import { ServiceWorkerChannelMain, ServiceWorkerChannelWorker } from './channel-service';
import { PostMessageChannelMain, PostMessageChannelWorker } from './channel-postmessage';
import { WebROptions } from '../webr-main';
export declare const ChannelType: {
readonly Automatic: 0;
readonly SharedArrayBuffer: 1;
readonly ServiceWorker: 2;
readonly PostMessage: 3;
};
export type ChannelInitMessage = {
type: string;
data: {
config: Required<WebROptions>;
channelType: Exclude<(typeof ChannelType)[keyof typeof ChannelType], typeof ChannelType.Automatic>;
clientId?: string;
location?: string;
};
};
export declare function newChannelMain(data: Required<WebROptions>): SharedBufferChannelMain | ServiceWorkerChannelMain | PostMessageChannelMain;
export declare function newChannelWorker(msg: ChannelInitMessage): SharedBufferChannelWorker | ServiceWorkerChannelWorker | PostMessageChannelWorker;

View file

@ -0,0 +1,26 @@
import { Message } from './message';
import { WebROptions } from '../webr-main';
import { ChannelMain } from './channel';
export declare class PostMessageChannelMain extends ChannelMain {
#private;
initialised: Promise<unknown>;
resolve: (_?: unknown) => void;
close: () => void;
constructor(config: Required<WebROptions>);
interrupt(): void;
}
export declare class PostMessageChannelWorker {
#private;
constructor();
resolve(): void;
write(msg: Message, transfer?: [Transferable]): void;
writeSystem(msg: Message, transfer?: [Transferable]): void;
read(): Message;
inputOrDispatch(): number;
run(_args: string[]): void;
setDispatchHandler(dispatch: (msg: Message) => void): void;
request(msg: Message, transferables?: [Transferable]): Promise<any>;
setInterrupt(_: () => void): void;
handleInterrupt(): void;
onMessageFromMainThread(message: Message): void;
}

View file

@ -0,0 +1,30 @@
import { Message, Response } from './message';
import { ChannelMain, ChannelWorker } from './channel';
import { WebROptions } from '../webr-main';
export declare class ServiceWorkerChannelMain extends ChannelMain {
#private;
initialised: Promise<unknown>;
resolve: (_?: unknown) => void;
close: () => void;
constructor(config: Required<WebROptions>);
activeRegistration(): ServiceWorker;
interrupt(): void;
}
export declare class ServiceWorkerChannelWorker implements ChannelWorker {
#private;
onMessageFromMainThread: (msg: Message) => void;
constructor(data: {
clientId?: string;
location?: string;
});
resolve(): void;
write(msg: Message, transfer?: [Transferable]): void;
writeSystem(msg: Message, transfer?: [Transferable]): void;
syncRequest(message: Message): Response;
read(): Message;
inputOrDispatch(): number;
run(args: string[]): void;
setInterrupt(interrupt: () => void): void;
handleInterrupt(): void;
setDispatchHandler(dispatch: (msg: Message) => void): void;
}

View file

@ -0,0 +1,25 @@
import { Message } from './message';
import { ChannelMain, ChannelWorker } from './channel';
import { WebROptions } from '../webr-main';
export declare class SharedBufferChannelMain extends ChannelMain {
#private;
initialised: Promise<unknown>;
resolve: (_?: unknown) => void;
close: () => void;
constructor(config: Required<WebROptions>);
interrupt(): void;
}
export declare class SharedBufferChannelWorker implements ChannelWorker {
#private;
onMessageFromMainThread: (msg: Message) => void;
constructor();
resolve(): void;
write(msg: Message, transfer?: [Transferable]): void;
writeSystem(msg: Message, transfer?: [Transferable]): void;
read(): Message;
inputOrDispatch(): number;
run(args: string[]): void;
setInterrupt(interrupt: () => void): void;
handleInterrupt(): void;
setDispatchHandler(dispatch: (msg: Message) => void): void;
}

View file

@ -0,0 +1,44 @@
/**
* Interfaces for the webR main and worker thread communication channels.
* @module Channel
*/
import { AsyncQueue } from './queue';
import { Message, Response } from './message';
import { WebRPayload } from '../payload';
export declare abstract class ChannelMain {
#private;
inputQueue: AsyncQueue<Message>;
outputQueue: AsyncQueue<Message>;
systemQueue: AsyncQueue<Message>;
abstract initialised: Promise<unknown>;
abstract close(): void;
abstract interrupt(): void;
read(): Promise<Message>;
flush(): Promise<Message[]>;
readSystem(): Promise<Message>;
write(msg: Message): void;
request(msg: Message, transferables?: [Transferable]): Promise<WebRPayload>;
protected putClosedMessage(): void;
protected resolveResponse(msg: Response): void;
}
export interface ChannelWorker {
resolve(): void;
write(msg: Message, transfer?: [Transferable]): void;
writeSystem(msg: Message, transfer?: [Transferable]): void;
read(): Message;
handleInterrupt(): void;
setInterrupt(interrupt: () => void): void;
run(args: string[]): void;
inputOrDispatch: () => number;
setDispatchHandler: (dispatch: (msg: Message) => void) => void;
onMessageFromMainThread: (msg: Message) => void;
}
/**
* Handler functions dealing with setup and commmunication over a Service Worker.
*/
export interface ServiceWorkerHandlers {
handleActivate: (this: ServiceWorkerGlobalScope, ev: ExtendableEvent) => any;
handleFetch: (this: ServiceWorkerGlobalScope, ev: FetchEvent) => any;
handleInstall: (this: ServiceWorkerGlobalScope, ev: ExtendableEvent) => any;
handleMessage: (this: ServiceWorkerGlobalScope, ev: ExtendableMessageEvent) => any;
}

View file

@ -0,0 +1,50 @@
/**
* WebR communication channel messaging and request types.
* @module Message
*/
import { UUID } from './task-common';
/** A webR communication channel message. */
export interface Message {
type: string;
data?: any;
}
/** A webR communication channel request. */
export interface Request {
type: 'request';
data: {
uuid: UUID;
msg: Message;
};
}
/** A webR communication channel response. */
export interface Response {
type: 'response';
data: {
uuid: UUID;
resp: unknown;
};
}
/** @internal */
export declare function newRequest(msg: Message, transferables?: [Transferable]): Request;
/** @internal */
export declare function newResponse(uuid: UUID, resp: unknown, transferables?: [Transferable]): Response;
/** A webR communication channel sync-request.
* @internal
*/
export interface SyncRequest {
type: 'sync-request';
data: {
msg: Message;
reqData: SyncRequestData;
};
}
/** Transfer data required when using sync-request with SharedArrayBuffer.
* @internal */
export interface SyncRequestData {
taskId?: number;
sizeBuffer: Int32Array;
signalBuffer: Int32Array;
dataBuffer: Uint8Array;
}
/** @internal */
export declare function newSyncRequest(msg: Message, data: SyncRequestData): SyncRequest;

View file

@ -0,0 +1,17 @@
/**
* @module Queue
*/
/**
* Asynchronous queue mechanism to be used by the communication channels.
* @typeParam T The type of item to be stored in the queue.
*/
export declare class AsyncQueue<T> {
#private;
constructor();
reset(): void;
put(t: T): void;
get(): Promise<T>;
isEmpty(): boolean;
isBlocked(): boolean;
get length(): number;
}

View file

@ -0,0 +1,6 @@
import { ServiceWorkerHandlers } from './channel';
export declare function handleInstall(): void;
export declare function handleActivate(event: ExtendableEvent): void;
export declare function handleFetch(event: FetchEvent): boolean;
export declare function handleMessage(event: ExtendableMessageEvent): boolean;
export declare const webRHandlers: ServiceWorkerHandlers;

View file

@ -0,0 +1,17 @@
export declare const SZ_BUF_DOESNT_FIT = 0;
export declare const SZ_BUF_FITS_IDX = 1;
export declare const SZ_BUF_SIZE_IDX = 0;
export interface Endpoint extends EventSource {
postMessage(message: any, transfer?: Transferable[]): void;
start?: () => void;
}
export interface EventSource {
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void;
}
export declare function toWireValue(value: any): [any, Transferable[]];
export declare function transfer<T>(obj: T, transfers: Transferable[]): T;
export type UUID = string;
export declare function isUUID(x: any): x is UUID;
export declare const UUID_LENGTH = 63;
export declare function generateUUID(): UUID;

View file

@ -0,0 +1,15 @@
import { Endpoint } from './task-common';
import { SyncRequestData } from './message';
/**
* Respond to a blocking request. Most of the work has already been done in
* asynclink, we are just responsible here for getting the return value back to
* the requester through this slightly convoluted Atomics protocol.
* @param {Endpoint} endpoint A message port to receive messages from. Other
* thread is blocked, so we can't send messages back.
* @param {SyncRequestData} data The message that was recieved. We will use it
* to read out the buffers to write the answer into. NOTE: requester
* owns buffers.
* @param {any} response The value we want to send back to the requester. We
* have to encode it into data_buffer.
*/
export declare function syncResponse(endpoint: Endpoint, data: SyncRequestData, response: any): Promise<void>;

View file

@ -0,0 +1,42 @@
import { Endpoint } from './task-common';
import { Message } from './message';
export declare class SyncTask {
#private;
endpoint: Endpoint;
msg: Message;
transfers: Transferable[];
taskId?: number;
sizeBuffer?: Int32Array;
signalBuffer?: Int32Array;
syncifier: _Syncifier;
constructor(endpoint: Endpoint, msg: Message, transfers?: Transferable[]);
scheduleSync(): this | undefined;
poll(): boolean;
doSync(): Generator<undefined, unknown, unknown>;
get result(): unknown;
syncify(): any;
}
declare class _Syncifier {
nextTaskId: Int32Array;
signalBuffer: Int32Array;
tasks: Map<number, SyncTask>;
constructor();
scheduleTask(task: SyncTask): void;
waitOnSignalBuffer(): void;
tasksIdsToWakeup(): Generator<number, void, unknown>;
pollTasks(task?: SyncTask): boolean;
syncifyTask(task: SyncTask): void;
}
/**
* Sets the interrupt handler. This is called when the computation is
* interrupted. Should zero the interrupt buffer and throw an exception.
* @internal
*/
export declare function setInterruptHandler(handler: () => void): void;
/**
* Sets the interrupt buffer. Should be a shared array buffer. When element 0
* is set non-zero it signals an interrupt.
* @internal
*/
export declare function setInterruptBuffer(buffer: ArrayBufferLike): void;
export {};