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.0.0-fix-types-20220529011148 to 0.0.0-preview-20230116035648

build/cjs/_virtual/_rollupPluginBabelHelpers.cjs

2

build/typescript/abort.d.ts

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

export declare type ThreadAbortSignal = {
export type ThreadAbortSignal = {
aborted: true;

@@ -3,0 +3,0 @@ start?: never;

export declare const RETAIN_METHOD: unique symbol;
export declare const RELEASE_METHOD: unique symbol;
export declare const RETAINED_BY: unique symbol;
export declare const ENCODE_METHOD: unique symbol;
//# sourceMappingURL=constants.d.ts.map
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

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

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

@@ -5,8 +5,8 @@ export { createThread } from './thread';

export type { MemoryManageable, MemoryRetainer } from './memory';
export { RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY } from './constants';
export { RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY, ENCODE_METHOD, } from './constants';
export { targetFromWebWorker, targetFromMessagePort, targetFromBrowserWebSocket, } from './targets';
export { createBasicEncoder } from './encoding';
export { createBasicEncoder, createBasicEncoderWithOverrides } from './encoding';
export { createThreadAbortSignal, acceptThreadAbortSignal } from './abort';
export type { ThreadAbortSignal } from './abort';
export type { Thread, ThreadTarget, ThreadCallable, ThreadExposable, ThreadSafeArgument, ThreadSafeReturnType, ThreadEncodingStrategy, ThreadEncodingStrategyApi, AnyFunction, } from './types';
export type { Thread, ThreadTarget, ThreadCallable, ThreadExposable, ThreadSafeArgument, ThreadSafeReturnType, ThreadEncodingStrategy, ThreadEncodingStrategyApi, ThreadEncodable, AnyFunction, } from './types';
//# sourceMappingURL=index.d.ts.map

@@ -17,2 +17,3 @@ import { RETAINED_BY, RETAIN_METHOD, RELEASE_METHOD } from './constants';

}): boolean;
export declare function isBasicObject(value: unknown): boolean;
//# sourceMappingURL=memory.d.ts.map

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

import type { RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY } from './constants';
export declare type Thread<Target> = ThreadCallable<Target>;
import type { RELEASE_METHOD, RETAIN_METHOD, ENCODE_METHOD, RETAINED_BY } from './constants';
export type Thread<Target> = ThreadCallable<Target>;
export interface ThreadTarget {

@@ -12,3 +12,3 @@ send(message: any, transferables?: Transferable[]): void;

}
export declare type ThreadExposable<T> = {
export type ThreadExposable<T> = {
[K in keyof T]: T[K] extends (...args: infer Args) => infer ReturnType ? ThreadExposableFunction<Args, ReturnType> : never;

@@ -19,10 +19,10 @@ };

}
export declare type ThreadCallable<T> = {
export type ThreadCallable<T> = {
[K in keyof T]: T[K] extends (...args: infer Args) => infer ReturnType ? ThreadCallableFunction<Args, ReturnType> : never;
};
export declare type MaybePromise<T> = T extends Promise<any> ? T : T | Promise<T>;
export declare type ThreadSafeReturnType<T> = T extends AsyncGenerator<any, any, any> ? T : T extends Generator<infer T, infer R, infer N> ? AsyncGenerator<T, R, N> : T extends Promise<any> ? T : T extends infer U | Promise<infer U> ? Promise<U> : T extends (...args: infer Args) => infer TypeReturned ? (...args: Args) => ThreadSafeReturnType<TypeReturned> : T extends (infer ArrayElement)[] ? ThreadSafeReturnType<ArrayElement>[] : T extends readonly (infer ArrayElement)[] ? readonly ThreadSafeReturnType<ArrayElement>[] : T extends object ? {
export type MaybePromise<T> = T extends Promise<any> ? T : T | Promise<T>;
export type ThreadSafeReturnType<T> = T extends AsyncGenerator<any, any, any> ? T : T extends Generator<infer T, infer R, infer N> ? AsyncGenerator<T, R, N> : T extends Promise<any> ? T : T extends infer U | Promise<infer U> ? Promise<U> : T extends (...args: infer Args) => infer TypeReturned ? (...args: Args) => ThreadSafeReturnType<TypeReturned> : T extends (infer ArrayElement)[] ? ThreadSafeReturnType<ArrayElement>[] : T extends readonly (infer ArrayElement)[] ? readonly ThreadSafeReturnType<ArrayElement>[] : T extends object ? {
[K in keyof T]: ThreadSafeReturnType<T[K]>;
} : T;
export declare type ThreadSafeArgument<T> = T extends (...args: infer Args) => infer TypeReturned ? TypeReturned extends Promise<any> ? (...args: Args) => TypeReturned : TypeReturned extends AsyncGenerator<any, any, any> ? (...args: Args) => TypeReturned : TypeReturned extends Generator<infer T, infer R, infer N> ? (...args: Args) => AsyncGenerator<T, R, N> : TypeReturned extends boolean ? (...args: Args) => boolean | Promise<boolean> : (...args: Args) => TypeReturned | Promise<TypeReturned> : {
export type ThreadSafeArgument<T> = T extends (...args: infer Args) => infer TypeReturned ? TypeReturned extends Promise<any> ? (...args: Args) => TypeReturned : TypeReturned extends AsyncGenerator<any, any, any> ? (...args: Args) => TypeReturned : TypeReturned extends Generator<infer T, infer R, infer N> ? (...args: Args) => AsyncGenerator<T, R, N> : TypeReturned extends boolean ? (...args: Args) => boolean | Promise<boolean> : (...args: Args) => TypeReturned | Promise<TypeReturned> : {
[K in keyof T]: ThreadSafeArgument<T[K]>;

@@ -50,3 +50,8 @@ };

}
export declare type AnyFunction = Function;
export interface ThreadEncodable {
[ENCODE_METHOD](api: {
encode(value: any): unknown;
}): any;
}
export type AnyFunction = Function;
//# sourceMappingURL=types.d.ts.map
# @quilted/threads
## 0.0.0-fix-types-20220529011148
## 0.0.0-preview-20230116035648
### Patch Changes
- [#331](https://github.com/lemonmade/quilt/pull/331) [`f356dc06`](https://github.com/lemonmade/quilt/commit/f356dc067628550114b8e2a06b6878a1506bbed2) Thanks [@lemonmade](https://github.com/lemonmade)! - Fix React types in stricter package managers
- Remove need for @babel/runtime peer dependency
- Updated dependencies [[`f356dc06`](https://github.com/lemonmade/quilt/commit/f356dc067628550114b8e2a06b6878a1506bbed2)]:
- @quilted/events@0.0.0-fix-types-20220529011148
- Updated dependencies []:
- @quilted/events@0.0.0-preview-20230116035648
## 0.1.11
### Patch Changes
- [`8f1d275b`](https://github.com/lemonmade/quilt/commit/8f1d275b6de0abbc6f61bcd5401555f6480eb474) Thanks [@lemonmade](https://github.com/lemonmade)! - Remove need for @babel/runtime peer dependency
## 0.1.10
### Patch Changes
- [`8afad785`](https://github.com/lemonmade/quilt/commit/8afad7855d8f8f7d9ca8f9caaa8cbfd79a6432d0) Thanks [@lemonmade](https://github.com/lemonmade)! - Improve self-referencing detection in threads
* [`9df5024d`](https://github.com/lemonmade/quilt/commit/9df5024d1594fcdc16d51c8bbb1ae7f26026ae43) Thanks [@lemonmade](https://github.com/lemonmade)! - Fix custom encoders and decoders returning falsy values
## 0.1.9
### Patch Changes
- [`df9713c5`](https://github.com/lemonmade/quilt/commit/df9713c5b296b439c5947595f47e41448b5c8282) Thanks [@lemonmade](https://github.com/lemonmade)! - Add self-referencing detection to encoder
## 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
### Patch Changes
- [`163db45f`](https://github.com/lemonmade/quilt/commit/163db45f7a398a66d4ac0bac0dc5e6c3b3a62144) Thanks [@lemonmade](https://github.com/lemonmade)! - Add custom encoding method
## 0.1.6
### Patch Changes
- [`a12c3576`](https://github.com/lemonmade/quilt/commit/a12c357693b173461f51a35fb7efdd0a9267e471) Thanks [@lemonmade](https://github.com/lemonmade)! - Fix more build issues
## 0.1.5
### Patch Changes
- [`0629288e`](https://github.com/lemonmade/quilt/commit/0629288ee4ba2e2ccfd73fbb216c3559e1a5c77e) Thanks [@lemonmade](https://github.com/lemonmade)! - Fix missing package builds
## 0.1.4
### Patch Changes
- [#364](https://github.com/lemonmade/quilt/pull/364) [`4dc1808a`](https://github.com/lemonmade/quilt/commit/4dc1808a86d15e821b218b528617430cbd8b5b48) Thanks [@lemonmade](https://github.com/lemonmade)! - Update to simplified Quilt config
## 0.1.3
### Patch Changes
- [#359](https://github.com/lemonmade/quilt/pull/359) [`2eceac54`](https://github.com/lemonmade/quilt/commit/2eceac546fa3ee3e2c4d2887ab4a6a021acb52cd) Thanks [@lemonmade](https://github.com/lemonmade)! - Update TypeScript and ESLint to latest versions
## 0.1.2
### Patch Changes
- [#331](https://github.com/lemonmade/quilt/pull/331) [`efc54f75`](https://github.com/lemonmade/quilt/commit/efc54f75cb29ec4143a8e52f577edff518014a6b) Thanks [@lemonmade](https://github.com/lemonmade)! - Fix React types in stricter package managers
## 0.1.1

@@ -13,0 +75,0 @@

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

"type": "module",
"version": "0.0.0-fix-types-20220529011148",
"version": "0.0.0-preview-20230116035648",
"license": "MIT",

@@ -22,2 +22,4 @@ "engines": {

".": {
"types": "./build/typescript/index.d.ts",
"quilt:source": "./source/index.ts",
"quilt:esnext": "./build/esnext/index.esnext",

@@ -31,17 +33,12 @@ "import": "./build/esm/index.mjs",

"dependencies": {
"@quilted/events": "^0.0.0-fix-types-20220529011148"
"@quilted/events": "0.0.0-preview-20230116035648"
},
"peerDependencies": {
"@babel/runtime": ">=7.0.0 <8.0.0"
"devDependencies": {
"@quilted/testing": "0.0.0-preview-20230116035648"
},
"peerDependenciesMeta": {
"@babel/runtime": {
"optional": true
}
},
"eslintConfig": {
"extends": [
"@quilted/eslint-config/package"
"@quilted/eslint-config/project"
]
}
}

@@ -1,6 +0,5 @@

import {createPackage, quiltPackage} from '@quilted/craft';
import {createProject, quiltPackage} from '@quilted/craft';
export default createPackage((pkg) => {
pkg.entry({source: './source/index.ts'});
pkg.use(quiltPackage());
export default createProject((project) => {
project.use(quiltPackage());
});
export const RETAIN_METHOD = Symbol.for('Threads::Retain');
export const RELEASE_METHOD = Symbol.for('Threads::Release');
export const RETAINED_BY = Symbol.for('Threads::RetainedBy');
export const ENCODE_METHOD = Symbol.for('Threads::Encode');

@@ -1,9 +0,19 @@

import {RETAINED_BY, RETAIN_METHOD, RELEASE_METHOD} from '../constants';
import {
RETAINED_BY,
RETAIN_METHOD,
ENCODE_METHOD,
RELEASE_METHOD,
} from '../constants';
import type {
ThreadEncodingStrategy,
ThreadEncodingStrategyApi,
ThreadEncodable,
AnyFunction,
} from '../types';
import type {MemoryRetainer} from '../memory';
import {StackFrame, isMemoryManageable} from '../memory';
import {
StackFrame,
isBasicObject,
isMemoryManageable,
type MemoryRetainer,
} from '../memory';

@@ -13,192 +23,270 @@ const FUNCTION = '_@f';

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;
};
type EncodeResult = ReturnType<ThreadEncodingStrategy['encode']>;
if (Array.isArray(value)) {
const result = value.map((item) => encodeValue(item));
return [result, transferables];
}
function encode(
value: unknown,
seen: Map<any, EncodeResult> = new Map(),
): EncodeResult {
if (value == null) return [value];
const result: Record<string, any> = {};
const seenValue = seen.get(value);
if (seenValue) return seenValue;
for (const key of Object.keys(value)) {
result[key] = encodeValue((value as any)[key]);
}
seen.set(value, [undefined]);
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;
const override = encodeOverride?.(value, encodeOverrideApi);
if (override !== undefined) {
seen.set(value, override);
return override;
}
return [result, transferables];
}
if (typeof value === 'object') {
const transferables: Transferable[] = [];
const encodeValue = (value: any) => {
const [fieldValue, nestedTransferables = []] = encode(value, seen);
transferables.push(...nestedTransferables);
return fieldValue;
};
if (typeof value === 'function') {
if (functionsToId.has(value)) {
const id = functionsToId.get(value)!;
return [{[FUNCTION]: id}];
}
if (typeof (value as any)[ENCODE_METHOD] === 'function') {
const result = (value as ThreadEncodable)[ENCODE_METHOD]({
encode: encodeValue,
});
const id = api.uuid();
const fullResult: EncodeResult = [result, transferables];
seen.set(value, fullResult);
functionsToId.set(value, id);
idsToFunction.set(id, value);
return [result, transferables];
}
return [{[FUNCTION]: id}];
}
if (Array.isArray(value)) {
const result = value.map((item) => encodeValue(item));
const fullResult: EncodeResult = [result, transferables];
seen.set(value, fullResult);
return [value];
}
return fullResult;
}
function decode(value: unknown, retainedBy?: Iterable<MemoryRetainer>): any {
if (typeof value === 'object') {
if (value == null) {
return value as any;
const valueIsIterator = isIterator(value);
if (isBasicObject(value) || valueIsIterator) {
const result: Record<string, any> = {};
for (const key of Object.keys(value)) {
result[key] = encodeValue((value as any)[key]);
}
if (valueIsIterator) {
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;
}
const fullResult: EncodeResult = [result, transferables];
seen.set(value, fullResult);
return fullResult;
}
}
if (Array.isArray(value)) {
return value.map((value) => decode(value, retainedBy));
if (typeof value === 'function') {
if (functionsToId.has(value)) {
const id = functionsToId.get(value)!;
const result: EncodeResult = [{[FUNCTION]: id}];
seen.set(value, result);
return result;
}
const id = api.uuid();
functionsToId.set(value, id);
idsToFunction.set(id, value);
const result: EncodeResult = [{[FUNCTION]: id}];
seen.set(value, result);
return result;
}
if (FUNCTION in value) {
const id = (value as {[FUNCTION]: string})[FUNCTION];
const result: EncodeResult = [value];
seen.set(value, result);
if (idsToProxy.has(id)) {
return idsToProxy.get(id)! as any;
return result;
}
function decode(
value: unknown,
retainedBy?: Iterable<MemoryRetainer>,
): any {
const override = decodeOverride?.(value, retainedBy, decodeOverrideApi);
if (override !== undefined) return override;
if (typeof value === 'object') {
if (value == null) {
return value as any;
}
let retainCount = 0;
let released = false;
if (Array.isArray(value)) {
return value.map((value) => decode(value, retainedBy));
}
const release = () => {
retainCount -= 1;
if (FUNCTION in value) {
const id = (value as {[FUNCTION]: string})[FUNCTION];
if (retainCount === 0) {
released = true;
idsToProxy.delete(id);
api.release(id);
if (idsToProxy.has(id)) {
return idsToProxy.get(id)! as any;
}
};
const retain = () => {
retainCount += 1;
};
let retainCount = 0;
let released = false;
const retainers = new Set(retainedBy);
const release = () => {
retainCount -= 1;
const proxy = (...args: any[]) => {
if (released) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
if (retainCount === 0) {
released = true;
idsToProxy.delete(id);
api.release(id);
}
};
if (!idsToProxy.has(id)) {
throw new Error(
'You attempted to call a function that was already revoked.',
);
}
const retain = () => {
retainCount += 1;
};
return api.call(id, args);
};
const retainers = new Set(retainedBy);
Object.defineProperties(proxy, {
[RELEASE_METHOD]: {value: release, writable: false},
[RETAIN_METHOD]: {value: retain, writable: false},
[RETAINED_BY]: {value: retainers, writable: false},
});
const proxy = (...args: any[]) => {
if (released) {
throw new Error(
'You attempted to call a function that was already released.',
);
}
for (const retainer of retainers) {
retainer.add(proxy as any);
}
if (!idsToProxy.has(id)) {
throw new Error(
'You attempted to call a function that was already revoked.',
);
}
idsToProxy.set(id, proxy);
return api.call(id, args);
};
return proxy as any;
}
Object.defineProperties(proxy, {
[RELEASE_METHOD]: {value: release, writable: false},
[RETAIN_METHOD]: {value: retain, writable: false},
[RETAINED_BY]: {value: retainers, writable: false},
});
const result: Record<string | symbol, any> = {};
for (const retainer of retainers) {
retainer.add(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);
idsToProxy.set(id, proxy);
return proxy as any;
}
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();
function isIterator(value: any) {
return (
value != null &&
(Symbol.asyncIterator in value || Symbol.iterator in value) &&
typeof (value as any).next === 'function'
);
}

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

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

@@ -5,4 +5,9 @@ export {createThread} from './thread';

export type {MemoryManageable, MemoryRetainer} from './memory';
export {RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY} from './constants';
export {
RELEASE_METHOD,
RETAIN_METHOD,
RETAINED_BY,
ENCODE_METHOD,
} from './constants';
export {
targetFromWebWorker,

@@ -12,3 +17,3 @@ targetFromMessagePort,

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

@@ -25,3 +30,4 @@ export type {ThreadAbortSignal} from './abort';

ThreadEncodingStrategyApi,
ThreadEncodable,
AnyFunction,
} from './types';

@@ -33,2 +33,13 @@ import {RETAINED_BY, RETAIN_METHOD, RELEASE_METHOD} from './constants';

export function retain(value: any, {deep = true} = {}): boolean {
return retainInternal(value, deep, new Map());
}
function retainInternal(
value: any,
deep: boolean,
seen: Map<any, boolean>,
): boolean {
const seenValue = seen.get(value);
if (seenValue) return seenValue;
const canRetain = isMemoryManageable(value);

@@ -40,13 +51,23 @@

seen.set(value, canRetain);
if (deep) {
if (Array.isArray(value)) {
return value.reduce(
(canRetain, item) => retain(item, {deep}) || canRetain,
const nestedCanRetain = value.reduce(
(canRetain, item) => retainInternal(item, deep, seen) || canRetain,
canRetain,
);
} else if (typeof value === 'object' && value != null) {
return Object.keys(value).reduce(
(canRetain, key) => retain(value[key], {deep}) || canRetain,
seen.set(value, nestedCanRetain);
return nestedCanRetain;
}
if (isBasicObject(value)) {
const nestedCanRetain = Object.keys(value).reduce(
(canRetain, key) => retainInternal(value[key], deep, seen) || canRetain,
canRetain,
);
seen.set(value, nestedCanRetain);
return nestedCanRetain;
}

@@ -59,2 +80,13 @@ }

export function release(value: any, {deep = true} = {}): boolean {
return releaseInternal(value, deep, new Map());
}
function releaseInternal(
value: any,
deep: boolean,
seen: Map<any, boolean>,
): boolean {
const seenValue = seen.get(value);
if (seenValue) return seenValue;
const canRelease = isMemoryManageable(value);

@@ -66,13 +98,24 @@

seen.set(value, canRelease);
if (deep) {
if (Array.isArray(value)) {
return value.reduce(
(canRelease, item) => release(item, {deep}) || canRelease,
const nestedCanRelease = value.reduce(
(canRelease, item) => releaseInternal(item, deep, seen) || canRelease,
canRelease,
);
} else if (typeof value === 'object' && value != null) {
return Object.keys(value).reduce(
(canRelease, key) => release(value[key], {deep}) || canRelease,
seen.set(value, nestedCanRelease);
return nestedCanRelease;
}
if (isBasicObject(value)) {
const nestedCanRelease = Object.keys(value).reduce(
(canRelease, key) =>
releaseInternal(value[key], deep, seen) || canRelease,
canRelease,
);
seen.set(value, nestedCanRelease);
return nestedCanRelease;
}

@@ -83,1 +126,8 @@ }

}
export function isBasicObject(value: unknown) {
if (value == null || typeof value !== 'object') return false;
const prototype = Object.getPrototypeOf(value);
return prototype == null || prototype === Object.prototype;
}

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

import type {RELEASE_METHOD, RETAIN_METHOD, RETAINED_BY} from './constants';
import type {
RELEASE_METHOD,
RETAIN_METHOD,
ENCODE_METHOD,
RETAINED_BY,
} from './constants';

@@ -50,4 +55,3 @@ export type Thread<Target> = ThreadCallable<Target>;

? readonly ThreadSafeReturnType<ArrayElement>[]
: // eslint-disable-next-line @typescript-eslint/ban-types
T extends object
: T extends object
? {[K in keyof T]: ThreadSafeReturnType<T[K]>}

@@ -98,3 +102,7 @@ : T;

export interface ThreadEncodable {
[ENCODE_METHOD](api: {encode(value: any): unknown}): any;
}
// eslint-disable-next-line @typescript-eslint/ban-types
export type AnyFunction = Function;
{
"extends": "@quilted/typescript/pkg.json",
"extends": "@quilted/typescript/project.json",
"compilerOptions": {

@@ -4,0 +4,0 @@ "rootDir": "source",

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

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