wasm-idle 0.3.2 → 0.4.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.
Files changed (46) hide show
  1. package/README.md +22 -2
  2. package/dist/clang/app.d.ts +2 -1
  3. package/dist/clang/app.js +166 -137
  4. package/dist/clang/index.d.ts +6 -0
  5. package/dist/clang/index.js +137 -21
  6. package/dist/debug/expression.js +135 -19
  7. package/dist/debug/index.d.ts +1 -1
  8. package/dist/debug/index.js +1 -1
  9. package/dist/debug/language/index.d.ts +1 -0
  10. package/dist/debug/language/index.js +1 -0
  11. package/dist/debug/language/python.d.ts +2 -0
  12. package/dist/debug/language/python.js +14 -0
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.js +1 -1
  15. package/dist/playground/assetBridge.d.ts +20 -0
  16. package/dist/playground/assetBridge.js +192 -0
  17. package/dist/playground/assets.d.ts +32 -0
  18. package/dist/playground/assets.js +97 -0
  19. package/dist/playground/clang.d.ts +11 -3
  20. package/dist/playground/clang.js +57 -20
  21. package/dist/playground/index.d.ts +2 -1
  22. package/dist/playground/index.js +10 -2
  23. package/dist/playground/java.d.ts +33 -0
  24. package/dist/playground/java.js +161 -0
  25. package/dist/playground/javaStdin.d.ts +8 -0
  26. package/dist/playground/javaStdin.js +323 -0
  27. package/dist/playground/options.d.ts +19 -0
  28. package/dist/playground/options.js +15 -1
  29. package/dist/playground/python.d.ts +21 -6
  30. package/dist/playground/python.js +135 -25
  31. package/dist/playground/sandbox.d.ts +5 -2
  32. package/dist/playground/stdinBuffer.d.ts +7 -0
  33. package/dist/playground/stdinBuffer.js +100 -0
  34. package/dist/playground/teavmConfig.d.ts +3 -0
  35. package/dist/playground/teavmConfig.js +14 -0
  36. package/dist/playground/worker/assets.d.ts +12 -0
  37. package/dist/playground/worker/assets.js +257 -0
  38. package/dist/playground/worker/clang.js +13 -23
  39. package/dist/playground/worker/java.d.ts +1 -0
  40. package/dist/playground/worker/java.js +228 -0
  41. package/dist/playground/worker/python.js +264 -58
  42. package/dist/terminal/Terminal.svelte +98 -18
  43. package/dist/terminal/Terminal.svelte.d.ts +4 -1
  44. package/dist/terminal/theme.js +2 -2
  45. package/dist/terminal/types.d.ts +4 -2
  46. package/package.json +11 -11
@@ -1,7 +1,9 @@
1
1
  import type { DebugCommand, DebugSessionEvent, SandboxExecutionOptions } from './options';
2
+ import type { PlaygroundRuntimeAssets } from './assets';
2
3
  import type { Sandbox } from './sandbox';
3
4
  import type { Writable } from 'svelte/store';
4
5
  declare class Clang implements Sandbox {
6
+ language: 'C' | 'CPP';
5
7
  ts: number;
6
8
  output: any;
7
9
  ondebug?: (event: DebugSessionEvent) => void;
@@ -9,20 +11,26 @@ declare class Clang implements Sandbox {
9
11
  buffer: SharedArrayBuffer;
10
12
  debugBuffer: SharedArrayBuffer;
11
13
  interruptBuffer: SharedArrayBuffer;
12
- internalBuffer: string[];
14
+ pendingInput: string[];
13
15
  begin: number;
14
16
  elapse: number;
15
17
  uid: number;
16
18
  log: boolean;
19
+ waitingForInput: boolean;
20
+ pendingEof: boolean;
17
21
  exit: boolean;
18
- load(path: string, code?: string, log?: boolean, args?: string[], _options?: SandboxExecutionOptions): Promise<void>;
22
+ constructor(language: 'C' | 'CPP');
23
+ load(runtimeAssets?: string | PlaygroundRuntimeAssets, code?: string, log?: boolean, args?: string[], _options?: SandboxExecutionOptions, _progress?: {
24
+ set?: (value: number) => void;
25
+ } | import('svelte/store').Writable<number>): Promise<void>;
19
26
  write(input: string): void;
20
- _write(input: string): void;
21
27
  eof(): void;
28
+ private flushPendingInput;
22
29
  run(code: string, prepare: boolean, log?: boolean, prog?: Writable<number> | {
23
30
  set?: (value: number) => void;
24
31
  }, args?: string[], options?: SandboxExecutionOptions): Promise<boolean | string>;
25
32
  debugCommand(command: DebugCommand): void;
33
+ kill(): void;
26
34
  terminate(): void;
27
35
  clear(): Promise<void>;
28
36
  }
@@ -1,4 +1,7 @@
1
+ import { resolveSandboxExecutionArgs } from './options';
2
+ import { flushBufferedEof, flushQueuedStdin, resetBufferedStdin } from './stdinBuffer';
1
3
  class Clang {
4
+ language;
2
5
  ts = Date.now();
3
6
  output = null;
4
7
  ondebug;
@@ -6,16 +9,24 @@ class Clang {
6
9
  buffer = new SharedArrayBuffer(1024);
7
10
  debugBuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4);
8
11
  interruptBuffer = new SharedArrayBuffer(1);
9
- internalBuffer = [];
12
+ pendingInput = [];
10
13
  begin = 0;
11
14
  elapse = 0;
12
15
  uid = 0;
13
16
  log = true;
17
+ waitingForInput = false;
18
+ pendingEof = false;
14
19
  exit = true;
15
- load(path, code = '', log = true, args = [], _options = {}) {
20
+ constructor(language) {
21
+ this.language = language;
22
+ }
23
+ load(runtimeAssets = '', code = '', log = true, args = [], _options = {}, _progress) {
16
24
  return new Promise(async (resolve) => {
17
25
  this.log = log;
18
- this.internalBuffer = [];
26
+ this.pendingInput = [];
27
+ this.waitingForInput = false;
28
+ this.pendingEof = false;
29
+ const path = typeof runtimeAssets === 'string' ? runtimeAssets : runtimeAssets?.rootUrl || '';
19
30
  if (!this.worker) {
20
31
  this.worker = new (await import('./worker/clang?worker')).default();
21
32
  this.worker.onmessage = () => resolve();
@@ -28,24 +39,33 @@ class Clang {
28
39
  });
29
40
  }
30
41
  write(input) {
31
- this.internalBuffer.push(input);
42
+ this.pendingInput.push(input);
43
+ this.pendingEof = false;
44
+ this.flushPendingInput();
32
45
  }
33
- _write(input) {
34
- let strInfo = input, padding = 4 - (strInfo.length % 4);
35
- while (strInfo.length % 4 !== 3)
36
- strInfo += ' ';
37
- strInfo += padding;
38
- const buffer = new Int32Array(this.buffer);
39
- const enc = new TextEncoder();
40
- const data = enc.encode(strInfo);
41
- buffer.set(new Int32Array(data.buffer.slice(data.byteOffset), 0));
46
+ eof() {
47
+ this.pendingEof = true;
48
+ this.flushPendingInput();
49
+ }
50
+ flushPendingInput() {
51
+ if (!this.waitingForInput)
52
+ return;
53
+ if (flushQueuedStdin(this.pendingInput, this.buffer)) {
54
+ this.waitingForInput = false;
55
+ return;
56
+ }
57
+ if (this.pendingEof) {
58
+ flushBufferedEof(this.buffer);
59
+ this.pendingEof = false;
60
+ this.waitingForInput = false;
61
+ }
42
62
  }
43
- eof() { }
44
63
  run(code, prepare, log = this.log, prog, args = [], options = {}) {
45
64
  this.exit = false;
46
65
  return new Promise(async (resolve, reject) => {
47
66
  if (!this.worker)
48
67
  return reject('Worker not loaded');
68
+ const { compileArgs, programArgs } = resolveSandboxExecutionArgs(this.language, args, options);
49
69
  const interrupt = new Uint8Array(this.interruptBuffer), _uid = ++this.uid;
50
70
  const handler = (event) => {
51
71
  if (!this.worker)
@@ -53,8 +73,10 @@ class Clang {
53
73
  if (_uid !== this.uid)
54
74
  return (this.worker.onmessage = null);
55
75
  const { id, output, results, log, error, buffer, progress, debugEvent } = event.data;
56
- if (buffer && this.internalBuffer.length)
57
- this._write(this.internalBuffer.splice(0, 1)[0]);
76
+ if (buffer) {
77
+ this.waitingForInput = true;
78
+ this.flushPendingInput();
79
+ }
58
80
  if (output)
59
81
  this.output(output);
60
82
  if (debugEvent)
@@ -62,6 +84,8 @@ class Clang {
62
84
  if (results) {
63
85
  this.elapse = Date.now() - this.begin;
64
86
  this.exit = true;
87
+ this.waitingForInput = false;
88
+ this.pendingEof = false;
65
89
  this.ondebug?.({ type: 'stop' });
66
90
  resolve(results);
67
91
  }
@@ -69,6 +93,10 @@ class Clang {
69
93
  console.log(log);
70
94
  if (error) {
71
95
  this.elapse = Date.now() - this.begin;
96
+ this.waitingForInput = false;
97
+ this.pendingEof = false;
98
+ this.exit = true;
99
+ this.ondebug?.({ type: 'stop' });
72
100
  reject(error);
73
101
  }
74
102
  if (progress)
@@ -85,7 +113,11 @@ class Clang {
85
113
  interrupt: this.interruptBuffer,
86
114
  context: {},
87
115
  log,
88
- args,
116
+ language: this.language,
117
+ compileArgs,
118
+ programArgs,
119
+ cppVersion: options.cppVersion,
120
+ cVersion: options.cVersion,
89
121
  debug: !!options.debug,
90
122
  breakpoints: [...(options.breakpoints || [])],
91
123
  pauseOnEntry: !!options.pauseOnEntry
@@ -99,7 +131,11 @@ class Clang {
99
131
  Atomics.notify(control, 0);
100
132
  this.ondebug?.({ type: 'resume', command });
101
133
  }
134
+ kill() {
135
+ this.terminate();
136
+ }
102
137
  terminate() {
138
+ this.pendingEof = false;
103
139
  new Uint8Array(this.interruptBuffer)[0] = 2;
104
140
  const control = new Int32Array(this.debugBuffer);
105
141
  Atomics.add(control, 0, 1);
@@ -107,11 +143,12 @@ class Clang {
107
143
  }
108
144
  async clear() {
109
145
  this.terminate();
110
- this.internalBuffer = [];
146
+ this.pendingInput = [];
147
+ this.waitingForInput = false;
148
+ this.pendingEof = false;
111
149
  if (this.worker)
112
150
  this.worker.onmessage = null;
113
- const buffer = new Int32Array(this.buffer);
114
- buffer.fill(0);
151
+ resetBufferedStdin(this.buffer);
115
152
  const debugBuffer = new Int32Array(this.debugBuffer);
116
153
  debugBuffer.fill(0);
117
154
  await new Promise((resolve) => setTimeout(resolve, 200));
@@ -1,5 +1,6 @@
1
1
  import Clang from './clang';
2
+ import Java from './java';
2
3
  import Python from './python';
3
4
  import type { Sandbox } from './sandbox';
4
5
  export declare const supportedLanguages: string[];
5
- export default function load(language: string): Promise<Sandbox | Clang | Python>;
6
+ export default function load(language: string): Promise<Sandbox | Clang | Java | Python>;
@@ -1,7 +1,8 @@
1
1
  import Clang from './clang';
2
+ import Java from './java';
2
3
  import Python from './python';
3
4
  const sandboxCache = {};
4
- export const supportedLanguages = ['PYTHON3', 'PYPY3', 'C', 'CPP'];
5
+ export const supportedLanguages = ['PYTHON3', 'PYPY3', 'C', 'CPP', 'JAVA'];
5
6
  export default async function load(language) {
6
7
  if (sandboxCache[language])
7
8
  return sandboxCache[language];
@@ -13,8 +14,13 @@ export default async function load(language) {
13
14
  sandbox = new Python();
14
15
  break;
15
16
  case 'C':
17
+ sandbox = new Clang('C');
18
+ break;
16
19
  case 'CPP':
17
- sandbox = new Clang();
20
+ sandbox = new Clang('CPP');
21
+ break;
22
+ case 'JAVA':
23
+ sandbox = new Java();
18
24
  break;
19
25
  default:
20
26
  throw new Error(`Unsupported language: ${language}`);
@@ -31,6 +37,8 @@ export default async function load(language) {
31
37
  sandboxCache['C'] = sandbox;
32
38
  if (language === 'CPP')
33
39
  sandboxCache['CPP'] = sandbox;
40
+ if (language === 'JAVA')
41
+ sandboxCache['JAVA'] = sandbox;
34
42
  }
35
43
  return sandbox;
36
44
  }
@@ -0,0 +1,33 @@
1
+ import { type CompilerDiagnostic, type SandboxExecutionOptions } from './options';
2
+ import { WorkerAssetBridge } from './assetBridge';
3
+ import { type PlaygroundRuntimeAssets } from './assets';
4
+ import type { Sandbox } from './sandbox';
5
+ declare class Java implements Sandbox {
6
+ output: any;
7
+ worker?: Worker;
8
+ buffer: SharedArrayBuffer;
9
+ pendingInput: string[];
10
+ begin: number;
11
+ elapse: number;
12
+ uid: number;
13
+ exit: boolean;
14
+ baseUrl: string;
15
+ activeReject: ((reason: string) => void) | null;
16
+ oncompilerdiagnostic?: (diagnostic: CompilerDiagnostic) => void;
17
+ waitingForInput: boolean;
18
+ pendingEof: boolean;
19
+ assetBridge: WorkerAssetBridge | null;
20
+ load(runtimeAssets?: string | PlaygroundRuntimeAssets, _code?: string, _log?: boolean, _args?: string[], _options?: SandboxExecutionOptions, progress?: {
21
+ set?: (value: number) => void;
22
+ } | import('svelte/store').Writable<number>): Promise<void>;
23
+ write(input: string): void;
24
+ eof(): void;
25
+ private flushPendingInput;
26
+ run(code: string, prepare: boolean, _log?: boolean, _prog?: {
27
+ set?: (value: number) => void;
28
+ } | import('svelte/store').Writable<number>, args?: string[], options?: SandboxExecutionOptions): Promise<boolean | string>;
29
+ kill(): void;
30
+ terminate(): void;
31
+ clear(): Promise<void>;
32
+ }
33
+ export default Java;
@@ -0,0 +1,161 @@
1
+ import { resolveSandboxExecutionArgs } from './options';
2
+ import { WorkerAssetBridge } from './assetBridge';
3
+ import { resolveRuntimeAssetConfig } from './assets';
4
+ import { flushBufferedEof, flushQueuedStdin, resetBufferedStdin } from './stdinBuffer';
5
+ class Java {
6
+ output = null;
7
+ worker = null;
8
+ buffer = new SharedArrayBuffer(1024);
9
+ pendingInput = [];
10
+ begin = 0;
11
+ elapse = 0;
12
+ uid = 0;
13
+ exit = true;
14
+ baseUrl = '';
15
+ activeReject = null;
16
+ oncompilerdiagnostic;
17
+ waitingForInput = false;
18
+ pendingEof = false;
19
+ assetBridge = null;
20
+ load(runtimeAssets = '', _code = '', _log = true, _args = [], _options = {}, progress) {
21
+ return new Promise(async (resolve, reject) => {
22
+ this.pendingInput = [];
23
+ this.waitingForInput = false;
24
+ this.pendingEof = false;
25
+ const assetConfig = resolveRuntimeAssetConfig('java', runtimeAssets, typeof window !== 'undefined' ? window.location.href : '');
26
+ this.baseUrl = assetConfig.baseUrl;
27
+ const needsWorkerReset = !this.worker || !this.assetBridge || !this.assetBridge.matches(assetConfig);
28
+ if (needsWorkerReset && this.worker) {
29
+ this.worker.terminate();
30
+ delete this.worker;
31
+ this.assetBridge = null;
32
+ }
33
+ if (!this.worker) {
34
+ this.worker = new (await import('./worker/java?worker')).default();
35
+ this.assetBridge = new WorkerAssetBridge(this.worker, 'java', assetConfig, progress);
36
+ this.worker.onmessage = (event) => {
37
+ if (this.assetBridge?.handleMessage(event))
38
+ return;
39
+ if (event.data?.load)
40
+ resolve();
41
+ if (event.data?.error)
42
+ reject(event.data.error);
43
+ };
44
+ this.worker.postMessage({
45
+ load: true,
46
+ assets: {
47
+ baseUrl: assetConfig.baseUrl,
48
+ useAssetBridge: assetConfig.useAssetBridge
49
+ }
50
+ });
51
+ }
52
+ else {
53
+ if (!this.assetBridge)
54
+ return reject('Worker asset bridge unavailable');
55
+ this.assetBridge.rebind(this.worker, assetConfig, progress);
56
+ resolve();
57
+ }
58
+ });
59
+ }
60
+ write(input) {
61
+ this.pendingInput.push(input);
62
+ this.pendingEof = false;
63
+ this.flushPendingInput();
64
+ }
65
+ eof() {
66
+ this.pendingEof = true;
67
+ this.flushPendingInput();
68
+ }
69
+ flushPendingInput() {
70
+ if (!this.waitingForInput)
71
+ return;
72
+ if (flushQueuedStdin(this.pendingInput, this.buffer)) {
73
+ this.waitingForInput = false;
74
+ return;
75
+ }
76
+ if (this.pendingEof) {
77
+ flushBufferedEof(this.buffer);
78
+ this.pendingEof = false;
79
+ this.waitingForInput = false;
80
+ }
81
+ }
82
+ run(code, prepare, _log = true, _prog, args = [], options = {}) {
83
+ this.exit = false;
84
+ return new Promise((resolve, reject) => {
85
+ if (!this.worker)
86
+ return reject('Worker not loaded');
87
+ const { programArgs } = resolveSandboxExecutionArgs('JAVA', args, options);
88
+ const _uid = ++this.uid;
89
+ this.activeReject = reject;
90
+ const handler = (event) => {
91
+ if (this.assetBridge?.handleMessage(event))
92
+ return;
93
+ if (!this.worker)
94
+ return reject('Worker not loaded');
95
+ if (_uid !== this.uid)
96
+ return (this.worker.onmessage = null);
97
+ const { output, results, error, buffer, diagnostic } = event.data;
98
+ if (buffer) {
99
+ this.waitingForInput = true;
100
+ this.flushPendingInput();
101
+ }
102
+ if (output)
103
+ this.output(output);
104
+ if (diagnostic)
105
+ this.oncompilerdiagnostic?.(diagnostic);
106
+ if (results) {
107
+ this.elapse = Date.now() - this.begin;
108
+ this.exit = true;
109
+ this.waitingForInput = false;
110
+ this.pendingEof = false;
111
+ this.activeReject = null;
112
+ resolve(results);
113
+ }
114
+ if (error) {
115
+ this.elapse = Date.now() - this.begin;
116
+ this.exit = true;
117
+ this.waitingForInput = false;
118
+ this.pendingEof = false;
119
+ this.activeReject = null;
120
+ reject(error);
121
+ }
122
+ };
123
+ this.worker.onmessage = handler;
124
+ this.begin = Date.now();
125
+ this.worker.postMessage({
126
+ code,
127
+ prepare,
128
+ buffer: this.buffer,
129
+ args: programArgs,
130
+ stdin: options.stdin || '',
131
+ baseUrl: this.baseUrl
132
+ });
133
+ });
134
+ }
135
+ kill() {
136
+ this.terminate();
137
+ }
138
+ terminate() {
139
+ this.activeReject?.('Process terminated');
140
+ this.activeReject = null;
141
+ this.waitingForInput = false;
142
+ this.pendingEof = false;
143
+ this.uid += 1;
144
+ this.worker?.terminate?.();
145
+ delete this.worker;
146
+ this.assetBridge = null;
147
+ this.exit = true;
148
+ }
149
+ async clear() {
150
+ this.pendingInput = [];
151
+ this.waitingForInput = false;
152
+ this.pendingEof = false;
153
+ if (this.worker)
154
+ this.worker.onmessage = null;
155
+ resetBufferedStdin(this.buffer);
156
+ if (!this.exit) {
157
+ this.terminate();
158
+ }
159
+ }
160
+ }
161
+ export default Java;
@@ -0,0 +1,8 @@
1
+ export interface PreparedJavaStdinInjection {
2
+ usesStdin: boolean;
3
+ stdinCacheKey: string;
4
+ transformedCode: string;
5
+ helperSourcePath: string | null;
6
+ helperSource: string | null;
7
+ }
8
+ export declare const prepareJavaStdinInjection: (code: string, stdin: string) => PreparedJavaStdinInjection;