24 lines
3.7 KiB
TypeScript
24 lines
3.7 KiB
TypeScript
import { FacadeHandlerError, FacadeRequest, FacadeResponse, FacadeSerialQueue, createRequest, isFacadeRequest } from "./facade-envelope.js";
|
|
|
|
export const ASSEMBLY_NATIVE_SCHEMA = "freecad-web-assembly/native-type-probe/v1" as const;
|
|
export const ASSEMBLY_NATIVE_COMMAND = "assembly.nativeTypeProbe" as const;
|
|
export const ASSEMBLY_NATIVE_FIXTURE = { schema: ASSEMBLY_NATIVE_SCHEMA, module: "Assembly", typeName: "Assembly::AssemblyObject" } as const;
|
|
export interface AssemblyNativePayload { schema: typeof ASSEMBLY_NATIVE_SCHEMA; module: "Assembly"; typeName: string }
|
|
export interface AssemblyNativeResult { schema: typeof ASSEMBLY_NATIVE_SCHEMA; module: "Assembly"; typeName: string; initialized: true; source: "freecad-source"; resourcesReleased: true }
|
|
export interface AssemblyNativeKernel { ccall(name: string, returnType: "number" | "string", argTypes?: string[], args?: unknown[]): number | string }
|
|
export type AssemblyNativeRequest = FacadeRequest<AssemblyNativePayload>; export type AssemblyNativeResponse = FacadeResponse<AssemblyNativeResult>;
|
|
export function createAssemblyNativeRequest(id: string, payload: AssemblyNativePayload = ASSEMBLY_NATIVE_FIXTURE): AssemblyNativeRequest { return createRequest(id, ASSEMBLY_NATIVE_COMMAND, payload, "assembly-native"); }
|
|
export function isAssemblyNativeRequest(value: unknown): value is AssemblyNativeRequest { if (!isFacadeRequest(value)) return false; const request = value as AssemblyNativeRequest; return request.command === ASSEMBLY_NATIVE_COMMAND && request.payload?.schema === ASSEMBLY_NATIVE_SCHEMA && request.payload?.module === "Assembly" && typeof request.payload.typeName === "string" && request.payload.typeName.length > 0; }
|
|
export async function handleAssemblyNative(payload: AssemblyNativePayload, signal: AbortSignal, source: AssemblyNativeKernel | Promise<AssemblyNativeKernel>): Promise<AssemblyNativeResult> {
|
|
if (signal.aborted) throw new FacadeHandlerError("cancelled", "request was cancelled");
|
|
if (!isAssemblyNativeRequest(createAssemblyNativeRequest("validation", payload))) throw new FacadeHandlerError("invalid_fixture", "Assembly native type probe payload is invalid");
|
|
const kernel = await source;
|
|
if (signal.aborted) throw new FacadeHandlerError("cancelled", "request was cancelled");
|
|
if (Number(kernel.ccall("fc_web_assembly_initialize", "number", ["string"], ["AssemblyApp"])) !== 1) throw new FacadeHandlerError(String(kernel.ccall("fc_web_assembly_error_code", "string") || "native_error"), String(kernel.ccall("fc_web_assembly_error_message", "string") || "Assembly native initialization failed"));
|
|
if (Number(kernel.ccall("fc_web_assembly_type_probe", "number", ["string"], [payload.typeName])) !== 1) throw new FacadeHandlerError(String(kernel.ccall("fc_web_assembly_error_code", "string") || "type_not_found"), String(kernel.ccall("fc_web_assembly_error_message", "string") || "Assembly type probe failed"));
|
|
const handle = Number(kernel.ccall("fc_web_assembly_create_handle", "number", ["string"], [payload.typeName]));
|
|
if (handle <= 0 || Number(kernel.ccall("fc_web_assembly_release_handle", "number", ["number"], [handle])) !== 1 || Number(kernel.ccall("fc_web_assembly_active_handles", "number")) !== 0) throw new FacadeHandlerError("resource_leak", "Assembly native type handle was not released");
|
|
return { schema: ASSEMBLY_NATIVE_SCHEMA, module: "Assembly", typeName: String(kernel.ccall("fc_web_assembly_last_type", "string")), initialized: true, source: "freecad-source", resourcesReleased: true };
|
|
}
|
|
export function dispatchAssemblyNative(queue: FacadeSerialQueue, request: AssemblyNativeRequest, source: AssemblyNativeKernel | Promise<AssemblyNativeKernel>): Promise<AssemblyNativeResponse> { return queue.dispatch(request, (payload, signal) => handleAssemblyNative(payload, signal, source)); }
|