@quilted/threads
Advanced tools
Comparing version 0.0.0-preview-20230526061211 to 0.0.0-preview-20230801233353
@@ -1,7 +0,5 @@ | ||
export { createThread } from './thread.ts'; | ||
export type { ThreadOptions } from './thread.ts'; | ||
export { retain, release, StackFrame, isMemoryManageable } from './memory.ts'; | ||
export type { MemoryManageable, MemoryRetainer } from './memory.ts'; | ||
export { RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY, ENCODE_METHOD, } from './constants.ts'; | ||
export { targetFromIframe, targetFromInsideIframe, targetFromWebWorker, targetFromMessagePort, targetFromBrowserWebSocket, } from './targets.ts'; | ||
export { createThread, createThreadFromBrowserWebSocket, createThreadFromIframe, createThreadFromInsideIframe, createThreadFromMessagePort, createThreadFromWebWorker, type ThreadOptions, } from './targets.ts'; | ||
export { createBasicEncoder, createBasicEncoderWithOverrides, } from './encoding.ts'; | ||
@@ -8,0 +6,0 @@ export { createThreadAbortSignal, acceptThreadAbortSignal } from './abort.ts'; |
@@ -1,6 +0,7 @@ | ||
export { targetFromIframe } from './targets/iframe/iframe.ts'; | ||
export { targetFromInsideIframe } from './targets/iframe/nested.ts'; | ||
export { targetFromMessagePort } from './targets/message-port.ts'; | ||
export { targetFromBrowserWebSocket } from './targets/web-socket-browser.ts'; | ||
export { targetFromWebWorker } from './targets/web-worker.ts'; | ||
export { createThread, type ThreadOptions } from './targets/target.ts'; | ||
export { createThreadFromIframe } from './targets/iframe/iframe.ts'; | ||
export { createThreadFromInsideIframe } from './targets/iframe/nested.ts'; | ||
export { createThreadFromMessagePort } from './targets/message-port.ts'; | ||
export { createThreadFromBrowserWebSocket } from './targets/web-socket-browser.ts'; | ||
export { createThreadFromWebWorker } from './targets/web-worker.ts'; | ||
//# sourceMappingURL=targets.d.ts.map |
@@ -1,5 +0,5 @@ | ||
import type { ThreadTarget } from '../../types.ts'; | ||
export declare function targetFromIframe(iframe: HTMLIFrameElement, { targetOrigin }?: { | ||
import { type ThreadOptions } from '../target.ts'; | ||
export declare function createThreadFromIframe<Self = Record<string, never>, Target = Record<string, never>>(iframe: HTMLIFrameElement, { targetOrigin, ...options }?: ThreadOptions<Self, Target> & { | ||
targetOrigin?: string; | ||
}): ThreadTarget; | ||
}): import("../../types.ts").ThreadCallable<Target>; | ||
//# sourceMappingURL=iframe.d.ts.map |
@@ -1,5 +0,5 @@ | ||
import type { ThreadTarget } from '../../types.ts'; | ||
export declare function targetFromInsideIframe({ targetOrigin, }?: { | ||
import { type ThreadOptions } from '../target.ts'; | ||
export declare function createThreadFromInsideIframe<Self = Record<string, never>, Target = Record<string, never>>({ targetOrigin, ...options }?: ThreadOptions<Self, Target> & { | ||
targetOrigin?: string; | ||
}): ThreadTarget; | ||
}): import("../../types.ts").ThreadCallable<Target>; | ||
//# sourceMappingURL=nested.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import type { ThreadTarget } from '../types.ts'; | ||
export declare function targetFromMessagePort(port: MessagePort): ThreadTarget; | ||
import { type ThreadOptions } from './target.ts'; | ||
export declare function createThreadFromMessagePort<Self = Record<string, never>, Target = Record<string, never>>(port: MessagePort, options?: ThreadOptions<Self, Target>): import("../types.ts").ThreadCallable<Target>; | ||
//# sourceMappingURL=message-port.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import type { ThreadTarget } from '../types.ts'; | ||
export declare function targetFromBrowserWebSocket(websocket: WebSocket): ThreadTarget; | ||
import { type ThreadOptions } from './target.ts'; | ||
export declare function createThreadFromBrowserWebSocket<Self = Record<string, never>, Target = Record<string, never>>(websocket: WebSocket, options?: ThreadOptions<Self, Target>): import("../types.ts").ThreadCallable<Target>; | ||
//# sourceMappingURL=web-socket-browser.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import type { ThreadTarget } from '../types.ts'; | ||
export declare function targetFromWebWorker(worker: Worker): ThreadTarget; | ||
import { type ThreadOptions } from './target.ts'; | ||
export declare function createThreadFromWebWorker<Self = Record<string, never>, Target = Record<string, never>>(worker: Worker, options?: ThreadOptions<Self, Target>): import("../types.ts").ThreadCallable<Target>; | ||
//# sourceMappingURL=web-worker.d.ts.map |
# @quilted/threads | ||
## 0.0.0-preview-20230526061211 | ||
## 0.0.0-preview-20230801233353 | ||
### Patch Changes | ||
- Encode more native JS types | ||
- Simplify thread creation and add helpers for transferring signals over threads | ||
## 0.1.16 | ||
### Patch Changes | ||
- [`e45f766b`](https://github.com/lemonmade/quilt/commit/e45f766bce9e8632fe17d9e9c2e3d446d0783feb) Thanks [@lemonmade](https://github.com/lemonmade)! - Simplify thread creation and add helpers for transferring signals over threads | ||
## 0.1.15 | ||
@@ -10,0 +16,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"type": "module", | ||
"version": "0.0.0-preview-20230526061211", | ||
"version": "0.0.0-preview-20230801233353", | ||
"license": "MIT", | ||
@@ -27,5 +27,19 @@ "engines": { | ||
"require": "./build/cjs/index.cjs" | ||
}, | ||
"./signals": { | ||
"types": "./build/typescript/signals.d.ts", | ||
"quilt:source": "./source/signals.ts", | ||
"quilt:esnext": "./build/esnext/signals.esnext", | ||
"import": "./build/esm/signals.mjs", | ||
"require": "./build/cjs/signals.cjs" | ||
} | ||
}, | ||
"types": "./build/typescript/index.d.ts", | ||
"typesVersions": { | ||
"*": { | ||
"signals": [ | ||
"./build/typescript/signals.d.ts" | ||
] | ||
} | ||
}, | ||
"sideEffects": false, | ||
@@ -35,4 +49,13 @@ "dependencies": { | ||
}, | ||
"peerDependencies": { | ||
"@preact/signals-core": "^1.3.0" | ||
}, | ||
"peerDependenciesMeta": { | ||
"@preact/signals-core": { | ||
"optional": true | ||
} | ||
}, | ||
"devDependencies": { | ||
"@quilted/testing": "0.1.5" | ||
"@preact/signals-core": "^1.3.0", | ||
"@quilted/testing": "0.1.6" | ||
}, | ||
@@ -39,0 +62,0 @@ "eslintConfig": { |
@@ -1,3 +0,1 @@ | ||
export {createThread} from './thread.ts'; | ||
export type {ThreadOptions} from './thread.ts'; | ||
export {retain, release, StackFrame, isMemoryManageable} from './memory.ts'; | ||
@@ -12,7 +10,9 @@ export type {MemoryManageable, MemoryRetainer} from './memory.ts'; | ||
export { | ||
targetFromIframe, | ||
targetFromInsideIframe, | ||
targetFromWebWorker, | ||
targetFromMessagePort, | ||
targetFromBrowserWebSocket, | ||
createThread, | ||
createThreadFromBrowserWebSocket, | ||
createThreadFromIframe, | ||
createThreadFromInsideIframe, | ||
createThreadFromMessagePort, | ||
createThreadFromWebWorker, | ||
type ThreadOptions, | ||
} from './targets.ts'; | ||
@@ -19,0 +19,0 @@ export { |
@@ -1,5 +0,6 @@ | ||
export {targetFromIframe} from './targets/iframe/iframe.ts'; | ||
export {targetFromInsideIframe} from './targets/iframe/nested.ts'; | ||
export {targetFromMessagePort} from './targets/message-port.ts'; | ||
export {targetFromBrowserWebSocket} from './targets/web-socket-browser.ts'; | ||
export {targetFromWebWorker} from './targets/web-worker.ts'; | ||
export {createThread, type ThreadOptions} from './targets/target.ts'; | ||
export {createThreadFromIframe} from './targets/iframe/iframe.ts'; | ||
export {createThreadFromInsideIframe} from './targets/iframe/nested.ts'; | ||
export {createThreadFromMessagePort} from './targets/message-port.ts'; | ||
export {createThreadFromBrowserWebSocket} from './targets/web-socket-browser.ts'; | ||
export {createThreadFromWebWorker} from './targets/web-worker.ts'; |
import {on} from '@quilted/events'; | ||
import type {ThreadTarget} from '../../types.ts'; | ||
import { | ||
createThread, | ||
type ThreadTarget, | ||
type ThreadOptions, | ||
} from '../target.ts'; | ||
import {CHECK_MESSAGE, RESPONSE_MESSAGE} from './shared.ts'; | ||
export function targetFromIframe( | ||
export function createThreadFromIframe< | ||
Self = Record<string, never>, | ||
Target = Record<string, never>, | ||
>( | ||
iframe: HTMLIFrameElement, | ||
{targetOrigin = '*'}: {targetOrigin?: string} = {}, | ||
): ThreadTarget { | ||
{ | ||
targetOrigin = '*', | ||
...options | ||
}: ThreadOptions<Self, Target> & {targetOrigin?: string} = {}, | ||
) { | ||
let connected = false; | ||
@@ -35,26 +45,29 @@ | ||
return { | ||
send(message, transfer) { | ||
if (!connected) { | ||
return connectedPromise.then(() => sendMessage(message, transfer)); | ||
} | ||
return createThread( | ||
{ | ||
send(message, transfer) { | ||
if (!connected) { | ||
return connectedPromise.then(() => sendMessage(message, transfer)); | ||
} | ||
return sendMessage(message, transfer); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WindowEventHandlersEventMap, 'message'>( | ||
self, | ||
'message', | ||
{ | ||
signal, | ||
}, | ||
); | ||
return sendMessage(message, transfer); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WindowEventHandlersEventMap, 'message'>( | ||
self, | ||
'message', | ||
{ | ||
signal, | ||
}, | ||
); | ||
for await (const message of messages) { | ||
if (message.source !== iframe.contentWindow) continue; | ||
if (message.data === RESPONSE_MESSAGE) continue; | ||
yield message.data; | ||
} | ||
for await (const message of messages) { | ||
if (message.source !== iframe.contentWindow) continue; | ||
if (message.data === RESPONSE_MESSAGE) continue; | ||
yield message.data; | ||
} | ||
}, | ||
}, | ||
}; | ||
options, | ||
); | ||
} |
import {on} from '@quilted/events'; | ||
import type {ThreadTarget} from '../../types.ts'; | ||
import {createThread, type ThreadOptions} from '../target.ts'; | ||
import {CHECK_MESSAGE, RESPONSE_MESSAGE} from './shared.ts'; | ||
export function targetFromInsideIframe({ | ||
export function createThreadFromInsideIframe< | ||
Self = Record<string, never>, | ||
Target = Record<string, never>, | ||
>({ | ||
targetOrigin = '*', | ||
}: {targetOrigin?: string} = {}): ThreadTarget { | ||
...options | ||
}: ThreadOptions<Self, Target> & {targetOrigin?: string} = {}) { | ||
if (typeof self === 'undefined' || self.parent == null) { | ||
@@ -46,21 +50,24 @@ throw new Error( | ||
return { | ||
send(message, transfer) { | ||
return parent.postMessage(message, targetOrigin, transfer); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WindowEventHandlersEventMap, 'message'>( | ||
self, | ||
'message', | ||
{ | ||
signal, | ||
}, | ||
); | ||
return createThread( | ||
{ | ||
send(message, transfer) { | ||
return parent.postMessage(message, targetOrigin, transfer); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WindowEventHandlersEventMap, 'message'>( | ||
self, | ||
'message', | ||
{ | ||
signal, | ||
}, | ||
); | ||
for await (const message of messages) { | ||
if (message.data === CHECK_MESSAGE) continue; | ||
yield message.data; | ||
} | ||
for await (const message of messages) { | ||
if (message.data === CHECK_MESSAGE) continue; | ||
yield message.data; | ||
} | ||
}, | ||
}, | ||
}; | ||
options, | ||
); | ||
} |
import {on} from '@quilted/events'; | ||
import type {ThreadTarget} from '../types.ts'; | ||
import {createThread, type ThreadOptions} from './target.ts'; | ||
export function targetFromMessagePort(port: MessagePort): ThreadTarget { | ||
return { | ||
send(...args: [any, Transferable[]]) { | ||
port.postMessage(...args); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<MessagePortEventMap, 'message'>(port, 'message', { | ||
signal, | ||
}); | ||
export function createThreadFromMessagePort< | ||
Self = Record<string, never>, | ||
Target = Record<string, never>, | ||
>(port: MessagePort, options?: ThreadOptions<Self, Target>) { | ||
return createThread( | ||
{ | ||
send(...args: [any, Transferable[]]) { | ||
port.postMessage(...args); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<MessagePortEventMap, 'message'>(port, 'message', { | ||
signal, | ||
}); | ||
port.start(); | ||
port.start(); | ||
for await (const message of messages) { | ||
yield message.data; | ||
} | ||
for await (const message of messages) { | ||
yield message.data; | ||
} | ||
}, | ||
}, | ||
}; | ||
options, | ||
); | ||
} |
import {on, once} from '@quilted/events'; | ||
import type {ThreadTarget} from '../types.ts'; | ||
import {createThread, type ThreadOptions} from './target.ts'; | ||
export function targetFromBrowserWebSocket(websocket: WebSocket): ThreadTarget { | ||
return { | ||
async send(message) { | ||
if (websocket.readyState !== websocket.OPEN) { | ||
await once(websocket, 'open'); | ||
} | ||
export function createThreadFromBrowserWebSocket< | ||
Self = Record<string, never>, | ||
Target = Record<string, never>, | ||
>(websocket: WebSocket, options?: ThreadOptions<Self, Target>) { | ||
return createThread( | ||
{ | ||
async send(message) { | ||
if (websocket.readyState !== websocket.OPEN) { | ||
await once(websocket, 'open'); | ||
} | ||
websocket.send(JSON.stringify(message)); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WebSocketEventMap, 'message'>(websocket, 'message', { | ||
signal, | ||
}); | ||
websocket.send(JSON.stringify(message)); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WebSocketEventMap, 'message'>( | ||
websocket, | ||
'message', | ||
{ | ||
signal, | ||
}, | ||
); | ||
if (websocket.readyState !== websocket.OPEN) { | ||
await once(websocket, 'open', {signal}); | ||
} | ||
if (websocket.readyState !== websocket.OPEN) { | ||
await once(websocket, 'open', {signal}); | ||
} | ||
if (signal?.aborted) return; | ||
if (signal?.aborted) return; | ||
for await (const message of messages) { | ||
yield JSON.parse(message.data); | ||
} | ||
for await (const message of messages) { | ||
yield JSON.parse(message.data); | ||
} | ||
}, | ||
}, | ||
}; | ||
options, | ||
); | ||
} |
import {on} from '@quilted/events'; | ||
import type {ThreadTarget} from '../types.ts'; | ||
import {createThread, type ThreadOptions} from './target.ts'; | ||
export function targetFromWebWorker(worker: Worker): ThreadTarget { | ||
return { | ||
send(...args: [any, Transferable[]]) { | ||
worker.postMessage(...args); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WorkerEventMap, 'message'>(worker, 'message', { | ||
signal, | ||
}); | ||
export function createThreadFromWebWorker< | ||
Self = Record<string, never>, | ||
Target = Record<string, never>, | ||
>(worker: Worker, options?: ThreadOptions<Self, Target>) { | ||
return createThread( | ||
{ | ||
send(...args: [any, Transferable[]]) { | ||
worker.postMessage(...args); | ||
}, | ||
async *listen({signal}) { | ||
const messages = on<WorkerEventMap, 'message'>(worker, 'message', { | ||
signal, | ||
}); | ||
for await (const message of messages) { | ||
yield message.data; | ||
} | ||
for await (const message of messages) { | ||
yield message.data; | ||
} | ||
}, | ||
}, | ||
}; | ||
options, | ||
); | ||
} |
import {describe, it, expect} from '@quilted/testing'; | ||
import {createThread, targetFromMessagePort} from '../index.ts'; | ||
import {MessageChannel} from './utiltiies.ts'; | ||
import {createThreadFromMessagePort} from '../index.ts'; | ||
import {MessageChannel} from './utilities.ts'; | ||
@@ -12,7 +12,8 @@ describe('thread', () => { | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1); | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: {hello: () => 'world'}, | ||
@@ -30,7 +31,8 @@ }); | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1); | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: { | ||
@@ -50,5 +52,6 @@ greet: async (getName) => `Hello, ${await getName()}!`, | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1); | ||
@@ -58,3 +61,3 @@ let yielded = 0; | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: { | ||
@@ -80,5 +83,6 @@ *iterate() { | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1); | ||
@@ -88,3 +92,3 @@ let yielded = 0; | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: { | ||
@@ -112,8 +116,8 @@ async *iterate() { | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
{signal: abort.signal}, | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1, {signal: abort.signal}); | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: { | ||
@@ -137,8 +141,8 @@ greet: () => 'Hello, world!', | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
{signal: abort.signal}, | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1, {signal: abort.signal}); | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
expose: { | ||
@@ -165,7 +169,8 @@ // eslint-disable-next-line @typescript-eslint/no-empty-function | ||
const {port1, port2} = new MessageChannel(); | ||
const threadOne = createThread<Record<string, never>, EndpointApi>( | ||
targetFromMessagePort(port1), | ||
); | ||
const threadOne = createThreadFromMessagePort< | ||
Record<string, never>, | ||
EndpointApi | ||
>(port1); | ||
createThread<EndpointApi>(targetFromMessagePort(port2), { | ||
createThreadFromMessagePort<EndpointApi>(port2, { | ||
signal: abort.signal, | ||
@@ -172,0 +177,0 @@ expose: { |
@@ -16,3 +16,5 @@ import type { | ||
export interface ThreadExposableFunction<Args extends any[], ReturnType> { | ||
(...args: ThreadSafeArgument<Args>): ReturnType extends Promise<any> | ||
( | ||
...args: ThreadSafeArgument<Args> | ||
): ReturnType extends Promise<any> | ||
? ReturnType | ||
@@ -19,0 +21,0 @@ : ReturnType extends AsyncGenerator<any, any, any> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
205293
124
3773
2
2