New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@quilted/threads

Package Overview
Dependencies
Maintainers
0
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@quilted/threads - npm Package Compare versions

Comparing version 0.0.0-preview-20240817164832 to 0.0.0-preview-20240826020905

2

build/typescript/index.d.ts
export { markAsTransferable } from './transfer.ts';
export { RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY, retain, release, StackFrame, isMemoryManageable, type MemoryManageable, type MemoryRetainer, } from './memory.ts';
export { MESSAGE_CALL, MESSAGE_CALL_RESULT, MESSAGE_FUNCTION_CALL, MESSAGE_FUNCTION_RESULT, SERIALIZE_METHOD, TRANSFERABLE, } from './constants.ts';
export { Thread, type AnyThread, type ThreadOptions, type ThreadImports, type ThreadMessageTarget, type ThreadFunctions, type ThreadSerialization, type ThreadMessageMap, } from './Thread.ts';
export { Thread, type AnyThread, type ThreadOptions, type ThreadImports, type ThreadMessageTarget, type ThreadFunctions, type ThreadSerialization, type ThreadMessageMap, type ThreadSerializationOptions, } from './Thread.ts';
export { ThreadBroadcastChannel } from './threads/ThreadBroadcastChannel.ts';

@@ -6,0 +6,0 @@ export { ThreadBrowserWebSocket } from './threads/ThreadBrowserWebSocket.ts';

@@ -1,2 +0,2 @@

import type { AnyThread, ThreadSerialization } from '../Thread.ts';
import type { AnyThread, ThreadSerialization, ThreadSerializationOptions } from '../Thread.ts';
/**

@@ -16,2 +16,3 @@ * A thread serialization that can transfer an extended set of JavaScript types, by converting

#private;
constructor(options?: ThreadSerializationOptions);
/**

@@ -18,0 +19,0 @@ * Serializes a value into a JSON-compatible format that can be transferred between threads.

@@ -1,2 +0,2 @@

import type { AnyThread, ThreadSerialization } from '../Thread.ts';
import type { AnyThread, ThreadSerialization, ThreadSerializationOptions } from '../Thread.ts';
/**

@@ -14,2 +14,3 @@ * A thread encoder that can transfer supports a wide variety of JavaScript types by

#private;
constructor(options?: ThreadSerializationOptions);
/**

@@ -16,0 +17,0 @@ * Serializes a value into a structured cloning-compatible format that can be transferred between threads.

@@ -55,2 +55,19 @@ import type { AnyFunction } from './types.ts';

/**
* Options to customize the creation of a `ThreadSerialization` instance.
*/
export interface ThreadSerializationOptions {
/**
* A custom function to run when serializing values. If this function returns `undefined`,
* the default serialization will be used. You can also call the second argument to this function
* to apply the default serialization to subsets of the value.
*/
serialize?(value: object, defaultSerialize: (value: unknown) => unknown, thread: AnyThread, transferable?: any[]): any | undefined;
/**
* A custom function to run when deserializing values. If this function returns `undefined`,
* the default deserialization will be used. You can also call the second argument to this function
* to apply the default deserialization to subsets of the value.
*/
deserialize?(value: object, defaultDeserialize: (value: unknown) => unknown, thread: AnyThread): any | undefined;
}
/**
* Options to customize the creation of a `Thread` instance.

@@ -57,0 +74,0 @@ */

@@ -64,3 +64,7 @@ /**

static serialize(signal: Pick<AbortSignal, 'aborted' | 'addEventListener'>, { retain, release }?: ThreadAbortSignalOptions): ThreadAbortSignalSerialization;
/**
* Checks if a value is a serialized ThreadSignal.
*/
static isSerialized(value: unknown): value is ThreadAbortSignalSerialization;
}
//# sourceMappingURL=ThreadAbortSignal.d.ts.map

@@ -60,2 +60,6 @@ import { Signal, type ReadonlySignal } from '@preact/signals-core';

static serialize<T>(signal: ReadonlySignal<T>, { writable, signal: abortSignal, retain, release, }?: ThreadSignalOptions): ThreadSignalSerialization<T>;
/**
* Checks if a value is a serialized ThreadSignal.
*/
static isSerialized<T = unknown>(value: unknown): value is ThreadSignalSerialization<T>;
}

@@ -62,0 +66,0 @@ /**

# @quilted/threads
## 0.0.0-preview-20240817164832
## 0.0.0-preview-20240826020905
### Major Changes
### Minor Changes
- Changed `ThreadAbortSignal` utilities to be class-based instead of being a collection of utility functions. This change aligns the API more closely with `AbortController` in the browser, which is created with `new AbortController()`.
- Add custom `serialize` and `deserialize` options to both thread serialization implementations
Previously, you used `createThreadAbortSignal()` to serialize an `AbortSignal` to pass over a thread, and `acceptThreadAbortSignal()` to turn it into a “live” `AbortSignal`. With the new API, you will do the same steps, but with `ThreadAbortSignal.serialize()` and `new ThreadAbortSignal`:
- Add methods to check for `ThreadSignal` and `ThreadAbortSignal`
```ts
import {
createThreadAbortSignal,
acceptThreadAbortSignal,
} from '@quilted/threads';
## 3.1.0
const abortController = new AbortController();
const serializedAbortSignal = createThreadAbortSignal(abortController.signal);
const liveAbortSignal = acceptThreadAbortSignal(serializedAbortSignal);
### Minor Changes
await fetch('/', {signal: liveAbortSignal});
- [`f2463ec`](https://github.com/lemonmade/quilt/commit/f2463ec87c1af107fcfa0f307765912c9f86e29b) Thanks [@lemonmade](https://github.com/lemonmade)! - Add custom `serialize` and `deserialize` options to both thread serialization implementations
// Becomes:
- [`b5ca2bd`](https://github.com/lemonmade/quilt/commit/b5ca2bd058f650509f062c609b5a49a39e0b4823) Thanks [@lemonmade](https://github.com/lemonmade)! - Add methods to check for `ThreadSignal` and `ThreadAbortSignal`
import { ThreadAbortSignal } from '@quilted/threads';\
const abortController = new AbortController();
const serializedAbortSignal = ThreadAbortSignal.serialize(abortController.signal);
const liveAbortSignal = new ThreadAbortSignal(serializedAbortSignal);
await fetch('/', {signal: liveAbortSignal});
```
Additionally, the new `ThreadAbortSignal` class assumes you are not doing manual memory management by default. If your target environment does not support automatic memory management of transferred functions, you will need to manually pass the `retain` and `release` functions to the new APIs:
```ts
import {retain, release, ThreadAbortSignal} from '@quilted/threads';
const abortController = new AbortController();
const serializedAbortSignal = ThreadAbortSignal.serialize(
abortController.signal,
{retain, release},
);
const liveAbortSignal = new ThreadAbortSignal(serializedAbortSignal, {
retain,
release,
});
await fetch('/', {signal: liveAbortSignal});
```
- Refactored the API for creating threads. The new APIs are class based, and now use module-style language to define the functions shared between threads: `exports` when creating a thread indicates the methods that can be called, and `imports` allows you to call those methods in the paired thread.
For example, you previously used `createThreadFromWebWorker()` to create a thread from a web worker. Now, you use the `ThreadWebWorker` class:
```js
// Old API:
import {createThreadFromWebWorker} from '@quilted/threads';
// Parent page
const worker = new Worker('worker.js');
const thread = createThreadFromWebWorker(worker);
const result = await thread.doWork();
// Worker
createThreadFromWebWorker(self, {
expose: {
async doWork() {
/* ... */
},
},
});
// ---
// New API:
import {ThreadWebWorker} from '@quilted/threads';
// Parent
const worker = new Worker('worker.js');
const thread = new ThreadWebWorker(worker);
const result = await thread.imports.doWork();
// Worker
new ThreadWebWorker(worker, {
exports: {
async doWork() {
/* ... */
},
},
});
```
Additionally, the threads library now exports two additional helpers for turning web objects into threads: `ThreadWindow` and `ThreadNestedWindow`, which can be used to create a communication channel between a parent page and popup windows or tabs.
- Changed Preact thread utilities to be class-based instead of being a collection of utility functions.
Previously, you used `createThreadSignal()` to serialize a Preact signal to pass over a thread, and `acceptThreadSignal()` to turn it into a "live" signal. With the new API, you will do the same steps, but with `ThreadSignal.serialize()` and `new ThreadSignal()`:
```js
import {signal, computed} from '@preact/signals-core';
import {ThreadWebWorker, ThreadSignal} from '@quilted/threads';
// Old API:
const result = signal(32);
const serializedSignal = createThreadSignal(result);
await thread.imports.calculateResult(serializedSignal);
// New API:
const result = signal(32);
const serializedSignal = ThreadSignal.serialize(result);
await thread.imports.calculateResult(serializedSignal);
// In the target thread:
// Old API:
function calculateResult(resultThreadSignal) {
const result = acceptThreadSignal(resultThreadSignal);
const computedSignal = computed(
() => `Result from thread: ${result.value}`,
);
// ...
}
// New API:
function calculateResult(resultThreadSignal) {
const result = new ThreadSignal(resultThreadSignal);
const computedSignal = computed(
() => `Result from thread: ${result.value}`,
);
// ...
}
```
### Patch Changes
- Updated dependencies []:
- @quilted/events@0.0.0-preview-20240817164832
## 3.0.0

@@ -140,0 +20,0 @@

@@ -5,3 +5,3 @@ {

"type": "module",
"version": "0.0.0-preview-20240817164832",
"version": "0.0.0-preview-20240826020905",
"license": "MIT",

@@ -44,3 +44,3 @@ "engines": {

"dependencies": {
"@quilted/events": "0.0.0-preview-20240817164832"
"@quilted/events": "^2.1.1"
},

@@ -47,0 +47,0 @@ "peerDependencies": {

@@ -31,2 +31,3 @@ export {markAsTransferable} from './transfer.ts';

type ThreadMessageMap,
type ThreadSerializationOptions,
} from './Thread.ts';

@@ -33,0 +34,0 @@ export {ThreadBroadcastChannel} from './threads/ThreadBroadcastChannel.ts';

import type {ThreadSerializable} from '../types.ts';
import type {AnyThread, ThreadSerialization} from '../Thread.ts';
import type {
AnyThread,
ThreadSerialization,
ThreadSerializationOptions,
} from '../Thread.ts';
import {SERIALIZE_METHOD, TRANSFERABLE} from '../constants.ts';

@@ -32,2 +36,10 @@

export class ThreadSerializationJSON implements ThreadSerialization {
readonly #customSerializer?: ThreadSerializationOptions['serialize'];
readonly #customDeserializer?: ThreadSerializationOptions['deserialize'];
constructor(options?: ThreadSerializationOptions) {
this.#customSerializer = options?.serialize;
this.#customDeserializer = options?.deserialize;
}
/**

@@ -45,2 +57,3 @@ * Serializes a value into a JSON-compatible format that can be transferred between threads.

seen = new Map<unknown, unknown>(),
isApplyingDefault = false,
): any {

@@ -55,2 +68,17 @@ if (value == null) return value;

if (typeof value === 'object') {
if (this.#customSerializer && !isApplyingDefault) {
const customValue = this.#customSerializer(
value,
(value) =>
this.#serializeInternal(value, thread, transferable, seen, true),
thread,
transferable,
);
if (customValue !== undefined) {
seen.set(value, customValue);
return customValue;
}
}
if ((value as any)[TRANSFERABLE]) {

@@ -194,4 +222,22 @@ transferable?.push(value as any);

#deserializeInternal(value: unknown, thread: AnyThread): any {
#deserializeInternal(
value: unknown,
thread: AnyThread,
isApplyingDefault = false,
): any {
if (value == null) return value;
if (typeof value === 'object') {
if (this.#customDeserializer && !isApplyingDefault) {
const customValue = this.#customDeserializer(
value,
(value) => this.#deserializeInternal(value, thread, true),
thread,
);
if (customValue !== undefined) {
return customValue;
}
}
if (value == null) {

@@ -198,0 +244,0 @@ return value as any;

import type {ThreadSerializable} from '../types.ts';
import type {AnyThread, ThreadSerialization} from '../Thread.ts';
import type {
AnyThread,
ThreadSerialization,
ThreadSerializationOptions,
} from '../Thread.ts';
import {SERIALIZE_METHOD, TRANSFERABLE} from '../constants.ts';

@@ -21,2 +25,10 @@

export class ThreadSerializationStructuredClone implements ThreadSerialization {
readonly #customSerializer?: ThreadSerializationOptions['serialize'];
readonly #customDeserializer?: ThreadSerializationOptions['deserialize'];
constructor(options?: ThreadSerializationOptions) {
this.#customSerializer = options?.serialize;
this.#customDeserializer = options?.deserialize;
}
/**

@@ -34,2 +46,3 @@ * Serializes a value into a structured cloning-compatible format that can be transferred between threads.

seen = new Map<unknown, unknown>(),
isApplyingDefault = false,
): any {

@@ -44,2 +57,17 @@ if (value == null) return value;

if (typeof value === 'object') {
if (this.#customSerializer && !isApplyingDefault) {
const customValue = this.#customSerializer(
value,
(value) =>
this.#serializeInternal(value, thread, transferable, seen, true),
thread,
transferable,
);
if (customValue !== undefined) {
seen.set(value, customValue);
return customValue;
}
}
if ((value as any)[TRANSFERABLE]) {

@@ -135,4 +163,22 @@ transferable?.push(value as any);

#deserializeInternal(value: unknown, thread: AnyThread): any {
#deserializeInternal(
value: unknown,
thread: AnyThread,
isApplyingDefault = false,
): any {
if (value == null) return value;
if (typeof value === 'object') {
if (this.#customDeserializer && !isApplyingDefault) {
const customValue = this.#customDeserializer(
value,
(value) => this.#deserializeInternal(value, thread, true),
thread,
);
if (customValue !== undefined) {
return customValue;
}
}
if (value == null) {

@@ -139,0 +185,0 @@ return value as any;

@@ -82,2 +82,30 @@ import {NestedAbortController} from '@quilted/events';

/**
* Options to customize the creation of a `ThreadSerialization` instance.
*/
export interface ThreadSerializationOptions {
/**
* A custom function to run when serializing values. If this function returns `undefined`,
* the default serialization will be used. You can also call the second argument to this function
* to apply the default serialization to subsets of the value.
*/
serialize?(
value: object,
defaultSerialize: (value: unknown) => unknown,
thread: AnyThread,
transferable?: any[],
): any | undefined;
/**
* A custom function to run when deserializing values. If this function returns `undefined`,
* the default deserialization will be used. You can also call the second argument to this function
* to apply the default deserialization to subsets of the value.
*/
deserialize?(
value: object,
defaultDeserialize: (value: unknown) => unknown,
thread: AnyThread,
): any | undefined;
}
/**
* Options to customize the creation of a `Thread` instance.

@@ -84,0 +112,0 @@ */

@@ -181,2 +181,14 @@ /**

}
/**
* Checks if a value is a serialized ThreadSignal.
*/
static isSerialized(value: unknown): value is ThreadAbortSignalSerialization {
return (
typeof value === 'object' &&
value != null &&
typeof (value as any).aborted === 'boolean' &&
typeof (value as any).start === 'function'
);
}
}

@@ -183,0 +195,0 @@

@@ -175,2 +175,15 @@ import {Signal, type ReadonlySignal} from '@preact/signals-core';

}
/**
* Checks if a value is a serialized ThreadSignal.
*/
static isSerialized<T = unknown>(
value: unknown,
): value is ThreadSignalSerialization<T> {
return (
typeof value === 'object' &&
value != null &&
typeof (value as any).start === 'function'
);
}
}

@@ -177,0 +190,0 @@

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc