wasm-idle 0.1.0 → 0.2.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/README.md +1 -1
- package/dist/clang/app.d.ts +1 -1
- package/dist/clang/app.js +9 -9
- package/dist/clang/encode.d.ts +1 -1
- package/dist/clang/index.d.ts +3 -3
- package/dist/clang/index.js +25 -19
- package/dist/clang/memory/index.d.ts +3 -3
- package/dist/clang/memory/index.js +3 -3
- package/dist/clang/memory/memFs.d.ts +2 -2
- package/dist/clang/memory/memFs.js +7 -7
- package/dist/clang/memory/memory.js +2 -2
- package/dist/clang/memory/tar.d.ts +1 -1
- package/dist/clang/memory/tar.js +5 -5
- package/dist/clang/wasm.d.ts +2 -2
- package/dist/clang/wasm.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/playground/clang.d.ts +2 -2
- package/dist/playground/clang.js +3 -4
- package/dist/playground/index.d.ts +3 -2
- package/dist/playground/index.js +3 -0
- package/dist/playground/python.d.ts +1 -1
- package/dist/playground/python.js +2 -3
- package/dist/playground/sandbox.d.ts +5 -2
- package/dist/playground/sandbox.js +1 -1
- package/dist/playground/worker/clang.js +2 -1
- package/dist/terminal/Terminal.svelte +215 -152
- package/dist/terminal/Terminal.svelte.d.ts +14 -34
- package/dist/terminal/index.d.ts +3 -3
- package/dist/terminal/index.js +3 -3
- package/package.json +71 -71
package/README.md
CHANGED
package/dist/clang/app.d.ts
CHANGED
package/dist/clang/app.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { bindNew } from
|
|
2
|
-
import { Memory } from
|
|
3
|
-
import { getInstance } from
|
|
4
|
-
import { NotImplemented, ProcExit } from
|
|
1
|
+
import { bindNew } from './apply';
|
|
2
|
+
import { Memory } from './memory';
|
|
3
|
+
import { getInstance } from './wasm';
|
|
4
|
+
import { NotImplemented, ProcExit } from './error';
|
|
5
5
|
const ESUCCESS = 0;
|
|
6
|
-
const RAF_PROC_EXIT_CODE =
|
|
6
|
+
const RAF_PROC_EXIT_CODE = 0xc0c0a;
|
|
7
7
|
export default class App {
|
|
8
8
|
ready;
|
|
9
9
|
mem = null;
|
|
@@ -20,9 +20,10 @@ export default class App {
|
|
|
20
20
|
this.memfs = memfs;
|
|
21
21
|
const env = bindNew(this);
|
|
22
22
|
const wasi_unstable = {
|
|
23
|
-
...bindNew(this, 'proc_exit', 'environ_sizes_get', 'environ_get', 'args_sizes_get', 'args_get', 'random_get', 'clock_time_get', 'poll_oneoff'),
|
|
23
|
+
...bindNew(this, 'proc_exit', 'environ_sizes_get', 'environ_get', 'args_sizes_get', 'args_get', 'random_get', 'clock_time_get', 'poll_oneoff'),
|
|
24
|
+
...this.memfs.exports
|
|
24
25
|
};
|
|
25
|
-
this.ready = getInstance(module, { wasi_unstable, env }).then(instance => {
|
|
26
|
+
this.ready = getInstance(module, { wasi_unstable, env }).then((instance) => {
|
|
26
27
|
this.instance = instance;
|
|
27
28
|
this.exports = this.instance.exports;
|
|
28
29
|
this.mem = new Memory(this.exports.memory);
|
|
@@ -79,8 +80,7 @@ export default class App {
|
|
|
79
80
|
for (const name of names) {
|
|
80
81
|
this.mem.write32(environ_ptrs, environ_buf);
|
|
81
82
|
environ_ptrs += 4;
|
|
82
|
-
environ_buf +=
|
|
83
|
-
this.mem.writeStr(environ_buf, `${name}=${this.environ[name]}`);
|
|
83
|
+
environ_buf += this.mem.writeStr(environ_buf, `${name}=${this.environ[name]}`);
|
|
84
84
|
}
|
|
85
85
|
this.mem.write32(environ_ptrs, 0);
|
|
86
86
|
return ESUCCESS;
|
package/dist/clang/encode.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare function readStr(u8: Uint8Array, o: number, len?: number): string;
|
|
2
2
|
export declare function readStrR(u8: Uint8Array, o: number, len?: number): string;
|
|
3
3
|
export declare function readOct(u8: Uint8Array, o: number, len: number): number;
|
|
4
|
-
export declare function readUint8(u8: Uint8Array, o: number, len: number): Uint8Array
|
|
4
|
+
export declare function readUint8(u8: Uint8Array, o: number, len: number): Uint8Array<ArrayBufferLike>;
|
package/dist/clang/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import App from
|
|
2
|
-
import { MemFS } from
|
|
3
|
-
import { type Writable } from
|
|
1
|
+
import App from './app';
|
|
2
|
+
import { MemFS } from './memory';
|
|
3
|
+
import { type Writable } from 'svelte/store';
|
|
4
4
|
interface APIOption {
|
|
5
5
|
stdin: () => string;
|
|
6
6
|
stdout: (str: string) => void;
|
package/dist/clang/index.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import App from
|
|
2
|
-
import { MemFS, untar } from
|
|
3
|
-
import { green, yellow, normal } from
|
|
4
|
-
import { compile, readBuffer } from
|
|
5
|
-
import { clangUrl, lldUrl, rootUrl } from
|
|
6
|
-
import { derived, writable } from
|
|
1
|
+
import App from './app';
|
|
2
|
+
import { MemFS, untar } from './memory';
|
|
3
|
+
import { green, yellow, normal } from './color';
|
|
4
|
+
import { compile, readBuffer } from './wasm';
|
|
5
|
+
import { clangUrl, lldUrl, rootUrl } from './url';
|
|
6
|
+
import { derived, writable } from 'svelte/store';
|
|
7
7
|
const clangCommonArgs = [
|
|
8
8
|
'-disable-free',
|
|
9
|
-
'-isysroot',
|
|
10
|
-
'
|
|
11
|
-
'-internal-isystem',
|
|
12
|
-
'
|
|
13
|
-
'-
|
|
14
|
-
'
|
|
15
|
-
'-
|
|
9
|
+
'-isysroot',
|
|
10
|
+
'/',
|
|
11
|
+
'-internal-isystem',
|
|
12
|
+
'/include/c++/v1',
|
|
13
|
+
'-internal-isystem',
|
|
14
|
+
'/include',
|
|
15
|
+
'-internal-isystem',
|
|
16
|
+
'/lib/clang/8.0.1/include',
|
|
17
|
+
'-ferror-limit',
|
|
18
|
+
'19',
|
|
19
|
+
'-fmessage-length',
|
|
20
|
+
'80',
|
|
21
|
+
'-fcolor-diagnostics'
|
|
16
22
|
];
|
|
17
23
|
const toUtf8 = (text) => {
|
|
18
24
|
const surrogate = encodeURIComponent(text);
|
|
@@ -21,7 +27,7 @@ const toUtf8 = (text) => {
|
|
|
21
27
|
const character = surrogate[i];
|
|
22
28
|
i += 1;
|
|
23
29
|
if (character == '%') {
|
|
24
|
-
const hex = surrogate.substring(i, i += 2);
|
|
30
|
+
const hex = surrogate.substring(i, (i += 2));
|
|
25
31
|
if (hex)
|
|
26
32
|
result += String.fromCharCode(parseInt(hex, 16));
|
|
27
33
|
}
|
|
@@ -44,7 +50,7 @@ export default class Clang {
|
|
|
44
50
|
progress = {
|
|
45
51
|
clang: writable(0),
|
|
46
52
|
lld: writable(0),
|
|
47
|
-
memfs: writable(0)
|
|
53
|
+
memfs: writable(0)
|
|
48
54
|
};
|
|
49
55
|
constructor(options) {
|
|
50
56
|
this.moduleCache = {};
|
|
@@ -56,17 +62,17 @@ export default class Clang {
|
|
|
56
62
|
stdout: this.stdout,
|
|
57
63
|
stdin: options.stdin,
|
|
58
64
|
path: this.path,
|
|
59
|
-
progress: this.progress.memfs
|
|
65
|
+
progress: this.progress.memfs
|
|
60
66
|
});
|
|
61
67
|
const progress = derived([this.progress.clang, this.progress.lld, this.progress.memfs], ([clang, lld, memfs]) => {
|
|
62
68
|
return (clang + lld + memfs) / 3;
|
|
63
69
|
});
|
|
64
|
-
progress.subscribe(value => {
|
|
70
|
+
progress.subscribe((value) => {
|
|
65
71
|
options.progress(value);
|
|
66
72
|
});
|
|
67
73
|
this.getModule(clangUrl(this.path), this.progress.clang);
|
|
68
74
|
this.getModule(lldUrl(this.path), this.progress.lld);
|
|
69
|
-
this.ready = this.memfs.ready.then(() => this.hostLogAsync(`Untarring ${rootUrl(this.path)}`, readBuffer(rootUrl(this.path)).then(buffer => untar(buffer, this.memfs))));
|
|
75
|
+
this.ready = this.memfs.ready.then(() => this.hostLogAsync(`Untarring ${rootUrl(this.path)}`, readBuffer(rootUrl(this.path)).then((buffer) => untar(buffer, this.memfs))));
|
|
70
76
|
}
|
|
71
77
|
hostLog(message) {
|
|
72
78
|
if (!this.log)
|
|
@@ -134,7 +140,7 @@ export default class Clang {
|
|
|
134
140
|
await this.compile({ input, code, obj });
|
|
135
141
|
await this.link(obj, wasm);
|
|
136
142
|
this.lastCode = code;
|
|
137
|
-
return this.wasm = await this.hostLogAsync(`Compiling ${wasm}`, WebAssembly.compile(this.memfs.getFileContents(wasm)));
|
|
143
|
+
return (this.wasm = await this.hostLogAsync(`Compiling ${wasm}`, WebAssembly.compile(this.memfs.getFileContents(wasm))));
|
|
138
144
|
}
|
|
139
145
|
async compileLinkRun(code) {
|
|
140
146
|
return await this.run(await this.compileLink(code), true, `test.wasm`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import MemFS from
|
|
2
|
-
import Memory from
|
|
3
|
-
import untar from
|
|
1
|
+
import MemFS from './memFs';
|
|
2
|
+
import Memory from './memory';
|
|
3
|
+
import untar from './tar';
|
|
4
4
|
export { MemFS, Memory, untar };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import MemFS from
|
|
2
|
-
import Memory from
|
|
3
|
-
import untar from
|
|
1
|
+
import MemFS from './memFs';
|
|
2
|
+
import Memory from './memory';
|
|
3
|
+
import untar from './tar';
|
|
4
4
|
export { MemFS, Memory, untar };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Memory } from './';
|
|
2
|
-
import type { Writable } from
|
|
2
|
+
import type { Writable } from 'svelte/store';
|
|
3
3
|
interface MemFsOptions {
|
|
4
4
|
stdin: () => string;
|
|
5
5
|
stdout: (str: string) => void;
|
|
@@ -22,7 +22,7 @@ export default class MemFS {
|
|
|
22
22
|
setStdinStr(str: string): void;
|
|
23
23
|
addDirectory(path: string): void;
|
|
24
24
|
addFile(path: string, contents: string | ArrayBuffer | Uint8Array): void;
|
|
25
|
-
getFileContents(path: string): Uint8Array
|
|
25
|
+
getFileContents(path: string): Uint8Array<ArrayBuffer>;
|
|
26
26
|
abort(): void;
|
|
27
27
|
host_write(fd: number, iovs: number, iovs_len: number, nwritten_out: number): number;
|
|
28
28
|
host_read(fd: number, iovs: number, iovs_len: number, nread: number): number;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Memory } from './';
|
|
2
|
-
import { bindNew } from
|
|
3
|
-
import { AbortError, assert } from
|
|
4
|
-
import { compile } from
|
|
5
|
-
import { memfsUrl } from
|
|
2
|
+
import { bindNew } from '../apply';
|
|
3
|
+
import { AbortError, assert } from '../error';
|
|
4
|
+
import { compile } from '../wasm';
|
|
5
|
+
import { memfsUrl } from '../url';
|
|
6
6
|
const ESUCCESS = 0;
|
|
7
7
|
export default class MemFS {
|
|
8
8
|
ready;
|
|
@@ -17,11 +17,11 @@ export default class MemFS {
|
|
|
17
17
|
constructor(options) {
|
|
18
18
|
this.stdin = options.stdin;
|
|
19
19
|
this.stdout = options.stdout;
|
|
20
|
-
this.stdinStr = options.stdinStr ||
|
|
20
|
+
this.stdinStr = options.stdinStr || '';
|
|
21
21
|
const env = bindNew(this, 'abort', 'host_write', 'host_read', 'memfs_log', 'copy_in', 'copy_out');
|
|
22
22
|
this.ready = compile(memfsUrl(options.path), options.progress)
|
|
23
|
-
.then(module => WebAssembly.instantiate(module, { env }))
|
|
24
|
-
.then(instance => {
|
|
23
|
+
.then((module) => WebAssembly.instantiate(module, { env }))
|
|
24
|
+
.then((instance) => {
|
|
25
25
|
this.instance = instance;
|
|
26
26
|
this.exports = instance.exports;
|
|
27
27
|
this.mem = new Memory(this.exports.memory);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readStr, readStrR } from
|
|
1
|
+
import { readStr, readStrR } from '../encode';
|
|
2
2
|
export default class Memory {
|
|
3
3
|
memory;
|
|
4
4
|
buffer;
|
|
@@ -52,7 +52,7 @@ export default class Memory {
|
|
|
52
52
|
if (buf instanceof ArrayBuffer)
|
|
53
53
|
return this.writeUint8(o, new Uint8Array(buf));
|
|
54
54
|
else if (typeof buf === 'string')
|
|
55
|
-
return this.writeUint8(o, buf.split('').map(x => x.charCodeAt(0)));
|
|
55
|
+
return this.writeUint8(o, buf.split('').map((x) => x.charCodeAt(0)));
|
|
56
56
|
else
|
|
57
57
|
return this.writeUint8(o, buf);
|
|
58
58
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { MemFS } from
|
|
1
|
+
import type { MemFS } from './';
|
|
2
2
|
export default function untar(buffer: ArrayBuffer, memfs: MemFS): void;
|
package/dist/clang/memory/tar.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readStr, readOct } from
|
|
2
|
-
import { assert } from
|
|
1
|
+
import { readStr, readOct } from '../encode';
|
|
2
|
+
import { assert } from '../error';
|
|
3
3
|
function* readEntry(buffer) {
|
|
4
4
|
const u8 = new Uint8Array(buffer);
|
|
5
5
|
let offset = 0;
|
|
@@ -9,7 +9,7 @@ function* readEntry(buffer) {
|
|
|
9
9
|
}, oct = (len) => {
|
|
10
10
|
offset += len;
|
|
11
11
|
return readOct(u8, offset - len, len);
|
|
12
|
-
}, align = () => offset = (offset + 511) & ~511;
|
|
12
|
+
}, align = () => (offset = (offset + 511) & ~511);
|
|
13
13
|
while (offset + 512 <= u8.length) {
|
|
14
14
|
const entryInit = {
|
|
15
15
|
filename: str(100),
|
|
@@ -21,7 +21,7 @@ function* readEntry(buffer) {
|
|
|
21
21
|
checksum: oct(8),
|
|
22
22
|
type: str(1),
|
|
23
23
|
linkname: str(100),
|
|
24
|
-
ustar: str(8)
|
|
24
|
+
ustar: str(8)
|
|
25
25
|
};
|
|
26
26
|
if (!entryInit.ustar)
|
|
27
27
|
return;
|
|
@@ -31,7 +31,7 @@ function* readEntry(buffer) {
|
|
|
31
31
|
groupName: str(32),
|
|
32
32
|
devMajor: str(8),
|
|
33
33
|
devMinor: str(8),
|
|
34
|
-
filenamePrefix: str(155)
|
|
34
|
+
filenamePrefix: str(155)
|
|
35
35
|
};
|
|
36
36
|
align();
|
|
37
37
|
if (entry.type === '0') {
|
package/dist/clang/wasm.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Writable } from
|
|
2
|
-
export declare const readBuffer: (name: string, progress?: Writable<number>) => Promise<Uint8Array
|
|
1
|
+
import type { Writable } from 'svelte/store';
|
|
2
|
+
export declare const readBuffer: (name: string, progress?: Writable<number>) => Promise<Uint8Array<ArrayBufferLike>>;
|
|
3
3
|
export declare function compile(filename: string, progress?: Writable<number>): Promise<any>;
|
|
4
4
|
export declare function getInstance(module: WebAssembly.Module, imports: WebAssembly.Imports): Promise<WebAssembly.Instance>;
|
package/dist/clang/wasm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as zip from
|
|
1
|
+
import * as zip from '@zip.js/zip.js';
|
|
2
2
|
const store = {};
|
|
3
3
|
export const readBuffer = async (name, progress) => {
|
|
4
4
|
const response = await fetch(name);
|
|
@@ -34,7 +34,7 @@ export async function compile(filename, progress) {
|
|
|
34
34
|
// application/wasm mimetype.
|
|
35
35
|
if (store[filename])
|
|
36
36
|
return store[filename];
|
|
37
|
-
return store[filename] = WebAssembly.compile(await readBuffer(filename, progress));
|
|
37
|
+
return (store[filename] = WebAssembly.compile(await readBuffer(filename, progress)));
|
|
38
38
|
}
|
|
39
39
|
export function getInstance(module, imports) {
|
|
40
40
|
return WebAssembly.instantiate(module, imports);
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/playground/clang.js
CHANGED
|
@@ -38,8 +38,7 @@ class Clang {
|
|
|
38
38
|
const data = enc.encode(strInfo);
|
|
39
39
|
buffer.set(new Int32Array(data.buffer.slice(data.byteOffset), 0));
|
|
40
40
|
}
|
|
41
|
-
eof() {
|
|
42
|
-
}
|
|
41
|
+
eof() { }
|
|
43
42
|
run(code, prepare, log = this.log, prog) {
|
|
44
43
|
this.exit = false;
|
|
45
44
|
return new Promise(async (resolve, reject) => {
|
|
@@ -50,7 +49,7 @@ class Clang {
|
|
|
50
49
|
if (!this.worker)
|
|
51
50
|
return reject('Worker not loaded');
|
|
52
51
|
if (_uid !== this.uid)
|
|
53
|
-
return this.worker.onmessage = null;
|
|
52
|
+
return (this.worker.onmessage = null);
|
|
54
53
|
const { id, output, results, log, error, buffer, progress } = event.data;
|
|
55
54
|
if (buffer && this.internalBuffer.length)
|
|
56
55
|
this._write(this.internalBuffer.splice(0, 1)[0]);
|
|
@@ -79,7 +78,7 @@ class Clang {
|
|
|
79
78
|
buffer: this.buffer,
|
|
80
79
|
interrupt: this.interruptBuffer,
|
|
81
80
|
context: {},
|
|
82
|
-
log
|
|
81
|
+
log
|
|
83
82
|
});
|
|
84
83
|
});
|
|
85
84
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Clang from './clang';
|
|
2
|
-
import
|
|
2
|
+
import Python from './python';
|
|
3
|
+
import type { Sandbox } from './sandbox';
|
|
3
4
|
export declare const supportedLanguages: string[];
|
|
4
|
-
export default function load(language: string): Promise<Sandbox | Clang |
|
|
5
|
+
export default function load(language: string): Promise<Sandbox | Clang | Python>;
|
package/dist/playground/index.js
CHANGED
|
@@ -35,14 +35,13 @@ class Python {
|
|
|
35
35
|
const data = enc.encode(strInfo);
|
|
36
36
|
buffer.set(new Int32Array(data.buffer.slice(data.byteOffset), 0));
|
|
37
37
|
}
|
|
38
|
-
eof() {
|
|
39
|
-
}
|
|
38
|
+
eof() { }
|
|
40
39
|
run(code, prepare) {
|
|
41
40
|
return new Promise(async (resolve, reject) => {
|
|
42
41
|
const interrupt = new Uint8Array(this.interruptBuffer), _uid = ++this.uid;
|
|
43
42
|
const handler = (event) => {
|
|
44
43
|
if (_uid !== this.uid)
|
|
45
|
-
return this.worker.onmessage = null;
|
|
44
|
+
return (this.worker.onmessage = null);
|
|
46
45
|
const { id, output, results, log, error, buffer } = event.data;
|
|
47
46
|
if (buffer && this.internalBuffer.length)
|
|
48
47
|
this._write(this.internalBuffer.splice(0, 1)[0]);
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
interface
|
|
1
|
+
export interface Sandbox {
|
|
2
2
|
constructor: any;
|
|
3
3
|
eof: () => void;
|
|
4
4
|
load: (path: string, code?: string, log?: boolean) => Promise<void>;
|
|
5
5
|
run: (code: string, prepare: boolean, log?: boolean) => Promise<string>;
|
|
6
6
|
terminate: () => void;
|
|
7
7
|
clear: () => Promise<void>;
|
|
8
|
+
kill?: () => void;
|
|
9
|
+
write?: (data: string) => void;
|
|
10
|
+
output?: (data: string) => void;
|
|
11
|
+
elapse?: number;
|
|
8
12
|
}
|
|
9
|
-
export default sandbox;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
|
@@ -1,158 +1,221 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Sandbox } from '../playground/sandbox';
|
|
3
|
+
import { Theme, registerAllPlugins } from './';
|
|
4
|
+
import load from '../playground';
|
|
5
|
+
import { onMount } from 'svelte';
|
|
6
|
+
import '@xterm/xterm/css/xterm.css';
|
|
7
|
+
import type { Terminal } from '@xterm/xterm';
|
|
8
|
+
|
|
9
|
+
type TerminalControl = typeof terminalControl;
|
|
10
|
+
interface Props {
|
|
11
|
+
dark?: boolean;
|
|
12
|
+
path?: string;
|
|
13
|
+
font?: string;
|
|
14
|
+
|
|
15
|
+
onload?: () => void;
|
|
16
|
+
onfinish?: () => void;
|
|
17
|
+
onkey?: (e: KeyboardEvent) => void;
|
|
18
|
+
terminal?: TerminalControl;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
dark = false,
|
|
23
|
+
path = '',
|
|
24
|
+
font = "'D2 coding', monospace",
|
|
25
|
+
onload,
|
|
26
|
+
onfinish,
|
|
27
|
+
onkey,
|
|
28
|
+
terminal = $bindable()
|
|
29
|
+
}: Props = $props();
|
|
30
|
+
|
|
31
|
+
let ref = $state<HTMLElement>(),
|
|
32
|
+
clientWidth = $state(0),
|
|
33
|
+
clientHeight = $state(0),
|
|
34
|
+
term = $state<Terminal>(),
|
|
35
|
+
finish = true,
|
|
36
|
+
input = '',
|
|
37
|
+
sandbox: Sandbox,
|
|
38
|
+
first = true,
|
|
39
|
+
tc = 0,
|
|
40
|
+
plugin = $state(),
|
|
41
|
+
ll: string | null = null;
|
|
42
|
+
|
|
43
|
+
function wait() {
|
|
44
|
+
return new Promise<void>((r) => {
|
|
45
|
+
const i = setInterval(() => {
|
|
46
|
+
if (term) {
|
|
47
|
+
clearInterval(i);
|
|
48
|
+
r();
|
|
49
|
+
}
|
|
50
|
+
}, 100);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function initSandbox(language: string) {
|
|
55
|
+
let _tc = ++tc;
|
|
56
|
+
await wait();
|
|
57
|
+
if (sandbox) await sandbox.clear();
|
|
58
|
+
input = '';
|
|
59
|
+
finish = false;
|
|
60
|
+
if (ll !== language) {
|
|
61
|
+
sandbox = await load(language);
|
|
62
|
+
await sandbox.clear();
|
|
63
|
+
ll = language;
|
|
64
|
+
}
|
|
65
|
+
sandbox.output = (output: string) =>
|
|
66
|
+
_tc === tc && term && term.write(output.replaceAll('\n', '\r\n'));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function runSandbox(pr: Promise<boolean>) {
|
|
70
|
+
return pr
|
|
71
|
+
.then((x) => {
|
|
72
|
+
term?.write(`\r\nProcess finished after ${sandbox.elapse}ms\u001B[?25l`);
|
|
73
|
+
return x;
|
|
74
|
+
})
|
|
75
|
+
.catch((msg) => {
|
|
76
|
+
term?.write(`\r\n\x1B[1;3;31m${msg}\u001B[?25l`);
|
|
77
|
+
return false;
|
|
78
|
+
})
|
|
79
|
+
.finally((ret) => {
|
|
80
|
+
onfinish?.();
|
|
81
|
+
finish = true;
|
|
82
|
+
if (term) term.options.cursorBlink = false;
|
|
83
|
+
return ret;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function initTerm(blink = true) {
|
|
88
|
+
await wait();
|
|
89
|
+
if (!term) return;
|
|
90
|
+
term.options.cursorBlink = blink;
|
|
91
|
+
term.focus();
|
|
92
|
+
|
|
93
|
+
if (!first) term?.write(`\r\n\x1b[0m`);
|
|
94
|
+
first = false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const terminalControl = {
|
|
98
|
+
async clear() {
|
|
99
|
+
await wait();
|
|
100
|
+
term?.reset();
|
|
101
|
+
term?.write(`\u001B[?25l\x1b[0m\x1b[?25h`);
|
|
102
|
+
if (term) term.options.cursorBlink = false;
|
|
103
|
+
first = true;
|
|
104
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
105
|
+
},
|
|
106
|
+
async prepare(language: string, code: string, log = true, prog) {
|
|
107
|
+
await Promise.all([
|
|
108
|
+
initSandbox(language).then(() => sandbox.load(path, code, log)),
|
|
109
|
+
initTerm(false)
|
|
110
|
+
]);
|
|
111
|
+
return await runSandbox(sandbox.run(code, true, log, prog));
|
|
112
|
+
},
|
|
113
|
+
async run(language: string, code: string, log = true, prog) {
|
|
114
|
+
await Promise.all([
|
|
115
|
+
initSandbox(language).then(() => sandbox.load(path, code, log)),
|
|
116
|
+
initTerm()
|
|
117
|
+
]);
|
|
118
|
+
return await runSandbox(sandbox.run(code, false, log, prog));
|
|
119
|
+
},
|
|
120
|
+
async destroy() {
|
|
121
|
+
await wait();
|
|
122
|
+
term?.dispose();
|
|
123
|
+
if (sandbox) await sandbox.clear();
|
|
124
|
+
},
|
|
125
|
+
async write(input: string) {
|
|
126
|
+
await wait();
|
|
127
|
+
term?.write(input + '\r\n');
|
|
128
|
+
sandbox.write?.(input.replaceAll('\r', '\n') + '\n');
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
$effect(() => {
|
|
133
|
+
if (term) {
|
|
134
|
+
if (dark) term.options.theme = Theme.Tango_Dark;
|
|
135
|
+
else term.options.theme = Theme.Tango_Light;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
$effect(() => {
|
|
140
|
+
let _ = clientWidth + clientHeight;
|
|
141
|
+
(plugin as any)?.fit?.fit?.();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
$effect(() => {
|
|
145
|
+
terminal = terminalControl;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
onMount(() => {
|
|
149
|
+
import('@xterm/xterm').then(async ({ Terminal }) => {
|
|
150
|
+
if (!ref) return;
|
|
151
|
+
term = new Terminal({
|
|
152
|
+
theme: dark ? Theme.Tango_Dark : Theme.Tango_Light,
|
|
153
|
+
cursorBlink: false,
|
|
154
|
+
allowTransparency: true,
|
|
155
|
+
fontFamily: font,
|
|
156
|
+
allowProposedApi: true
|
|
157
|
+
});
|
|
158
|
+
term.open(ref);
|
|
159
|
+
term.onKey((e: { key: string; domEvent: KeyboardEvent }) => {
|
|
160
|
+
if (finish || !term) return;
|
|
161
|
+
const ev = e.domEvent;
|
|
162
|
+
const printable = !ev.altKey && !ev.ctrlKey && !ev.metaKey;
|
|
163
|
+
onkey?.(ev);
|
|
164
|
+
if (ev.key === 'Enter') {
|
|
165
|
+
term.write('\r\n');
|
|
166
|
+
sandbox.write?.(input + '\n');
|
|
167
|
+
input = '';
|
|
168
|
+
} else if (ev.key === 'Backspace') {
|
|
169
|
+
if (term.buffer.active.cursorX > 0) {
|
|
170
|
+
term.write('\b \b');
|
|
171
|
+
if (input.length > 0) input = input.substring(0, input.length - 1);
|
|
172
|
+
}
|
|
173
|
+
} else if (printable) {
|
|
174
|
+
if (
|
|
175
|
+
(e.key >= String.fromCharCode(0x20) &&
|
|
176
|
+
e.key <= String.fromCharCode(0x7e)) ||
|
|
177
|
+
e.key >= '\u00a0'
|
|
178
|
+
) {
|
|
179
|
+
input += e.key;
|
|
180
|
+
term.write(e.key);
|
|
181
|
+
}
|
|
182
|
+
} else if ((ev.ctrlKey || ev.metaKey) && ev.key === 'c') {
|
|
183
|
+
sandbox.kill?.();
|
|
184
|
+
} else if ((ev.ctrlKey || ev.metaKey) && ev.key === 'd') {
|
|
185
|
+
sandbox.kill?.();
|
|
186
|
+
} else if ((ev.ctrlKey || ev.metaKey) && ev.key === 'v') {
|
|
187
|
+
navigator.clipboard.readText().then((text) => {
|
|
188
|
+
term?.write(text);
|
|
189
|
+
sandbox.write?.(text);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
plugin = await registerAllPlugins(term);
|
|
194
|
+
|
|
195
|
+
onload?.();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return async () => {
|
|
199
|
+
term?.dispose();
|
|
200
|
+
if (sandbox) await sandbox.clear();
|
|
201
|
+
};
|
|
202
|
+
});
|
|
139
203
|
</script>
|
|
140
204
|
|
|
141
205
|
<main>
|
|
142
|
-
|
|
206
|
+
<div bind:this={ref} bind:clientWidth bind:clientHeight></div>
|
|
143
207
|
</main>
|
|
144
208
|
|
|
145
|
-
|
|
146
209
|
<style>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
</style>
|
|
210
|
+
main {
|
|
211
|
+
padding: 10px;
|
|
212
|
+
width: calc(100% - 20px);
|
|
213
|
+
height: calc(100% - 20px);
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
div {
|
|
218
|
+
width: 100%;
|
|
219
|
+
height: 100%;
|
|
220
|
+
}
|
|
221
|
+
</style>
|
|
@@ -1,39 +1,19 @@
|
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
|
2
1
|
import '@xterm/xterm/css/xterm.css';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
destroy(): Promise<void>;
|
|
13
|
-
write(input: string): Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
events: {
|
|
17
|
-
finish: CustomEvent<any>;
|
|
18
|
-
key: CustomEvent<any>;
|
|
19
|
-
load: CustomEvent<any>;
|
|
20
|
-
} & {
|
|
21
|
-
[evt: string]: CustomEvent<any>;
|
|
22
|
-
};
|
|
23
|
-
slots: {};
|
|
24
|
-
exports?: {} | undefined;
|
|
25
|
-
bindings?: string | undefined;
|
|
26
|
-
};
|
|
27
|
-
export type TerminalProps = typeof __propDef.props;
|
|
28
|
-
export type TerminalEvents = typeof __propDef.events;
|
|
29
|
-
export type TerminalSlots = typeof __propDef.slots;
|
|
30
|
-
export default class Terminal extends SvelteComponent<TerminalProps, TerminalEvents, TerminalSlots> {
|
|
31
|
-
get terminal(): {
|
|
2
|
+
import type { Terminal } from '@xterm/xterm';
|
|
3
|
+
declare const Terminal: import("svelte").Component<{
|
|
4
|
+
dark?: boolean;
|
|
5
|
+
path?: string;
|
|
6
|
+
font?: string;
|
|
7
|
+
onload?: () => void;
|
|
8
|
+
onfinish?: () => void;
|
|
9
|
+
onkey?: (e: KeyboardEvent) => void;
|
|
10
|
+
terminal?: {
|
|
32
11
|
clear(): Promise<void>;
|
|
33
|
-
prepare(language:
|
|
34
|
-
run(language:
|
|
12
|
+
prepare(language: string, code: string, log: boolean | undefined, prog: any): Promise<boolean>;
|
|
13
|
+
run(language: string, code: string, log: boolean | undefined, prog: any): Promise<boolean>;
|
|
35
14
|
destroy(): Promise<void>;
|
|
36
15
|
write(input: string): Promise<void>;
|
|
37
16
|
};
|
|
38
|
-
}
|
|
39
|
-
|
|
17
|
+
}, {}, "terminal">;
|
|
18
|
+
type Terminal = ReturnType<typeof Terminal>;
|
|
19
|
+
export default Terminal;
|
package/dist/terminal/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Theme from
|
|
2
|
-
import registerAllPlugins from
|
|
3
|
-
import Terminal from
|
|
1
|
+
import Theme from './theme';
|
|
2
|
+
import registerAllPlugins from './plugin';
|
|
3
|
+
import Terminal from './Terminal.svelte';
|
|
4
4
|
export { Theme, registerAllPlugins };
|
|
5
5
|
export default Terminal;
|
package/dist/terminal/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Theme from
|
|
2
|
-
import registerAllPlugins from
|
|
3
|
-
import Terminal from
|
|
1
|
+
import Theme from './theme';
|
|
2
|
+
import registerAllPlugins from './plugin';
|
|
3
|
+
import Terminal from './Terminal.svelte';
|
|
4
4
|
export { Theme, registerAllPlugins };
|
|
5
5
|
export default Terminal;
|
package/package.json
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
2
|
+
"name": "wasm-idle",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "A simple web app to run C++/Python code in the browser",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite dev",
|
|
9
|
+
"build": "vite build && npm run package",
|
|
10
|
+
"preview": "vite preview",
|
|
11
|
+
"package": "svelte-kit sync && svelte-package && publint",
|
|
12
|
+
"prepublishOnly": "npm run package",
|
|
13
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
14
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
15
|
+
"lint": "prettier --check . && eslint .",
|
|
16
|
+
"format": "prettier --write ."
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@eslint/js": "^9.19.0",
|
|
20
|
+
"@sveltejs/adapter-auto": "^4.0.0",
|
|
21
|
+
"@sveltejs/adapter-static": "^3.0.8",
|
|
22
|
+
"@sveltejs/kit": "^2.17.1",
|
|
23
|
+
"@sveltejs/package": "^2.3.10",
|
|
24
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^8.23.0",
|
|
26
|
+
"@typescript-eslint/parser": "^8.23.0",
|
|
27
|
+
"eslint": "^9.19.0",
|
|
28
|
+
"eslint-config-prettier": "^10.0.1",
|
|
29
|
+
"eslint-plugin-svelte": "^2.46.1",
|
|
30
|
+
"eslint-plugin-svelte3": "^4.0.0",
|
|
31
|
+
"gh-pages": "^6.3.0",
|
|
32
|
+
"globals": "^15.14.0",
|
|
33
|
+
"monaco-editor": "^0.52.2",
|
|
34
|
+
"prettier": "^3.4.2",
|
|
35
|
+
"prettier-plugin-svelte": "^3.3.3",
|
|
36
|
+
"svelte": "^5.19.7",
|
|
37
|
+
"svelte-check": "^4.1.4",
|
|
38
|
+
"tslib": "^2.8.1",
|
|
39
|
+
"typescript": "^5.7.3",
|
|
40
|
+
"typescript-eslint": "^8.23.0",
|
|
41
|
+
"vite": "^6.0.11"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@xterm/addon-canvas": "^0.7.0",
|
|
45
|
+
"@xterm/addon-fit": "^0.10.0",
|
|
46
|
+
"@xterm/addon-ligatures": "^0.9.0",
|
|
47
|
+
"@xterm/addon-search": "^0.15.0",
|
|
48
|
+
"@xterm/addon-serialize": "^0.13.0",
|
|
49
|
+
"@xterm/addon-unicode11": "^0.8.0",
|
|
50
|
+
"@xterm/addon-web-links": "^0.11.0",
|
|
51
|
+
"@xterm/addon-webgl": "^0.18.0",
|
|
52
|
+
"@xterm/xterm": "^5.5.0",
|
|
53
|
+
"@zip.js/zip.js": "^2.7.57",
|
|
54
|
+
"publint": "^0.3.3",
|
|
55
|
+
"pyodide": "0.26.2"
|
|
56
|
+
},
|
|
57
|
+
"files": [
|
|
58
|
+
"dist",
|
|
59
|
+
"!dist/**/*.test.*",
|
|
60
|
+
"!dist/**/*.spec.*"
|
|
61
|
+
],
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"svelte": "^4.2.18"
|
|
64
|
+
},
|
|
65
|
+
"exports": {
|
|
66
|
+
".": {
|
|
67
|
+
"types": "./dist/index.d.ts",
|
|
68
|
+
"svelte": "./dist/index.js"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"svelte": "./dist/index.js",
|
|
72
|
+
"types": "./dist/index.d.ts"
|
|
73
73
|
}
|