@basthon/kernel-base 0.78.0 → 0.78.1

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/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.78.0";
1
+ export declare const VERSION = "0.78.1";
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.78.0";
1
+ export const VERSION = "0.78.1";
@@ -11,6 +11,7 @@ export declare class KernelMainBase<Type extends KernelWorkerBase> extends Kerne
11
11
  private _fallbackKey?;
12
12
  private _encrypt;
13
13
  private readonly _ephemeralAPI;
14
+ private readonly _conversionCanvas;
14
15
  constructor(options: any);
15
16
  /**
16
17
  * Is this a legacy worker? i.e. not runing in a worker.
@@ -49,6 +50,10 @@ export declare class KernelMainBase<Type extends KernelWorkerBase> extends Kerne
49
50
  * Stop the worker.
50
51
  */
51
52
  _stop(): Promise<void>;
53
+ /**
54
+ * Convert a canvas array buffer to a PNG data URL (base64 encoded).
55
+ */
56
+ private canvasArrayToPNGDataURL;
52
57
  /**
53
58
  * Process messages from worker (if any).
54
59
  */
@@ -12,6 +12,7 @@ export class KernelMainBase extends KernelBase {
12
12
  // synchronise comlink and communication channels
13
13
  this._channelSyncer = new PromiseDelegate();
14
14
  this._encrypt = (s) => s;
15
+ this._conversionCanvas = document.createElement("canvas");
15
16
  this._legacy = options?.legacy === true;
16
17
  // synchronous wait on SAB cannot be used in a legacy context
17
18
  // (atomic wait will block the main thread)
@@ -147,6 +148,25 @@ export class KernelMainBase extends KernelBase {
147
148
  }
148
149
  await super._stop();
149
150
  }
151
+ /**
152
+ * Convert a canvas array buffer to a PNG data URL (base64 encoded).
153
+ */
154
+ async canvasArrayToPNGDataURL(width, height, buffer) {
155
+ const canvas = this._conversionCanvas;
156
+ canvas.width = width;
157
+ canvas.height = height;
158
+ const ctx = canvas.getContext("2d");
159
+ if (ctx === null)
160
+ return;
161
+ const imageData = new ImageData(new Uint8ClampedArray(buffer), width, height);
162
+ ctx.putImageData(imageData, 0, 0);
163
+ const dataURL = canvas.toDataURL("image/png");
164
+ canvas.width = 0;
165
+ canvas.height = 0;
166
+ const pngPrefix = "data:image/png;base64,";
167
+ if (dataURL.startsWith(pngPrefix))
168
+ return dataURL.slice(pngPrefix.length);
169
+ }
150
170
  /**
151
171
  * Process messages from worker (if any).
152
172
  */
@@ -176,6 +196,14 @@ export class KernelMainBase extends KernelBase {
176
196
  //@ts-ignore
177
197
  msg.data.content = await self.basthon?.popDOMNode(id);
178
198
  }
199
+ else if (msg.data?.display_type === "canvas") {
200
+ const { width, height, buffer } = msg.data.content;
201
+ const png = await this.canvasArrayToPNGDataURL(width, height, buffer);
202
+ if (png == null)
203
+ return;
204
+ msg.data.display_type = "multiple";
205
+ msg.data.content = { "image/png": png };
206
+ }
179
207
  this.dispatchEvent("eval.display", msg.data);
180
208
  break;
181
209
  case "clear_output":
@@ -105,6 +105,10 @@ declare class KernelWorkerBase {
105
105
  * Display a blob (only png images are supported).
106
106
  */
107
107
  protected displayBlob(blob: Blob, data: any): Promise<void>;
108
+ /**
109
+ * Display a canvas.
110
+ */
111
+ protected displayCanvas(canvas: OffscreenCanvas, data: any): Promise<void>;
108
112
  /**
109
113
  * Display an element like a canvas, ... in the frontend.
110
114
  */
@@ -198,6 +198,21 @@ class KernelWorkerBase {
198
198
  }
199
199
  this.postMessage?.({ data, type: "display" });
200
200
  }
201
+ /**
202
+ * Display a canvas.
203
+ */
204
+ async displayCanvas(canvas, data) {
205
+ if (data == null)
206
+ data = this.clone(this.__eval_data__);
207
+ const { width, height } = canvas;
208
+ const ctx = canvas.getContext("2d");
209
+ if (ctx == null)
210
+ return;
211
+ const { data: imgData } = ctx.getImageData(0, 0, width, height); // Uint8ClampedArray raw RGBA
212
+ data["display_type"] = "canvas";
213
+ data["content"] = { width, height, buffer: imgData.buffer };
214
+ this.postMessage?.({ data, type: "display" }, [imgData.buffer]); // transfer buffer
215
+ }
201
216
  /**
202
217
  * Display an element like a canvas, ... in the frontend.
203
218
  */
@@ -205,10 +220,7 @@ class KernelWorkerBase {
205
220
  const data = this.clone(this.__eval_data__);
206
221
  if (globalThis.OffscreenCanvas != null &&
207
222
  element instanceof OffscreenCanvas) {
208
- this.addEvalPromise((async () => {
209
- const blob = await element.convertToBlob();
210
- await this.displayBlob(blob, data);
211
- })());
223
+ this.addEvalPromise(this.displayCanvas(element, data));
212
224
  }
213
225
  else {
214
226
  // in legacy mode, send HTML elements via DOM node bus
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basthon/kernel-base",
3
- "version": "0.78.0",
3
+ "version": "0.78.1",
4
4
  "description": "Basthon - Base Kernel",
5
5
  "homepage": "https://basthon.fr",
6
6
  "bugs": {