Advance M7 workflows and release operations
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-15 17:43:53 -04:00
parent 17ab961485
commit 7c16b279ae
103 changed files with 8064 additions and 429 deletions

View File

@@ -8,6 +8,7 @@ import type {
WebEngineRequest,
WebEngineResponse,
WebEngineResult,
WebEngineOpenResourceStatus,
WebEngineStatus,
} from "../../../protocol/web-engine";
import type { LODGenerationRequest } from "../../../protocol/lod";
@@ -25,6 +26,7 @@ interface PendingRequest {
reject: (error: ErrorReport) => void;
onProgress?: (progress: ProgressEvent) => void;
timer: ReturnType<typeof setTimeout>;
cleanup?: () => void;
}
export interface WebEngineClientOptions {
@@ -61,11 +63,11 @@ export class WebEngineClient {
return (await this.request({ type: "init" })).status;
}
async openBlend(buffer: ArrayBuffer, onProgress?: (progress: ProgressEvent) => void): Promise<BlendOpenResult> {
async openBlend(buffer: ArrayBuffer, onProgress?: (progress: ProgressEvent) => void, signal?: AbortSignal): Promise<BlendOpenResult> {
if (buffer.byteLength === 0) {
throw this.report("INVALID_ARGUMENT", "无法打开空的 .blend 文件", true);
}
const result = await this.request({ type: "openBlend", buffer }, [buffer], onProgress);
const result = await this.request({ type: "openBlend", buffer }, [buffer], onProgress, signal);
if (!result.snapshot) throw this.report("BLEND_READ_FAILED", "WebEngine 未返回 SceneIR", true);
this.geometryBuffers = result.geometryBuffers ?? [];
this.nonMeshGeometryBuffers = result.nonMeshGeometryBuffers ?? [];
@@ -146,6 +148,12 @@ export class WebEngineClient {
return result.blend;
}
async openResourceStatus(): Promise<WebEngineOpenResourceStatus> {
const result = await this.request({ type: "openResourceStatus" });
if (!result.openResources) throw this.report("INVALID_ARGUMENT", "WebEngine open resource status missing", true);
return result.openResources;
}
terminate(): void {
this.failPending(this.report("WORKER_TERMINATED", "WebEngineWorker 已关闭", true));
this.worker?.terminate();
@@ -169,16 +177,29 @@ export class WebEngineClient {
command: WebEngineRequest["command"],
transfer: Transferable[] = [],
onProgress?: (progress: ProgressEvent) => void,
signal?: AbortSignal,
): Promise<WebEngineResult> {
const worker = this.start();
const requestId = `web-engine-${++this.requestCounter}`;
const request = { requestId, command } as WebEngineRequest;
return new Promise<WebEngineResult>((resolve, reject) => {
const timer = setTimeout(() => {
this.pending.get(requestId)?.cleanup?.();
this.pending.delete(requestId);
reject(this.report("WORKER_TERMINATED", `WebEngine 请求超时: ${command.type}`, true));
}, this.timeoutMs);
this.pending.set(requestId, { resolve, reject, onProgress, timer });
const abort = (): void => {
worker.postMessage({
requestId: `web-engine-cancel-${++this.requestCounter}`,
command: { type: "cancelOpen", targetRequestId: requestId },
} satisfies WebEngineRequest);
};
const cleanup = signal ? () => signal.removeEventListener("abort", abort) : undefined;
this.pending.set(requestId, { resolve, reject, onProgress, timer, cleanup });
if (signal) {
signal.addEventListener("abort", abort, { once: true });
if (signal.aborted) abort();
}
worker.postMessage(request, transfer);
});
}
@@ -192,6 +213,7 @@ export class WebEngineClient {
}
this.pending.delete(response.requestId);
clearTimeout(pending.timer);
pending.cleanup?.();
if (response.ok) pending.resolve(response.result);
else pending.reject(response.error);
}
@@ -199,6 +221,7 @@ export class WebEngineClient {
private failPending(error: ErrorReport): void {
for (const pending of this.pending.values()) {
clearTimeout(pending.timer);
pending.cleanup?.();
pending.reject(error);
}
this.pending.clear();