Offload functions to worker threads with shared memory primitives for Node.js.
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

at e46aca05dbf9a2204886d23f7ae3b34883f4e5c6 84 lines 3.5 kB view raw
1import { SharedStruct } from './shared-struct.ts'; 2import { Bytes } from './bytes.ts'; 3import { SharedString } from './string.ts'; 4import { Tuple } from './tuple.ts'; 5 6const SHARED = Symbol.for('moroutine.shared'); 7 8const registry = new Map<string, new (buffer: SharedArrayBuffer, byteOffset: number) => unknown>(); 9 10export function registerSync(tag: string, ctor: new (buffer: SharedArrayBuffer, byteOffset: number) => unknown): void { 11 registry.set(tag, ctor); 12} 13 14export function serializeArg(arg: unknown): unknown { 15 if (typeof arg === 'object' && arg !== null && SHARED in arg) { 16 const data = (arg as any)[SHARED](); 17 if (data.tag === 'SharedStruct') { 18 const serializedFields: Record<string, unknown> = {}; 19 for (const key in data.fields) { 20 serializedFields[key] = serializeStructField(data.fields[key]); 21 } 22 return { __shared__: 'SharedStruct', fields: serializedFields }; 23 } 24 if (data.tag === 'Tuple') { 25 const serializedElements = (data.elements as any[]).map((el: any) => serializeStructField(el)); 26 return { __shared__: 'Tuple', elements: serializedElements }; 27 } 28 return { 29 __shared__: data.tag, 30 buffer: data.buffer, 31 byteOffset: data.byteOffset, 32 ...(data.size !== undefined && { size: data.size }), 33 ...(data.maxBytes !== undefined && { maxBytes: data.maxBytes }), 34 }; 35 } 36 return arg; 37} 38 39function serializeStructField(data: { tag: string; [key: string]: unknown }): unknown { 40 if (data.tag === 'SharedStruct') { 41 const serializedFields: Record<string, unknown> = {}; 42 for (const key in data.fields as Record<string, unknown>) { 43 serializedFields[key] = serializeStructField((data.fields as any)[key]); 44 } 45 return { __shared__: 'SharedStruct', fields: serializedFields }; 46 } 47 return { 48 __shared__: data.tag, 49 buffer: data.buffer, 50 byteOffset: data.byteOffset, 51 ...(data.size !== undefined && { size: data.size }), 52 ...(data.maxBytes !== undefined && { maxBytes: data.maxBytes }), 53 }; 54} 55 56export function deserializeArg(arg: unknown): unknown { 57 if (typeof arg === 'object' && arg !== null && '__shared__' in arg) { 58 const data = arg as { __shared__: string; [key: string]: unknown }; 59 if (data.__shared__ === 'Bytes') { 60 const typedData = data as { __shared__: string; buffer: SharedArrayBuffer; byteOffset: number; size: number }; 61 return new Bytes(typedData.size, typedData.buffer, typedData.byteOffset); 62 } 63 if (data.__shared__ === 'SharedString') { 64 const typedData = data as { __shared__: string; buffer: SharedArrayBuffer; byteOffset: number; maxBytes: number }; 65 return new SharedString(typedData.maxBytes, typedData.buffer, typedData.byteOffset); 66 } 67 if (data.__shared__ === 'SharedStruct') { 68 const fields = data.fields as Record<string, unknown>; 69 const reconstructed: Record<string, unknown> = {}; 70 for (const key in fields) { 71 reconstructed[key] = deserializeArg(fields[key]); 72 } 73 return new SharedStruct(reconstructed as any); 74 } 75 if (data.__shared__ === 'Tuple') { 76 const elements = (data.elements as unknown[]).map((el) => deserializeArg(el)); 77 return new Tuple(elements as any); 78 } 79 const typedData = data as { __shared__: string; buffer: SharedArrayBuffer; byteOffset: number }; 80 const ctor = registry.get(typedData.__shared__); 81 if (ctor) return new ctor(typedData.buffer, typedData.byteOffset); 82 } 83 return arg; 84}