@meonode/canvas 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/canvas/canvas.helper.js +0 -230
- package/dist/cjs/canvas/canvas.helper.js.map +1 -1
- package/dist/cjs/canvas/chart.canvas.js +70 -144
- package/dist/cjs/canvas/chart.canvas.js.map +1 -1
- package/dist/cjs/canvas/grid.canvas.js.map +1 -1
- package/dist/cjs/canvas/image.canvas.js +2 -2
- package/dist/cjs/canvas/image.canvas.js.map +1 -1
- package/dist/cjs/canvas/layout.canvas.js +23 -16
- package/dist/cjs/canvas/layout.canvas.js.map +1 -1
- package/dist/cjs/canvas/root.canvas.js +23 -117
- package/dist/cjs/canvas/root.canvas.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.js +2 -2
- package/dist/cjs/canvas/text.canvas.js.map +1 -1
- package/dist/cjs/constant/common.const.js.map +1 -1
- package/dist/cjs/{canvas → src/canvas}/canvas.helper.d.ts +1 -20
- package/dist/cjs/src/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/{esm → cjs/src}/canvas/canvas.type.d.ts +1 -12
- package/dist/cjs/src/canvas/canvas.type.d.ts.map +1 -0
- package/dist/cjs/{canvas → src/canvas}/chart.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/chart.canvas.d.ts.map +1 -0
- package/dist/cjs/src/canvas/grid.canvas.d.ts.map +1 -0
- package/dist/{esm → cjs/src}/canvas/image.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/image.canvas.d.ts.map +1 -0
- package/dist/{esm → cjs/src}/canvas/layout.canvas.d.ts +2 -2
- package/dist/cjs/src/canvas/layout.canvas.d.ts.map +1 -0
- package/dist/{esm → cjs/src}/canvas/root.canvas.d.ts +3 -2
- package/dist/cjs/src/canvas/root.canvas.d.ts.map +1 -0
- package/dist/cjs/{canvas → src/canvas}/text.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/text.canvas.d.ts.map +1 -0
- package/dist/cjs/src/constant/common.const.d.ts +18 -0
- package/dist/cjs/src/constant/common.const.d.ts.map +1 -0
- package/dist/cjs/src/index.d.ts.map +1 -0
- package/dist/cjs/src/util/disk.cache.d.ts.map +1 -0
- package/dist/cjs/src/worker/comlink.pool.d.ts +30 -0
- package/dist/cjs/src/worker/comlink.pool.d.ts.map +1 -0
- package/dist/cjs/src/worker/comlink.setup.d.ts +4 -0
- package/dist/cjs/src/worker/comlink.setup.d.ts.map +1 -0
- package/dist/cjs/src/worker/render.worker.d.ts.map +1 -0
- package/dist/cjs/src/worker/worker.types.d.ts +13 -0
- package/dist/cjs/src/worker/worker.types.d.ts.map +1 -0
- package/dist/cjs/util/disk.cache.js.map +1 -1
- package/dist/cjs/worker/comlink.pool.js +164 -0
- package/dist/cjs/worker/comlink.pool.js.map +1 -0
- package/dist/cjs/worker/comlink.setup.js +53 -0
- package/dist/cjs/worker/comlink.setup.js.map +1 -0
- package/dist/cjs/worker/render.worker.js +58 -61
- package/dist/cjs/worker/render.worker.js.map +1 -1
- package/dist/esm/canvas/canvas.helper.js +1 -230
- package/dist/esm/canvas/chart.canvas.js +71 -145
- package/dist/esm/canvas/image.canvas.js +2 -2
- package/dist/esm/canvas/layout.canvas.js +23 -16
- package/dist/esm/canvas/root.canvas.js +23 -116
- package/dist/esm/canvas/text.canvas.js +2 -2
- package/dist/esm/{canvas → src/canvas}/canvas.helper.d.ts +1 -20
- package/dist/esm/src/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/{cjs → esm/src}/canvas/canvas.type.d.ts +1 -12
- package/dist/esm/src/canvas/canvas.type.d.ts.map +1 -0
- package/dist/esm/{canvas → src/canvas}/chart.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/chart.canvas.d.ts.map +1 -0
- package/dist/esm/src/canvas/grid.canvas.d.ts.map +1 -0
- package/dist/{cjs → esm/src}/canvas/image.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/image.canvas.d.ts.map +1 -0
- package/dist/{cjs → esm/src}/canvas/layout.canvas.d.ts +2 -2
- package/dist/esm/src/canvas/layout.canvas.d.ts.map +1 -0
- package/dist/{cjs → esm/src}/canvas/root.canvas.d.ts +3 -2
- package/dist/esm/src/canvas/root.canvas.d.ts.map +1 -0
- package/dist/esm/{canvas → src/canvas}/text.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/text.canvas.d.ts.map +1 -0
- package/dist/esm/src/constant/common.const.d.ts +18 -0
- package/dist/esm/src/constant/common.const.d.ts.map +1 -0
- package/dist/esm/src/index.d.ts.map +1 -0
- package/dist/esm/src/util/disk.cache.d.ts.map +1 -0
- package/dist/esm/src/worker/comlink.pool.d.ts +30 -0
- package/dist/esm/src/worker/comlink.pool.d.ts.map +1 -0
- package/dist/esm/src/worker/comlink.setup.d.ts +4 -0
- package/dist/esm/src/worker/comlink.setup.d.ts.map +1 -0
- package/dist/esm/src/worker/render.worker.d.ts.map +1 -0
- package/dist/esm/src/worker/worker.types.d.ts +13 -0
- package/dist/esm/src/worker/worker.types.d.ts.map +1 -0
- package/dist/esm/worker/comlink.pool.js +139 -0
- package/dist/esm/worker/comlink.setup.js +30 -0
- package/dist/esm/worker/render.worker.js +38 -60
- package/package.json +9 -8
- package/dist/cjs/canvas/canvas.helper.d.ts.map +0 -1
- package/dist/cjs/canvas/canvas.type.d.ts.map +0 -1
- package/dist/cjs/canvas/chart.canvas.d.ts.map +0 -1
- package/dist/cjs/canvas/grid.canvas.d.ts.map +0 -1
- package/dist/cjs/canvas/image.canvas.d.ts.map +0 -1
- package/dist/cjs/canvas/layout.canvas.d.ts.map +0 -1
- package/dist/cjs/canvas/root.canvas.d.ts.map +0 -1
- package/dist/cjs/canvas/text.canvas.d.ts.map +0 -1
- package/dist/cjs/constant/common.const.d.ts +0 -37
- package/dist/cjs/constant/common.const.d.ts.map +0 -1
- package/dist/cjs/index.d.ts.map +0 -1
- package/dist/cjs/util/disk.cache.d.ts.map +0 -1
- package/dist/cjs/worker/render.worker.d.ts.map +0 -1
- package/dist/cjs/worker/worker.types.d.ts +0 -76
- package/dist/cjs/worker/worker.types.d.ts.map +0 -1
- package/dist/esm/canvas/canvas.helper.d.ts.map +0 -1
- package/dist/esm/canvas/canvas.type.d.ts.map +0 -1
- package/dist/esm/canvas/chart.canvas.d.ts.map +0 -1
- package/dist/esm/canvas/grid.canvas.d.ts.map +0 -1
- package/dist/esm/canvas/image.canvas.d.ts.map +0 -1
- package/dist/esm/canvas/layout.canvas.d.ts.map +0 -1
- package/dist/esm/canvas/root.canvas.d.ts.map +0 -1
- package/dist/esm/canvas/text.canvas.d.ts.map +0 -1
- package/dist/esm/constant/common.const.d.ts +0 -37
- package/dist/esm/constant/common.const.d.ts.map +0 -1
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/util/disk.cache.d.ts.map +0 -1
- package/dist/esm/worker/render.worker.d.ts.map +0 -1
- package/dist/esm/worker/worker.types.d.ts +0 -76
- package/dist/esm/worker/worker.types.d.ts.map +0 -1
- /package/dist/cjs/{canvas → src/canvas}/grid.canvas.d.ts +0 -0
- /package/dist/cjs/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/cjs/{util → src/util}/disk.cache.d.ts +0 -0
- /package/dist/cjs/{worker → src/worker}/render.worker.d.ts +0 -0
- /package/dist/esm/{canvas → src/canvas}/grid.canvas.d.ts +0 -0
- /package/dist/esm/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/esm/{util → src/util}/disk.cache.d.ts +0 -0
- /package/dist/esm/{worker → src/worker}/render.worker.d.ts +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Canvas } from 'skia-canvas';
|
|
1
|
+
import { Canvas, type CanvasRenderingContext2D } from 'skia-canvas';
|
|
2
2
|
import { ColumnNode, BoxNode } from '../canvas/layout.canvas.js';
|
|
3
3
|
import type { BaseProps, RootProps, CanvasElement, RootPropsWithWorker, RootPropsWithoutWorker } from '../canvas/canvas.type.js';
|
|
4
4
|
export declare const _clearRegisteredFonts: () => void;
|
|
@@ -58,7 +58,8 @@ export declare class RootNode extends ColumnNode {
|
|
|
58
58
|
* and final drawing
|
|
59
59
|
* @returns Promise resolving to the rendered Canvas instance
|
|
60
60
|
*/
|
|
61
|
-
render(): Promise<
|
|
61
|
+
render(ctx: CanvasRenderingContext2D, offsetX?: number, offsetY?: number): Promise<void>;
|
|
62
|
+
render(ctx?: CanvasRenderingContext2D, offsetX?: number, offsetY?: number): Promise<Canvas>;
|
|
62
63
|
}
|
|
63
64
|
/**
|
|
64
65
|
* Creates and renders a new root node with the given properties.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.canvas.d.ts","sourceRoot":"","sources":["../../../../src/canvas/root.canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAe,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAEhF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAW,MAAM,2BAA2B,CAAA;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAgB/H,eAAO,MAAM,qBAAqB,YAEjC,CAAA;AAmBD,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,kBAAkB,QAGpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,SAKxB;AAqFD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO,CAmB5D;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU;IAC9B,KAAK,EAAE,SAAS,GAAG,SAAS,CAAA;IACpC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAoB;IAClC,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAwC;IACnD,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,SAAS,GAAG,SAAS;IAoDxC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACY,MAAM,CAAC,GAAG,EAAE,wBAAwB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACjG,MAAM,CAAC,GAAG,CAAC,EAAE,wBAAwB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA4DlG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG;IAAE,OAAO,IAAI,IAAI,CAAA;CAAE,CAAC,CAAA;AACvF,wBAAgB,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -156,7 +156,7 @@ export declare class TextNode extends BoxNode {
|
|
|
156
156
|
* @param width Content box total width including padding
|
|
157
157
|
* @param height Content box total height including padding
|
|
158
158
|
*/
|
|
159
|
-
protected _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number): void
|
|
159
|
+
protected _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number): Promise<void>;
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
162
|
* Creates a new TextNode instance with rich text support
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.canvas.d.ts","sourceRoot":"","sources":["../../../../src/canvas/text.canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAe,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACpF,OAAO,EAAU,KAAK,wBAAwB,EAA2B,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAGnD;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAwC;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,kBAAkB,CAAe;IAEjC,KAAK,EAAE,SAAS,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;gBAElC,IAAI,GAAE,MAAM,GAAG,MAAW,EAAE,KAAK,GAAE,SAAc;IAuB7D;;;;;;;;OAQG;WACW,gBAAgB,CAC5B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,GAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;QACpC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;QAClC,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,wBAAwB,CAAC,WAAW,CAAC,CAAA;QACjD,YAAY,CAAC,EAAE,wBAAwB,CAAC,cAAc,CAAC,CAAA;KACnD;cAwBW,aAAa,IAAI,IAAI;IAoDxC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;IA+ErB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,gBAAgB;IAyBxB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAiCrB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAQjC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;IA+NnB;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IA6KpB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAmErB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;;;;;;OAgBG;cACsB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAkX3H;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,SAAS,KAAG,aAI9D,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Yoga, * as All from 'yoga-layout';
|
|
2
|
+
/**
|
|
3
|
+
* Style constants extending Yoga layout engine with additional border styles
|
|
4
|
+
*/
|
|
5
|
+
export declare enum Border {
|
|
6
|
+
Solid = 0,
|
|
7
|
+
Dashed = 1,
|
|
8
|
+
Dotted = 2
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Consolidated Style object combining Yoga layout constants and custom border styles
|
|
12
|
+
*/
|
|
13
|
+
export declare const Style: typeof All & {
|
|
14
|
+
Border: typeof Border;
|
|
15
|
+
};
|
|
16
|
+
export * from 'yoga-layout';
|
|
17
|
+
export default Yoga;
|
|
18
|
+
//# sourceMappingURL=common.const.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.const.d.ts","sourceRoot":"","sources":["../../../../src/constant/common.const.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,EAAE,KAAK,GAAG,MAAM,aAAa,CAAA;AAExC;;GAEG;AACH,oBAAY,MAAM;IAChB,KAAK,IAAA;IACL,MAAM,IAAA;IACN,MAAM,IAAA;CACP;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,OAAO,GAAG,GAAG;IAAE,MAAM,EAAE,OAAO,MAAM,CAAA;CAGvD,CAAA;AAED,cAAc,aAAa,CAAA;AAC3B,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAC9C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disk.cache.d.ts","sourceRoot":"","sources":["../../../../src/util/disk.cache.ts"],"names":[],"mappings":"AAaA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOvE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO7E;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhE;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAOpD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RenderResult } from '../worker/worker.types.js';
|
|
2
|
+
import type { RootProps } from '../canvas/canvas.type.js';
|
|
3
|
+
export interface PoolRenderResult extends RenderResult {
|
|
4
|
+
workerIdx: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Deeply walks an object tree, wraps any function values with Comlink.proxy(),
|
|
8
|
+
* and tracks wrapped proxies for deterministic cleanup.
|
|
9
|
+
*/
|
|
10
|
+
export declare function wrapFunctions<T>(obj: T, proxies: Set<unknown>): T;
|
|
11
|
+
/**
|
|
12
|
+
* Pool of Comlink-wrapped worker threads.
|
|
13
|
+
* Manages idle/queue scheduling and proxy lifecycle.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ComlinkPool {
|
|
16
|
+
private workers;
|
|
17
|
+
private endpoints;
|
|
18
|
+
private idle;
|
|
19
|
+
private queue;
|
|
20
|
+
constructor(size: number);
|
|
21
|
+
private acquire;
|
|
22
|
+
private release;
|
|
23
|
+
private drain;
|
|
24
|
+
private executeRender;
|
|
25
|
+
render(props: RootProps): Promise<PoolRenderResult>;
|
|
26
|
+
callOnCanvas(workerIdx: number, canvasId: number, method: string, args: unknown[]): Promise<Buffer | string | void>;
|
|
27
|
+
releaseCanvas(workerIdx: number, canvasId: number): void;
|
|
28
|
+
terminate(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=comlink.pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comlink.pool.d.ts","sourceRoot":"","sources":["../../../../src/worker/comlink.pool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,SAAS,EAAE,MAAM,CAAA;CAClB;AAQD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAuBjE;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,KAAK,CAAmB;gBAEpB,IAAI,EAAE,MAAM;IAYxB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,KAAK;YAQC,aAAa;IAWrB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0CzD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAInH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIxD,SAAS;CAOV"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comlink.setup.d.ts","sourceRoot":"","sources":["../../../../src/worker/comlink.setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAKlC,OAAO,YAAY,MAAM,mCAAmC,CAAA;AA2B5D,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.worker.d.ts","sourceRoot":"","sources":["../../../../src/worker/render.worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RootProps } from '../canvas/canvas.type.js';
|
|
2
|
+
export interface RenderResult {
|
|
3
|
+
canvasId: number;
|
|
4
|
+
buffer: Buffer;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkerAPI {
|
|
9
|
+
render(props: RootProps): Promise<RenderResult>;
|
|
10
|
+
callOnCanvas(canvasId: number, method: string, args: unknown[]): Promise<Buffer | string | void>;
|
|
11
|
+
releaseCanvas(canvasId: number): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=worker.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.types.d.ts","sourceRoot":"","sources":["../../../../src/worker/worker.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC/C,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAA;IAChG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk.cache.js","sources":["
|
|
1
|
+
{"version":3,"file":"disk.cache.js","sources":["../../../../../src/util/disk.cache.ts"],"sourcesContent":["import { createHash } from 'crypto'\nimport { promises as fs } from 'fs'\nimport { join } from 'path'\n\nconst CACHE_DIR = join(process.cwd(), '.cache', 'files')\nlet _dirEnsured = false\n\nasync function ensureDir(): Promise<void> {\n if (_dirEnsured) return\n await fs.mkdir(CACHE_DIR, { recursive: true })\n _dirEnsured = true\n}\n\nexport function hashBuffer(buf: Buffer): string {\n return createHash('sha256').update(buf).digest('hex')\n}\n\nexport async function readDiskCache(key: string): Promise<Buffer | null> {\n try {\n await ensureDir()\n return await fs.readFile(join(CACHE_DIR, key))\n } catch {\n return null\n }\n}\n\nexport async function writeDiskCache(key: string, data: Buffer): Promise<void> {\n try {\n await ensureDir()\n await fs.writeFile(join(CACHE_DIR, key), data)\n } catch {\n // best-effort — cache write failures are non-fatal\n }\n}\n\nexport async function deleteDiskCache(key: string): Promise<void> {\n try {\n await fs.unlink(join(CACHE_DIR, key))\n } catch {\n // non-fatal — file may not exist if write failed earlier\n }\n}\n\n/**\n * Delete the entire disk cache directory.\n * Called on process exit to clean up any orphaned cache files.\n */\nexport async function clearDiskCache(): Promise<void> {\n _dirEnsured = false\n try {\n await fs.rm(CACHE_DIR, { recursive: true, force: true })\n } catch {\n // non-fatal — directory may not exist\n }\n}\n\n// Clean up disk cache on process exit to handle crashes mid-render.\n// Guard prevents re-entry: clearDiskCache() is async, so without this the\n// beforeExit → schedule I/O → idle → beforeExit cycle loops forever.\nlet _exitCleanupStarted = false\nprocess.on('beforeExit', () => {\n if (_exitCleanupStarted) return\n _exitCleanupStarted = true\n void clearDiskCache()\n})\n\n// Also clean up on SIGINT/SIGTERM for graceful shutdowns\nconst cleanupOnExit = () => {\n clearDiskCache().finally(() => process.exit(0))\n}\nprocess.on('SIGINT', cleanupOnExit)\nprocess.on('SIGTERM', cleanupOnExit)\n"],"names":["join","fs","createHash"],"mappings":";;;;;;AAIA,MAAM,SAAS,GAAGA,SAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC;AACxD,IAAI,WAAW,GAAG,KAAK;AAEvB,eAAe,SAAS,GAAA;AACtB,IAAA,IAAI,WAAW;QAAE;AACjB,IAAA,MAAMC,WAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC9C,WAAW,GAAG,IAAI;AACpB;AAEM,SAAU,UAAU,CAAC,GAAW,EAAA;AACpC,IAAA,OAAOC,iBAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACvD;AAEO,eAAe,aAAa,CAAC,GAAW,EAAA;AAC7C,IAAA,IAAI;QACF,MAAM,SAAS,EAAE;AACjB,QAAA,OAAO,MAAMD,WAAE,CAAC,QAAQ,CAACD,SAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAChD;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF;AAEO,eAAe,cAAc,CAAC,GAAW,EAAE,IAAY,EAAA;AAC5D,IAAA,IAAI;QACF,MAAM,SAAS,EAAE;AACjB,QAAA,MAAMC,WAAE,CAAC,SAAS,CAACD,SAAI,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAChD;AAAE,IAAA,MAAM;;IAER;AACF;AAEO,eAAe,eAAe,CAAC,GAAW,EAAA;AAC/C,IAAA,IAAI;QACF,MAAMC,WAAE,CAAC,MAAM,CAACD,SAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACvC;AAAE,IAAA,MAAM;;IAER;AACF;AAEA;;;AAGG;AACI,eAAe,cAAc,GAAA;IAClC,WAAW,GAAG,KAAK;AACnB,IAAA,IAAI;AACF,QAAA,MAAMC,WAAE,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC1D;AAAE,IAAA,MAAM;;IAER;AACF;AAEA;AACA;AACA;AACA,IAAI,mBAAmB,GAAG,KAAK;AAC/B,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAK;AAC5B,IAAA,IAAI,mBAAmB;QAAE;IACzB,mBAAmB,GAAG,IAAI;IAC1B,KAAK,cAAc,EAAE;AACvB,CAAC,CAAC;AAEF;AACA,MAAM,aAAa,GAAG,MAAK;AACzB,IAAA,cAAc,EAAE,CAAC,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AACD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;AACnC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;;;;;;;;"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_worker_threads = require('node:worker_threads');
|
|
4
|
+
var node_url = require('node:url');
|
|
5
|
+
var path = require('node:path');
|
|
6
|
+
require('./comlink.setup.js');
|
|
7
|
+
var Comlink = require('comlink');
|
|
8
|
+
var nodeEndpoint = require('comlink/dist/esm/node-adapter.mjs');
|
|
9
|
+
|
|
10
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
|
+
function _interopNamespaceDefault(e) {
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
29
|
+
var Comlink__namespace = /*#__PURE__*/_interopNamespaceDefault(Comlink);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Deeply walks an object tree, wraps any function values with Comlink.proxy(),
|
|
33
|
+
* and tracks wrapped proxies for deterministic cleanup.
|
|
34
|
+
*/
|
|
35
|
+
function wrapFunctions(obj, proxies) {
|
|
36
|
+
if (obj === null || obj === undefined)
|
|
37
|
+
return obj;
|
|
38
|
+
if (typeof obj === 'function') {
|
|
39
|
+
const wrapped = Comlink__namespace.proxy(obj);
|
|
40
|
+
proxies.add(wrapped);
|
|
41
|
+
return wrapped;
|
|
42
|
+
}
|
|
43
|
+
if (typeof obj !== 'object')
|
|
44
|
+
return obj;
|
|
45
|
+
// Preserve binary data types — don't walk into them
|
|
46
|
+
if (Buffer.isBuffer(obj))
|
|
47
|
+
return obj;
|
|
48
|
+
if (obj instanceof ArrayBuffer)
|
|
49
|
+
return obj;
|
|
50
|
+
if (ArrayBuffer.isView(obj))
|
|
51
|
+
return obj;
|
|
52
|
+
if (Array.isArray(obj)) {
|
|
53
|
+
return obj.map(item => wrapFunctions(item, proxies));
|
|
54
|
+
}
|
|
55
|
+
const result = {};
|
|
56
|
+
for (const key of Object.keys(obj)) {
|
|
57
|
+
result[key] = wrapFunctions(obj[key], proxies);
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Pool of Comlink-wrapped worker threads.
|
|
63
|
+
* Manages idle/queue scheduling and proxy lifecycle.
|
|
64
|
+
*/
|
|
65
|
+
class ComlinkPool {
|
|
66
|
+
workers = [];
|
|
67
|
+
endpoints = [];
|
|
68
|
+
idle = [];
|
|
69
|
+
queue = [];
|
|
70
|
+
constructor(size) {
|
|
71
|
+
const workerFile = path__namespace.join(path__namespace.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('worker/comlink.pool.js', document.baseURI).href)))), '../worker/render.worker.js');
|
|
72
|
+
for (let i = 0; i < size; i++) {
|
|
73
|
+
const worker = new node_worker_threads.Worker(workerFile);
|
|
74
|
+
const endpoint = Comlink__namespace.wrap(nodeEndpoint(worker));
|
|
75
|
+
this.workers.push(worker);
|
|
76
|
+
this.endpoints.push(endpoint);
|
|
77
|
+
this.idle.push(i);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
acquire() {
|
|
81
|
+
return this.idle.pop() ?? null;
|
|
82
|
+
}
|
|
83
|
+
release(idx) {
|
|
84
|
+
this.idle.push(idx);
|
|
85
|
+
this.drain();
|
|
86
|
+
}
|
|
87
|
+
drain() {
|
|
88
|
+
while (this.queue.length > 0 && this.idle.length > 0) {
|
|
89
|
+
const task = this.queue.shift();
|
|
90
|
+
const idx = this.idle.pop();
|
|
91
|
+
void this.executeRender(idx, task.props, task.resolve, task.reject);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async executeRender(idx, props, resolve, reject) {
|
|
95
|
+
try {
|
|
96
|
+
const result = await this.endpoints[idx].render(props);
|
|
97
|
+
resolve({ ...result, workerIdx: idx });
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
this.release(idx);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async render(props) {
|
|
107
|
+
const proxies = new Set();
|
|
108
|
+
const wrapped = wrapFunctions(props, proxies);
|
|
109
|
+
const cleanup = () => {
|
|
110
|
+
for (const p of proxies) {
|
|
111
|
+
try {
|
|
112
|
+
;
|
|
113
|
+
p[Comlink__namespace.releaseProxy]?.();
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Proxy may already be released
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
// Direct path — idle worker available
|
|
121
|
+
const idx = this.acquire();
|
|
122
|
+
if (idx !== null) {
|
|
123
|
+
try {
|
|
124
|
+
const result = await this.endpoints[idx].render(wrapped);
|
|
125
|
+
return { ...result, workerIdx: idx };
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
this.release(idx);
|
|
129
|
+
cleanup();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Queued path — cleanup AFTER the queued task completes, not before
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
this.queue.push({
|
|
135
|
+
props: wrapped,
|
|
136
|
+
resolve: result => {
|
|
137
|
+
cleanup();
|
|
138
|
+
resolve(result);
|
|
139
|
+
},
|
|
140
|
+
reject: err => {
|
|
141
|
+
cleanup();
|
|
142
|
+
reject(err);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
callOnCanvas(workerIdx, canvasId, method, args) {
|
|
148
|
+
return this.endpoints[workerIdx].callOnCanvas(canvasId, method, args);
|
|
149
|
+
}
|
|
150
|
+
releaseCanvas(workerIdx, canvasId) {
|
|
151
|
+
this.endpoints[workerIdx].releaseCanvas(canvasId);
|
|
152
|
+
}
|
|
153
|
+
terminate() {
|
|
154
|
+
this.workers.forEach(w => w.terminate());
|
|
155
|
+
this.workers = [];
|
|
156
|
+
this.endpoints = [];
|
|
157
|
+
this.idle = [];
|
|
158
|
+
this.queue = [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
exports.ComlinkPool = ComlinkPool;
|
|
163
|
+
exports.wrapFunctions = wrapFunctions;
|
|
164
|
+
//# sourceMappingURL=comlink.pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comlink.pool.js","sources":["../../../../../src/worker/comlink.pool.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads'\nimport { fileURLToPath } from 'node:url'\nimport * as path from 'node:path'\nimport { Comlink, nodeEndpoint } from '@/worker/comlink.setup.js'\nimport type { Remote } from 'comlink'\nimport type { WorkerAPI, RenderResult } from '@/worker/worker.types.js'\nimport type { RootProps } from '@/canvas/canvas.type.js'\n\nexport interface PoolRenderResult extends RenderResult {\n workerIdx: number\n}\n\ninterface QueuedTask {\n props: RootProps\n resolve: (result: PoolRenderResult) => void\n reject: (err: Error) => void\n}\n\n/**\n * Deeply walks an object tree, wraps any function values with Comlink.proxy(),\n * and tracks wrapped proxies for deterministic cleanup.\n */\nexport function wrapFunctions<T>(obj: T, proxies: Set<unknown>): T {\n if (obj === null || obj === undefined) return obj\n if (typeof obj === 'function') {\n const wrapped = Comlink.proxy(obj)\n proxies.add(wrapped)\n return wrapped as unknown as T\n }\n if (typeof obj !== 'object') return obj\n\n // Preserve binary data types — don't walk into them\n if (Buffer.isBuffer(obj)) return obj\n if (obj instanceof ArrayBuffer) return obj\n if (ArrayBuffer.isView(obj)) return obj\n\n if (Array.isArray(obj)) {\n return obj.map(item => wrapFunctions(item, proxies)) as unknown as T\n }\n\n const result: Record<string, unknown> = {}\n for (const key of Object.keys(obj as Record<string, unknown>)) {\n result[key] = wrapFunctions((obj as Record<string, unknown>)[key], proxies)\n }\n return result as T\n}\n\n/**\n * Pool of Comlink-wrapped worker threads.\n * Manages idle/queue scheduling and proxy lifecycle.\n */\nexport class ComlinkPool {\n private workers: Worker[] = []\n private endpoints: Remote<WorkerAPI>[] = []\n private idle: number[] = []\n private queue: QueuedTask[] = []\n\n constructor(size: number) {\n const workerFile = path.join(path.dirname(fileURLToPath(import.meta.url)), '../worker/render.worker.js')\n\n for (let i = 0; i < size; i++) {\n const worker = new Worker(workerFile)\n const endpoint = Comlink.wrap<WorkerAPI>(nodeEndpoint(worker))\n this.workers.push(worker)\n this.endpoints.push(endpoint)\n this.idle.push(i)\n }\n }\n\n private acquire(): number | null {\n return this.idle.pop() ?? null\n }\n\n private release(idx: number) {\n this.idle.push(idx)\n this.drain()\n }\n\n private drain() {\n while (this.queue.length > 0 && this.idle.length > 0) {\n const task = this.queue.shift()!\n const idx = this.idle.pop()!\n void this.executeRender(idx, task.props, task.resolve, task.reject)\n }\n }\n\n private async executeRender(idx: number, props: RootProps, resolve: (result: PoolRenderResult) => void, reject: (err: Error) => void) {\n try {\n const result = await this.endpoints[idx].render(props)\n resolve({ ...result, workerIdx: idx })\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n } finally {\n this.release(idx)\n }\n }\n\n async render(props: RootProps): Promise<PoolRenderResult> {\n const proxies = new Set<unknown>()\n const wrapped = wrapFunctions(props, proxies)\n\n const cleanup = () => {\n for (const p of proxies) {\n try {\n ;(p as any)[Comlink.releaseProxy]?.()\n } catch {\n // Proxy may already be released\n }\n }\n }\n\n // Direct path — idle worker available\n const idx = this.acquire()\n if (idx !== null) {\n try {\n const result = await this.endpoints[idx].render(wrapped)\n return { ...result, workerIdx: idx }\n } finally {\n this.release(idx)\n cleanup()\n }\n }\n\n // Queued path — cleanup AFTER the queued task completes, not before\n return new Promise<PoolRenderResult>((resolve, reject) => {\n this.queue.push({\n props: wrapped,\n resolve: result => {\n cleanup()\n resolve(result)\n },\n reject: err => {\n cleanup()\n reject(err)\n },\n })\n })\n }\n\n callOnCanvas(workerIdx: number, canvasId: number, method: string, args: unknown[]): Promise<Buffer | string | void> {\n return this.endpoints[workerIdx].callOnCanvas(canvasId, method, args) as Promise<Buffer | string | void>\n }\n\n releaseCanvas(workerIdx: number, canvasId: number): void {\n this.endpoints[workerIdx].releaseCanvas(canvasId)\n }\n\n terminate() {\n this.workers.forEach(w => w.terminate())\n this.workers = []\n this.endpoints = []\n this.idle = []\n this.queue = []\n }\n}\n"],"names":["Comlink","path","fileURLToPath","Worker"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var Comlink = require('comlink');
|
|
4
|
+
var node_worker_threads = require('node:worker_threads');
|
|
5
|
+
var nodeEndpoint = require('comlink/dist/esm/node-adapter.mjs');
|
|
6
|
+
|
|
7
|
+
function _interopNamespaceDefault(e) {
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var Comlink__namespace = /*#__PURE__*/_interopNamespaceDefault(Comlink);
|
|
25
|
+
|
|
26
|
+
// src/worker/comlink.setup.ts
|
|
27
|
+
/**
|
|
28
|
+
* Fix Comlink.proxy() for Node.js worker_threads (issue #313).
|
|
29
|
+
* The built-in proxy transfer handler uses browser MessageChannel.
|
|
30
|
+
* This override uses Node's MessageChannel instead.
|
|
31
|
+
*
|
|
32
|
+
* Must be called on BOTH main thread and worker before any Comlink usage.
|
|
33
|
+
*/
|
|
34
|
+
function installNodeProxyHandler() {
|
|
35
|
+
Comlink__namespace.transferHandlers.set('proxy', {
|
|
36
|
+
canHandle: (obj) => typeof obj === 'object' && obj !== null && Comlink__namespace.proxyMarker in obj,
|
|
37
|
+
serialize: (obj) => {
|
|
38
|
+
const { port1, port2 } = new node_worker_threads.MessageChannel();
|
|
39
|
+
Comlink__namespace.expose(obj, nodeEndpoint(port1));
|
|
40
|
+
return [port2, [port2]];
|
|
41
|
+
},
|
|
42
|
+
deserialize: (port) => {
|
|
43
|
+
port.start?.();
|
|
44
|
+
return Comlink__namespace.wrap(nodeEndpoint(port));
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Install immediately on import
|
|
49
|
+
installNodeProxyHandler();
|
|
50
|
+
|
|
51
|
+
exports.Comlink = Comlink__namespace;
|
|
52
|
+
exports.nodeEndpoint = nodeEndpoint;
|
|
53
|
+
//# sourceMappingURL=comlink.setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comlink.setup.js","sources":["../../../../../src/worker/comlink.setup.ts"],"sourcesContent":["// src/worker/comlink.setup.ts\nimport * as Comlink from 'comlink'\nimport { MessageChannel } from 'node:worker_threads'\n\n// Use deep import path — Comlink has no `exports` field (issue #508)\n// @ts-expect-error — Comlink's node-adapter has no type declarations at this path\nimport nodeEndpoint from 'comlink/dist/esm/node-adapter.mjs'\n\n/**\n * Fix Comlink.proxy() for Node.js worker_threads (issue #313).\n * The built-in proxy transfer handler uses browser MessageChannel.\n * This override uses Node's MessageChannel instead.\n *\n * Must be called on BOTH main thread and worker before any Comlink usage.\n */\nfunction installNodeProxyHandler() {\n Comlink.transferHandlers.set('proxy', {\n canHandle: (obj: unknown): obj is { [Comlink.proxyMarker]: true } => typeof obj === 'object' && obj !== null && Comlink.proxyMarker in obj,\n serialize: (obj: unknown) => {\n const { port1, port2 } = new MessageChannel()\n Comlink.expose(obj, nodeEndpoint(port1))\n return [port2, [port2]]\n },\n deserialize: (port: MessagePort) => {\n ;(port as any).start?.()\n return Comlink.wrap(nodeEndpoint(port))\n },\n })\n}\n\n// Install immediately on import\ninstallNodeProxyHandler()\n\nexport { Comlink, nodeEndpoint }\n"],"names":["Comlink","MessageChannel"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAQA;;;;;;AAMG;AACH,SAAS,uBAAuB,GAAA;AAC9B,IAAAA,kBAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE;AACpC,QAAA,SAAS,EAAE,CAAC,GAAY,KAA6C,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAIA,kBAAO,CAAC,WAAW,IAAI,GAAG;AAC1I,QAAA,SAAS,EAAE,CAAC,GAAY,KAAI;YAC1B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAIC,kCAAc,EAAE;YAC7CD,kBAAO,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;AACxC,YAAA,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;AACD,QAAA,WAAW,EAAE,CAAC,IAAiB,KAAI;AAC/B,YAAA,IAAY,CAAC,KAAK,IAAI;YACxB,OAAOA,kBAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;AACF,KAAA,CAAC;AACJ;AAEA;AACA,uBAAuB,EAAE;;;;;"}
|
|
@@ -1,73 +1,70 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var node_worker_threads = require('node:worker_threads');
|
|
4
|
+
require('./comlink.setup.js');
|
|
4
5
|
var root_canvas = require('../canvas/root.canvas.js');
|
|
6
|
+
var Comlink = require('comlink');
|
|
7
|
+
var nodeEndpoint = require('comlink/dist/esm/node-adapter.mjs');
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var Comlink__namespace = /*#__PURE__*/_interopNamespaceDefault(Comlink);
|
|
27
|
+
|
|
28
|
+
if (!node_worker_threads.parentPort) {
|
|
20
29
|
throw new Error('[render.worker] Must be run as a worker thread');
|
|
21
30
|
}
|
|
22
31
|
const canvases = new Map();
|
|
23
32
|
let nextCanvasId = 0;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else if (msg.type === 'call') {
|
|
40
|
-
const canvas = canvases.get(msg.canvasId);
|
|
33
|
+
const api = {
|
|
34
|
+
async render(props) {
|
|
35
|
+
const canvas = await new root_canvas.RootNode(props).render();
|
|
36
|
+
const canvasId = nextCanvasId++;
|
|
37
|
+
canvases.set(canvasId, canvas);
|
|
38
|
+
const result = {
|
|
39
|
+
canvasId,
|
|
40
|
+
buffer: canvas.toBufferSync('png'),
|
|
41
|
+
width: canvas.width,
|
|
42
|
+
height: canvas.height,
|
|
43
|
+
};
|
|
44
|
+
return result;
|
|
45
|
+
},
|
|
46
|
+
async callOnCanvas(canvasId, method, args) {
|
|
47
|
+
const canvas = canvases.get(canvasId);
|
|
41
48
|
if (!canvas) {
|
|
42
|
-
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
try {
|
|
46
|
-
let result;
|
|
47
|
-
switch (msg.method) {
|
|
48
|
-
case 'toBuffer':
|
|
49
|
-
result = await canvas.toBuffer(...msg.args);
|
|
50
|
-
break;
|
|
51
|
-
case 'toURL':
|
|
52
|
-
result = await canvas.toURL(...msg.args);
|
|
53
|
-
break;
|
|
54
|
-
case 'toFile':
|
|
55
|
-
result = await canvas.toFile(...msg.args);
|
|
56
|
-
break;
|
|
57
|
-
case 'toSharp':
|
|
58
|
-
// Sharp instances can't be transferred across threads — serialize to buffer
|
|
59
|
-
result = await canvas.toSharp(...msg.args).toBuffer();
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
reply({ taskId: msg.taskId, result });
|
|
49
|
+
throw new Error(`[render.worker] Canvas ${canvasId} not found`);
|
|
63
50
|
}
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
switch (method) {
|
|
52
|
+
case 'toBuffer':
|
|
53
|
+
return canvas.toBuffer(...args);
|
|
54
|
+
case 'toURL':
|
|
55
|
+
return canvas.toURL(...args);
|
|
56
|
+
case 'toFile':
|
|
57
|
+
await canvas.toFile(...args);
|
|
58
|
+
return;
|
|
59
|
+
case 'toSharp':
|
|
60
|
+
return await canvas.toSharp(...args).toBuffer();
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(`[render.worker] Unknown method: ${method}`);
|
|
66
63
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
},
|
|
65
|
+
releaseCanvas(canvasId) {
|
|
66
|
+
canvases.delete(canvasId);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
Comlink__namespace.expose(api, nodeEndpoint(node_worker_threads.parentPort));
|
|
73
70
|
//# sourceMappingURL=render.worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.worker.js","sources":["
|
|
1
|
+
{"version":3,"file":"render.worker.js","sources":["../../../../../src/worker/render.worker.ts"],"sourcesContent":["import { parentPort } from 'node:worker_threads'\nimport { Comlink, nodeEndpoint } from '@/worker/comlink.setup.js'\nimport { RootNode } from '@/canvas/root.canvas.js'\nimport type { Canvas } from 'skia-canvas'\nimport type { WorkerAPI, RenderResult } from '@/worker/worker.types.js'\n\nif (!parentPort) {\n throw new Error('[render.worker] Must be run as a worker thread')\n}\n\nconst canvases = new Map<number, Canvas>()\nlet nextCanvasId = 0\n\nconst api: WorkerAPI = {\n async render(props) {\n const canvas = await new RootNode(props).render()\n const canvasId = nextCanvasId++\n canvases.set(canvasId, canvas)\n const result: RenderResult = {\n canvasId,\n buffer: canvas.toBufferSync('png'),\n width: canvas.width,\n height: canvas.height,\n }\n return result\n },\n\n async callOnCanvas(canvasId, method, args) {\n const canvas = canvases.get(canvasId)\n if (!canvas) {\n throw new Error(`[render.worker] Canvas ${canvasId} not found`)\n }\n switch (method) {\n case 'toBuffer':\n return canvas.toBuffer(...(args as [any, any?]))\n case 'toURL':\n return canvas.toURL(...(args as [any, any?]))\n case 'toFile':\n await canvas.toFile(...(args as [string, any?]))\n return\n case 'toSharp':\n return await canvas.toSharp(...(args as [any?])).toBuffer()\n default:\n throw new Error(`[render.worker] Unknown method: ${method}`)\n }\n },\n\n releaseCanvas(canvasId) {\n canvases.delete(canvasId)\n },\n}\n\nComlink.expose(api, nodeEndpoint(parentPort))\n"],"names":["parentPort","RootNode","Comlink"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,IAAI,CAACA,8BAAU,EAAE;AACf,IAAA,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC;AACnE;AAEA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB;AAC1C,IAAI,YAAY,GAAG,CAAC;AAEpB,MAAM,GAAG,GAAc;IACrB,MAAM,MAAM,CAAC,KAAK,EAAA;QAChB,MAAM,MAAM,GAAG,MAAM,IAAIC,oBAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;AACjD,QAAA,MAAM,QAAQ,GAAG,YAAY,EAAE;AAC/B,QAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;AAC9B,QAAA,MAAM,MAAM,GAAiB;YAC3B,QAAQ;AACR,YAAA,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB;AACD,QAAA,OAAO,MAAM;IACf,CAAC;AAED,IAAA,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAA;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAA,UAAA,CAAY,CAAC;QACjE;QACA,QAAQ,MAAM;AACZ,YAAA,KAAK,UAAU;AACb,gBAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAI,IAAoB,CAAC;AAClD,YAAA,KAAK,OAAO;AACV,gBAAA,OAAO,MAAM,CAAC,KAAK,CAAC,GAAI,IAAoB,CAAC;AAC/C,YAAA,KAAK,QAAQ;AACX,gBAAA,MAAM,MAAM,CAAC,MAAM,CAAC,GAAI,IAAuB,CAAC;gBAChD;AACF,YAAA,KAAK,SAAS;gBACZ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,GAAI,IAAe,CAAC,CAAC,QAAQ,EAAE;AAC7D,YAAA;AACE,gBAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAA,CAAE,CAAC;;IAElE,CAAC;AAED,IAAA,aAAa,CAAC,QAAQ,EAAA;AACpB,QAAA,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;CACF;AAEDC,kBAAO,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,CAACF,8BAAU,CAAC,CAAC;;"}
|