@basthon/kernel-base 0.71.5 → 0.72.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.71.5";
1
+ export declare const VERSION = "0.72.1";
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.71.5";
1
+ export const VERSION = "0.72.1";
@@ -8,6 +8,8 @@ export declare class KernelMainBase<Type extends KernelWorkerBase> extends Kerne
8
8
  private postMessageToWorker?;
9
9
  private _sab?;
10
10
  private _channelSyncer;
11
+ private _fallbackKey?;
12
+ private _encrypt;
11
13
  constructor(options: any);
12
14
  /**
13
15
  * Is this a legacy worker? i.e. not runing in a worker.
@@ -11,11 +11,16 @@ export class KernelMainBase extends KernelBase {
11
11
  super(options);
12
12
  // synchronise comlink and communication channels
13
13
  this._channelSyncer = new PromiseDelegate();
14
+ this._encrypt = (s) => s;
14
15
  this._legacy = options?.legacy === true;
15
16
  // synchronous wait on SAB cannot be used in a legacy context
16
17
  // (atomic wait will block the main thread)
17
- if (!this.isLegacy() && globalThis.crossOriginIsolated)
18
- this._sab = new SharedArrayBuffer(1024);
18
+ if (!this.isLegacy()) {
19
+ if (globalThis.crossOriginIsolated)
20
+ this._sab = new SharedArrayBuffer(1024);
21
+ else
22
+ this._fallbackKey = globalThis.crypto.randomUUID();
23
+ }
19
24
  }
20
25
  /**
21
26
  * Is this a legacy worker? i.e. not runing in a worker.
@@ -105,6 +110,14 @@ export class KernelMainBase extends KernelBase {
105
110
  console.log("Using SharedArrayBuffer for synchronous worker communication.");
106
111
  await this._remote?.setSAB(this._sab);
107
112
  }
113
+ else if (this._fallbackKey != null) {
114
+ console.warn("SharedArrayBuffer not available, falling back to " +
115
+ "using third-party server for synchronous worker communication.");
116
+ const pass = globalThis.crypto.randomUUID();
117
+ await this.remote?.setFallbackKeyAndPass(this._fallbackKey, pass);
118
+ const AES = await import("crypto-js/aes");
119
+ this._encrypt = (message) => AES.encrypt(message, pass).toString();
120
+ }
108
121
  // bind ports
109
122
  const port = await proxy[createEndpoint]();
110
123
  await this.remote?.setProxyPort(transfer(port, [port]));
@@ -180,6 +193,21 @@ export class KernelMainBase extends KernelBase {
180
193
  new Uint8Array(this._sab).set(encodedRes.subarray(0, this._sab.byteLength));
181
194
  Atomics.notify(new Int32Array(this._sab), 0, 1);
182
195
  }
196
+ else {
197
+ const response = await fetch("https://api.basthon.fr/ephemeral", {
198
+ method: "POST",
199
+ headers: {
200
+ "X-API-Referer": self.location.href,
201
+ },
202
+ body: JSON.stringify({
203
+ action: "post",
204
+ key: this._fallbackKey,
205
+ payload: this._encrypt(res),
206
+ }),
207
+ });
208
+ if (!response.ok)
209
+ throw new Error(`Basthon's network API error: ${response.status}`);
210
+ }
183
211
  break;
184
212
  case "breakpoint-move-on":
185
213
  //@ts-ignore
@@ -27,6 +27,8 @@ declare class KernelWorkerBase {
27
27
  private _sab?;
28
28
  private _domNodeBus?;
29
29
  private _toplevelInputPromise?;
30
+ private _fallbackKey?;
31
+ private _decrypt;
30
32
  constructor(options?: any);
31
33
  /**
32
34
  * Language implemented in the kernel (string).
@@ -62,6 +64,7 @@ declare class KernelWorkerBase {
62
64
  * Add a promise we should wait for during eval process.
63
65
  */
64
66
  protected addEvalPromise(promise: Promise<void>): void;
67
+ setFallbackKeyAndPass(key: string, pass: string): Promise<void>;
65
68
  protected _init(): Promise<void>;
66
69
  /**
67
70
  * Initialize the kernel. It is called by initWorker in KernelBase.
@@ -7,6 +7,7 @@ class KernelWorkerBase {
7
7
  constructor(options) {
8
8
  this._ready = new PromiseDelegate();
9
9
  this._evalPromises = []; // used to wait all promises emitted during computation
10
+ this._decrypt = (s) => s;
10
11
  this._options = options;
11
12
  this._legacy = options?.legacy === true;
12
13
  this._basthonRoot = self._assetsURL + "/" + VERSION + "/" + this.language();
@@ -92,6 +93,15 @@ class KernelWorkerBase {
92
93
  addEvalPromise(promise) {
93
94
  this._evalPromises.push(promise);
94
95
  }
96
+ /*
97
+ * Set fallback API key and encryption pass
98
+ * (if SharedArrayBuffer are not available).
99
+ */
100
+ async setFallbackKeyAndPass(key, pass) {
101
+ this._fallbackKey = key;
102
+ const CryptoJS = await import("crypto-js");
103
+ this._decrypt = (message) => CryptoJS.AES.decrypt(message, pass).toString(CryptoJS.enc.Utf8);
104
+ }
95
105
  /*
96
106
  * Initialize the kernel. Should be overloaded.
97
107
  */
@@ -339,12 +349,15 @@ class KernelWorkerBase {
339
349
  * an eval.input event to the main thread and wait for the response.
340
350
  */
341
351
  input(prompt, password = false) {
342
- if (this.syncCommSupport()) {
352
+ const sendInput = () => {
343
353
  const data = this.clone(this.__eval_data__);
344
354
  this.postMessage?.({
345
355
  type: "input",
346
356
  content: { data, prompt, password },
347
357
  });
358
+ };
359
+ if (this.syncCommSupport()) {
360
+ sendInput();
348
361
  // ensure value before waiting
349
362
  Atomics.store(new Int32Array(this._sab), 0, 0);
350
363
  Atomics.wait(new Int32Array(this._sab), 0, 0);
@@ -355,8 +368,19 @@ class KernelWorkerBase {
355
368
  return self._prompt(prompt ?? "") ?? "";
356
369
  }
357
370
  else {
358
- // basthon's API not yet implemented
359
- throw new Error("Your browser does not support SharedArrayBuffer. Please try to update it.");
371
+ sendInput();
372
+ const timeout = 2 * 60 * 1000; // 2 minutes
373
+ const tend = Date.now() + timeout;
374
+ // polling loop
375
+ while (Date.now() < tend) {
376
+ const request = new XMLHttpRequest();
377
+ request.open("POST", "https://api.basthon.fr/ephemeral", false); // synchronous request
378
+ request.setRequestHeader("X-API-Referer", this._basthonRoot ?? "null");
379
+ request.send(JSON.stringify({ action: "get", key: this._fallbackKey }));
380
+ if (request.status === 200)
381
+ return this._decrypt(request.responseText);
382
+ }
383
+ throw new Error("Error using the Basthon's network API");
360
384
  }
361
385
  }
362
386
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basthon/kernel-base",
3
- "version": "0.71.5",
3
+ "version": "0.72.1",
4
4
  "description": "Basthon - Base Kernel",
5
5
  "homepage": "https://basthon.fr",
6
6
  "bugs": {
@@ -35,14 +35,16 @@
35
35
  "clean": "rm -rf lib/ src/version.ts"
36
36
  },
37
37
  "dependencies": {
38
+ "crypto-js": "^4.2.0",
38
39
  "promise-delegate": "^1.0.1"
39
40
  },
40
41
  "devDependencies": {
42
+ "@types/crypto-js": "^4.2.2",
41
43
  "json": "^11.0.0",
42
44
  "typescript": "~5.4.5"
43
45
  },
44
46
  "publishConfig": {
45
47
  "access": "public"
46
48
  },
47
- "gitHead": "9388c98162e479baed187c63a3179bc4fd71e7f4"
49
+ "gitHead": "371c6e2e957238a2374418f52dd0166ba6172ff8"
48
50
  }