Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@quilted/threads

Package Overview
Dependencies
Maintainers
1
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.1.7 to 0.1.8

7

build/typescript/encoding/basic.d.ts
import type { ThreadEncodingStrategy, ThreadEncodingStrategyApi } from '../types';
export declare function createBasicEncoder(api: ThreadEncodingStrategyApi): ThreadEncodingStrategy;
import type { MemoryRetainer } from '../memory';
export declare function createBasicEncoderWithOverrides({ encode: encodeOverride, decode: decodeOverride, }?: {
encode?(value: unknown, api: ThreadEncodingStrategyApi & Pick<ThreadEncodingStrategy, 'encode'>): ReturnType<ThreadEncodingStrategy['encode']> | undefined;
decode?(value: unknown, retainedBy: Iterable<MemoryRetainer> | undefined, api: ThreadEncodingStrategyApi & Pick<ThreadEncodingStrategy, 'decode'>): unknown;
}): (api: ThreadEncodingStrategyApi) => ThreadEncodingStrategy;
export declare const createBasicEncoder: (api: ThreadEncodingStrategyApi) => ThreadEncodingStrategy;
//# sourceMappingURL=basic.d.ts.map

2

build/typescript/encoding/index.d.ts

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

export { createBasicEncoder } from './basic';
export { createBasicEncoder, createBasicEncoderWithOverrides } from './basic';
//# sourceMappingURL=index.d.ts.map

@@ -7,3 +7,3 @@ export { createThread } from './thread';

export { targetFromWebWorker, targetFromMessagePort, targetFromBrowserWebSocket, } from './targets';
export { createBasicEncoder } from './encoding';
export { createBasicEncoder, createBasicEncoderWithOverrides } from './encoding';
export { createThreadAbortSignal, acceptThreadAbortSignal } from './abort';

@@ -10,0 +10,0 @@ export type { ThreadAbortSignal } from './abort';

# @quilted/threads
## 0.1.8
### Patch Changes
- [`86587484`](https://github.com/lemonmade/quilt/commit/86587484846906e194bba956bbd338aa00544625) Thanks [@lemonmade](https://github.com/lemonmade)! - Add basic encoder overrides
## 0.1.7

@@ -4,0 +10,0 @@

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

"type": "module",
"version": "0.1.7",
"version": "0.1.8",
"license": "MIT",

@@ -8,0 +8,0 @@ "engines": {

@@ -19,200 +19,242 @@ import {

export function createBasicEncoder(
api: ThreadEncodingStrategyApi,
): ThreadEncodingStrategy {
const functionsToId = new Map<AnyFunction, string>();
const idsToFunction = new Map<string, AnyFunction>();
const idsToProxy = new Map<string, AnyFunction>();
export function createBasicEncoderWithOverrides({
encode: encodeOverride,
decode: decodeOverride,
}: {
encode?(
value: unknown,
api: ThreadEncodingStrategyApi & Pick<ThreadEncodingStrategy, 'encode'>,
): ReturnType<ThreadEncodingStrategy['encode']> | undefined;
decode?(
value: unknown,
retainedBy: Iterable<MemoryRetainer> | undefined,
api: ThreadEncodingStrategyApi & Pick<ThreadEncodingStrategy, 'decode'>,
): unknown;
} = {}) {
function createBasicEncoder(
api: ThreadEncodingStrategyApi,
): ThreadEncodingStrategy {
const functionsToId = new Map<AnyFunction, string>();
const idsToFunction = new Map<string, AnyFunction>();
const idsToProxy = new Map<string, AnyFunction>();
return {
encode,
decode,
call(id, args) {
const stackFrame = new StackFrame();
const func = idsToFunction.get(id);
const encodeOverrideApi = {...api, encode};
const decodeOverrideApi = {...api, decode};
if (func == null) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
return {
encode,
decode,
call(id, args) {
const stackFrame = new StackFrame();
const func = idsToFunction.get(id);
const retainedBy = isMemoryManageable(func)
? [stackFrame, ...func[RETAINED_BY]]
: [stackFrame];
if (func == null) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
const result = func(...(decode(args, retainedBy) as any[]));
const retainedBy = isMemoryManageable(func)
? [stackFrame, ...func[RETAINED_BY]]
: [stackFrame];
if (result == null || typeof result.then !== 'function') {
stackFrame.release();
}
const result = func(...(decode(args, retainedBy) as any[]));
return (async () => {
try {
const resolved = await result;
return resolved;
} finally {
if (result == null || typeof result.then !== 'function') {
stackFrame.release();
}
})();
},
release(id) {
const func = idsToFunction.get(id);
if (func) {
idsToFunction.delete(id);
functionsToId.delete(func);
}
},
terminate() {
functionsToId.clear();
idsToFunction.clear();
idsToProxy.clear();
},
};
return (async () => {
try {
const resolved = await result;
return resolved;
} finally {
stackFrame.release();
}
})();
},
release(id) {
const func = idsToFunction.get(id);
function encode(value: unknown): [any, Transferable[]?] {
if (typeof value === 'object') {
if (value == null) {
return [value];
}
if (func) {
idsToFunction.delete(id);
functionsToId.delete(func);
}
},
terminate() {
functionsToId.clear();
idsToFunction.clear();
idsToProxy.clear();
},
};
const transferables: Transferable[] = [];
const encodeValue = (value: any) => {
const [fieldValue, nestedTransferables = []] = encode(value);
transferables.push(...nestedTransferables);
return fieldValue;
};
function encode(
value: unknown,
context: {encoded: WeakSet<any>} = {encoded: new WeakSet()},
): [any, Transferable[]?] {
const override = encodeOverride?.(value, encodeOverrideApi);
if (typeof (value as any)[ENCODE_METHOD] === 'function') {
const result = (value as ThreadEncodable)[ENCODE_METHOD]({
encode: encodeValue,
});
if (override) return override;
return [result, transferables];
}
if (typeof value === 'object') {
if (value == null) {
return [value];
}
if (Array.isArray(value)) {
const result = value.map((item) => encodeValue(item));
if (context.encoded.has(value)) {
return [undefined];
}
context.encoded.add(value);
const transferables: Transferable[] = [];
const encodeValue = (value: any) => {
const [fieldValue, nestedTransferables = []] = encode(value, context);
transferables.push(...nestedTransferables);
return fieldValue;
};
if (typeof (value as any)[ENCODE_METHOD] === 'function') {
const result = (value as ThreadEncodable)[ENCODE_METHOD]({
encode: encodeValue,
});
return [result, transferables];
}
if (Array.isArray(value)) {
const result = value.map((item) => encodeValue(item));
return [result, transferables];
}
const result: Record<string, any> = {};
for (const key of Object.keys(value)) {
result[key] = encodeValue((value as any)[key]);
}
if (
(Symbol.asyncIterator in value || Symbol.iterator in value) &&
typeof (value as any).next === 'function'
) {
result.next ??= encodeValue((value as any).next.bind(value));
result.return ??= encodeValue((value as any).return.bind(value));
result.throw ??= encodeValue((value as any).throw.bind(value));
result[ASYNC_ITERATOR] = true;
}
return [result, transferables];
}
const result: Record<string, any> = {};
if (typeof value === 'function') {
if (functionsToId.has(value)) {
const id = functionsToId.get(value)!;
return [{[FUNCTION]: id}];
}
for (const key of Object.keys(value)) {
result[key] = encodeValue((value as any)[key]);
}
const id = api.uuid();
if (
(Symbol.asyncIterator in value || Symbol.iterator in value) &&
typeof (value as any).next === 'function'
) {
result.next ??= encodeValue((value as any).next.bind(value));
result.return ??= encodeValue((value as any).return.bind(value));
result.throw ??= encodeValue((value as any).throw.bind(value));
result[ASYNC_ITERATOR] = true;
functionsToId.set(value, id);
idsToFunction.set(id, value);
return [{[FUNCTION]: id}];
}
return [result, transferables];
return [value];
}
if (typeof value === 'function') {
if (functionsToId.has(value)) {
const id = functionsToId.get(value)!;
return [{[FUNCTION]: id}];
}
function decode(
value: unknown,
retainedBy?: Iterable<MemoryRetainer>,
): any {
const override = decodeOverride?.(value, retainedBy, decodeOverrideApi);
const id = api.uuid();
if (override) return override;
functionsToId.set(value, id);
idsToFunction.set(id, value);
if (typeof value === 'object') {
if (value == null) {
return value as any;
}
return [{[FUNCTION]: id}];
}
if (Array.isArray(value)) {
return value.map((value) => decode(value, retainedBy));
}
return [value];
}
if (FUNCTION in value) {
const id = (value as {[FUNCTION]: string})[FUNCTION];
function decode(value: unknown, retainedBy?: Iterable<MemoryRetainer>): any {
if (typeof value === 'object') {
if (value == null) {
return value as any;
}
if (idsToProxy.has(id)) {
return idsToProxy.get(id)! as any;
}
if (Array.isArray(value)) {
return value.map((value) => decode(value, retainedBy));
}
let retainCount = 0;
let released = false;
if (FUNCTION in value) {
const id = (value as {[FUNCTION]: string})[FUNCTION];
const release = () => {
retainCount -= 1;
if (idsToProxy.has(id)) {
return idsToProxy.get(id)! as any;
}
if (retainCount === 0) {
released = true;
idsToProxy.delete(id);
api.release(id);
}
};
let retainCount = 0;
let released = false;
const retain = () => {
retainCount += 1;
};
const release = () => {
retainCount -= 1;
const retainers = new Set(retainedBy);
if (retainCount === 0) {
released = true;
idsToProxy.delete(id);
api.release(id);
}
};
const proxy = (...args: any[]) => {
if (released) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
const retain = () => {
retainCount += 1;
};
if (!idsToProxy.has(id)) {
throw new Error(
'You attempted to call a function that was already revoked.',
);
}
const retainers = new Set(retainedBy);
return api.call(id, args);
};
const proxy = (...args: any[]) => {
if (released) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
Object.defineProperties(proxy, {
[RELEASE_METHOD]: {value: release, writable: false},
[RETAIN_METHOD]: {value: retain, writable: false},
[RETAINED_BY]: {value: retainers, writable: false},
});
if (!idsToProxy.has(id)) {
throw new Error(
'You attempted to call a function that was already revoked.',
);
for (const retainer of retainers) {
retainer.add(proxy as any);
}
return api.call(id, args);
};
idsToProxy.set(id, proxy);
Object.defineProperties(proxy, {
[RELEASE_METHOD]: {value: release, writable: false},
[RETAIN_METHOD]: {value: retain, writable: false},
[RETAINED_BY]: {value: retainers, writable: false},
});
for (const retainer of retainers) {
retainer.add(proxy as any);
return proxy as any;
}
idsToProxy.set(id, proxy);
const result: Record<string | symbol, any> = {};
return proxy as any;
}
for (const key of Object.keys(value)) {
if (key === ASYNC_ITERATOR) {
result[Symbol.asyncIterator] = () => result;
} else {
result[key] = decode((value as any)[key], retainedBy);
}
}
const result: Record<string | symbol, any> = {};
for (const key of Object.keys(value)) {
if (key === ASYNC_ITERATOR) {
result[Symbol.asyncIterator] = () => result;
} else {
result[key] = decode((value as any)[key], retainedBy);
}
return result;
}
return result;
return value;
}
}
return value;
}
return createBasicEncoder;
}
export const createBasicEncoder = createBasicEncoderWithOverrides();

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

export {createBasicEncoder} from './basic';
export {createBasicEncoder, createBasicEncoderWithOverrides} from './basic';

@@ -16,3 +16,3 @@ export {createThread} from './thread';

} from './targets';
export {createBasicEncoder} from './encoding';
export {createBasicEncoder, createBasicEncoderWithOverrides} from './encoding';
export {createThreadAbortSignal, acceptThreadAbortSignal} from './abort';

@@ -19,0 +19,0 @@ export type {ThreadAbortSignal} from './abort';

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