wasm-idle 0.0.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 +9 -0
- package/dist/clang/app.d.ts +24 -0
- package/dist/clang/app.js +119 -0
- package/dist/clang/apply.d.ts +2 -0
- package/dist/clang/apply.js +11 -0
- package/dist/clang/color.d.ts +3 -0
- package/dist/clang/color.js +3 -0
- package/dist/clang/encode.d.ts +3 -0
- package/dist/clang/encode.js +13 -0
- package/dist/clang/error.d.ts +14 -0
- package/dist/clang/error.js +27 -0
- package/dist/clang/index.d.ts +30 -0
- package/dist/clang/index.js +107 -0
- package/dist/clang/memory/index.d.ts +4 -0
- package/dist/clang/memory/index.js +4 -0
- package/dist/clang/memory/memFs.d.ts +31 -0
- package/dist/clang/memory/memFs.js +121 -0
- package/dist/clang/memory/memory.d.ts +17 -0
- package/dist/clang/memory/memory.js +56 -0
- package/dist/clang/memory/tar.d.ts +2 -0
- package/dist/clang/memory/tar.js +59 -0
- package/dist/clang/url.d.ts +4 -0
- package/dist/clang/url.js +4 -0
- package/dist/clang/wasm.d.ts +3 -0
- package/dist/clang/wasm.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/playground/clang.d.ts +20 -0
- package/dist/playground/clang.js +89 -0
- package/dist/playground/index.d.ts +3 -0
- package/dist/playground/index.js +33 -0
- package/dist/playground/python.d.ts +20 -0
- package/dist/playground/python.js +88 -0
- package/dist/playground/sandbox.d.ts +9 -0
- package/dist/playground/sandbox.js +1 -0
- package/dist/playground/worker/clang.d.ts +1 -0
- package/dist/playground/worker/clang.js +46 -0
- package/dist/playground/worker/python.d.ts +1 -0
- package/dist/playground/worker/python.js +77 -0
- package/dist/terminal/Terminal.svelte +130 -0
- package/dist/terminal/Terminal.svelte.d.ts +29 -0
- package/dist/terminal/index.d.ts +5 -0
- package/dist/terminal/index.js +5 -0
- package/dist/terminal/plugin/index.d.ts +9 -0
- package/dist/terminal/plugin/index.js +19 -0
- package/dist/terminal/theme.d.ts +49 -0
- package/dist/terminal/theme.js +49 -0
- package/package.json +60 -0
- package/static/image.jpeg +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readStr, readOct } from "../encode";
|
|
2
|
+
import { assert } from "../error";
|
|
3
|
+
function* readEntry(buffer) {
|
|
4
|
+
const u8 = new Uint8Array(buffer);
|
|
5
|
+
let offset = 0;
|
|
6
|
+
const str = (len) => {
|
|
7
|
+
offset += len;
|
|
8
|
+
return readStr(u8, offset - len, len);
|
|
9
|
+
}, oct = (len) => {
|
|
10
|
+
offset += len;
|
|
11
|
+
return readOct(u8, offset - len, len);
|
|
12
|
+
}, align = () => offset = (offset + 511) & ~511;
|
|
13
|
+
while (offset + 512 <= u8.length) {
|
|
14
|
+
const entryInit = {
|
|
15
|
+
filename: str(100),
|
|
16
|
+
mode: oct(8),
|
|
17
|
+
owner: oct(8),
|
|
18
|
+
group: oct(8),
|
|
19
|
+
size: oct(12),
|
|
20
|
+
mtime: oct(12),
|
|
21
|
+
checksum: oct(8),
|
|
22
|
+
type: str(1),
|
|
23
|
+
linkname: str(100),
|
|
24
|
+
ustar: str(8),
|
|
25
|
+
};
|
|
26
|
+
if (!entryInit.ustar)
|
|
27
|
+
return;
|
|
28
|
+
const entry = {
|
|
29
|
+
...entryInit,
|
|
30
|
+
ownerName: str(32),
|
|
31
|
+
groupName: str(32),
|
|
32
|
+
devMajor: str(8),
|
|
33
|
+
devMinor: str(8),
|
|
34
|
+
filenamePrefix: str(155),
|
|
35
|
+
};
|
|
36
|
+
align();
|
|
37
|
+
if (entry.type === '0') {
|
|
38
|
+
entry.contents = u8.subarray(offset, offset + entry.size);
|
|
39
|
+
offset += entry.size;
|
|
40
|
+
align();
|
|
41
|
+
}
|
|
42
|
+
yield entry;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export default function untar(buffer, memfs) {
|
|
46
|
+
for (const entry of readEntry(buffer)) {
|
|
47
|
+
switch (entry.type) {
|
|
48
|
+
case '0': // Regular file.
|
|
49
|
+
memfs.addFile(entry.filename, entry.contents);
|
|
50
|
+
break;
|
|
51
|
+
case '5': // Folder.
|
|
52
|
+
memfs.addDirectory(entry.filename);
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
console.log('type', entry.type);
|
|
56
|
+
assert(false);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function compile(filename: string): Promise<WebAssembly.Module>;
|
|
2
|
+
export declare function getInstance(module: WebAssembly.Module, imports: WebAssembly.Imports): Promise<WebAssembly.Instance>;
|
|
3
|
+
export declare const readBuffer: (name: string) => Promise<ArrayBuffer>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const url = (url) => url;
|
|
2
|
+
export async function compile(filename) {
|
|
3
|
+
// TODO: make compileStreaming work. It needs the server to use the
|
|
4
|
+
// application/wasm mimetype.
|
|
5
|
+
if (false && WebAssembly.compileStreaming) {
|
|
6
|
+
return WebAssembly.compileStreaming(fetch(url(filename)));
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
const response = await fetch(url(filename));
|
|
10
|
+
return WebAssembly.compile(await response.arrayBuffer());
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function getInstance(module, imports) {
|
|
14
|
+
return WebAssembly.instantiate(module, imports);
|
|
15
|
+
}
|
|
16
|
+
export const readBuffer = (name) => fetch(url(name)).then(r => r.arrayBuffer());
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type Sandbox from './sandbox';
|
|
2
|
+
declare class Clang implements Sandbox {
|
|
3
|
+
ts: number;
|
|
4
|
+
output: null;
|
|
5
|
+
worker: Worker;
|
|
6
|
+
buffer: SharedArrayBuffer;
|
|
7
|
+
interruptBuffer: SharedArrayBuffer;
|
|
8
|
+
internalBuffer: string[];
|
|
9
|
+
begin: number;
|
|
10
|
+
elapse: number;
|
|
11
|
+
uid: number;
|
|
12
|
+
load(path: string, code?: string, log?: boolean): Promise<void>;
|
|
13
|
+
write(input: string): void;
|
|
14
|
+
_write(input: string): void;
|
|
15
|
+
eof(): void;
|
|
16
|
+
run(code: string): Promise<string>;
|
|
17
|
+
terminate(): void;
|
|
18
|
+
clear(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export default Clang;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
class Clang {
|
|
2
|
+
ts = Date.now();
|
|
3
|
+
output = null;
|
|
4
|
+
worker = null;
|
|
5
|
+
buffer = new SharedArrayBuffer(1024);
|
|
6
|
+
interruptBuffer = new SharedArrayBuffer(1);
|
|
7
|
+
internalBuffer = [];
|
|
8
|
+
begin = 0;
|
|
9
|
+
elapse = 0;
|
|
10
|
+
uid = 0;
|
|
11
|
+
load(path, code = '', log = true) {
|
|
12
|
+
return new Promise(async (resolve) => {
|
|
13
|
+
this.internalBuffer = [];
|
|
14
|
+
if (!this.worker) {
|
|
15
|
+
this.worker = new (await import('./worker/clang?worker')).default();
|
|
16
|
+
this.worker.onmessage = (event) => {
|
|
17
|
+
resolve();
|
|
18
|
+
};
|
|
19
|
+
this.worker.postMessage({ load: true, path, log, code });
|
|
20
|
+
}
|
|
21
|
+
else
|
|
22
|
+
resolve();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
write(input) {
|
|
26
|
+
this.internalBuffer.push(input);
|
|
27
|
+
}
|
|
28
|
+
_write(input) {
|
|
29
|
+
let strInfo = input, padding = 4 - (strInfo.length % 4);
|
|
30
|
+
while (strInfo.length % 4 !== 3)
|
|
31
|
+
strInfo += ' ';
|
|
32
|
+
strInfo += padding;
|
|
33
|
+
const buffer = new Int32Array(this.buffer);
|
|
34
|
+
const enc = new TextEncoder();
|
|
35
|
+
const data = enc.encode(strInfo);
|
|
36
|
+
buffer.set(new Int32Array(data.buffer.slice(data.byteOffset), 0));
|
|
37
|
+
}
|
|
38
|
+
eof() {
|
|
39
|
+
}
|
|
40
|
+
run(code) {
|
|
41
|
+
return new Promise(async (resolve, reject) => {
|
|
42
|
+
const interrupt = new Uint8Array(this.interruptBuffer), _uid = ++this.uid;
|
|
43
|
+
const handler = (event) => {
|
|
44
|
+
if (_uid !== this.uid) {
|
|
45
|
+
this.worker.onmessage = null;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const { id, output, results, log, error, buffer } = event.data;
|
|
49
|
+
if (buffer && this.internalBuffer.length)
|
|
50
|
+
this._write(this.internalBuffer.splice(0, 1)[0]);
|
|
51
|
+
if (output)
|
|
52
|
+
this.output(output);
|
|
53
|
+
if (results) {
|
|
54
|
+
this.elapse = Date.now() - this.begin;
|
|
55
|
+
resolve(results);
|
|
56
|
+
}
|
|
57
|
+
if (log)
|
|
58
|
+
console.log(log);
|
|
59
|
+
if (error) {
|
|
60
|
+
this.elapse = Date.now() - this.begin;
|
|
61
|
+
reject(error);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
interrupt[0] = 0;
|
|
65
|
+
this.worker.onmessage = handler;
|
|
66
|
+
this.begin = Date.now();
|
|
67
|
+
this.worker.postMessage({
|
|
68
|
+
code,
|
|
69
|
+
buffer: this.buffer,
|
|
70
|
+
interrupt: this.interruptBuffer,
|
|
71
|
+
context: {}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
terminate() {
|
|
76
|
+
const interrupt = new Uint8Array(this.interruptBuffer);
|
|
77
|
+
interrupt[0] = 2;
|
|
78
|
+
}
|
|
79
|
+
async clear() {
|
|
80
|
+
this.terminate();
|
|
81
|
+
this.internalBuffer = [];
|
|
82
|
+
if (this.worker)
|
|
83
|
+
this.worker.onmessage = null;
|
|
84
|
+
const buffer = new Int32Array(this.buffer);
|
|
85
|
+
buffer.fill(0);
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export default Clang;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Clang from './clang';
|
|
2
|
+
import Python from './python';
|
|
3
|
+
const sandboxCache = {};
|
|
4
|
+
export const supportedLanguages = ['PYTHON3', 'PYPY3', 'C', 'CPP'];
|
|
5
|
+
export async function load(language) {
|
|
6
|
+
if (sandboxCache[language])
|
|
7
|
+
return sandboxCache[language];
|
|
8
|
+
let sandbox;
|
|
9
|
+
switch (language) {
|
|
10
|
+
case 'PYTHON3':
|
|
11
|
+
case 'PYTHON':
|
|
12
|
+
case 'PYPY3':
|
|
13
|
+
sandbox = new Python();
|
|
14
|
+
break;
|
|
15
|
+
case 'C':
|
|
16
|
+
case 'CPP':
|
|
17
|
+
sandbox = new Clang();
|
|
18
|
+
}
|
|
19
|
+
sandboxCache[language] = sandbox;
|
|
20
|
+
if (sandbox) {
|
|
21
|
+
if (language === 'PYTHON3')
|
|
22
|
+
sandboxCache['PYPY3'] = sandboxCache['PYTHON'] = sandbox;
|
|
23
|
+
if (language === 'PYTHON')
|
|
24
|
+
sandboxCache['PYTHON3'] = sandboxCache['PYPY3'] = sandbox;
|
|
25
|
+
if (language === 'PYPY3')
|
|
26
|
+
sandboxCache['PYTHON3'] = sandboxCache['PYTHON'] = sandbox;
|
|
27
|
+
if (language === 'C')
|
|
28
|
+
sandboxCache['C'] = sandbox;
|
|
29
|
+
if (language === 'CPP')
|
|
30
|
+
sandboxCache['CPP'] = sandbox;
|
|
31
|
+
}
|
|
32
|
+
return sandbox;
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type Sandbox from './sandbox';
|
|
2
|
+
declare class Python implements Sandbox {
|
|
3
|
+
ts: number;
|
|
4
|
+
output: null;
|
|
5
|
+
worker: Worker;
|
|
6
|
+
buffer: SharedArrayBuffer;
|
|
7
|
+
interruptBuffer: SharedArrayBuffer;
|
|
8
|
+
internalBuffer: string[];
|
|
9
|
+
begin: number;
|
|
10
|
+
elapse: number;
|
|
11
|
+
uid: number;
|
|
12
|
+
load(path: string, code?: string, log?: boolean): Promise<void>;
|
|
13
|
+
write(input: string): void;
|
|
14
|
+
_write(input: string): void;
|
|
15
|
+
eof(): void;
|
|
16
|
+
run(code: string): Promise<string>;
|
|
17
|
+
terminate(): void;
|
|
18
|
+
clear(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export default Python;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
class Python {
|
|
2
|
+
ts = Date.now();
|
|
3
|
+
output = null;
|
|
4
|
+
worker = null;
|
|
5
|
+
buffer = new SharedArrayBuffer(1024);
|
|
6
|
+
interruptBuffer = new SharedArrayBuffer(1);
|
|
7
|
+
internalBuffer = [];
|
|
8
|
+
begin = 0;
|
|
9
|
+
elapse = 0;
|
|
10
|
+
uid = 0;
|
|
11
|
+
load(path, code = '', log = true) {
|
|
12
|
+
return new Promise(async (resolve) => {
|
|
13
|
+
this.internalBuffer = [];
|
|
14
|
+
if (!this.worker) {
|
|
15
|
+
this.worker = new (await import('./worker/python?worker')).default();
|
|
16
|
+
this.worker.onmessage = (event) => {
|
|
17
|
+
resolve();
|
|
18
|
+
};
|
|
19
|
+
this.worker.postMessage({ load: true, path, log, code });
|
|
20
|
+
}
|
|
21
|
+
else
|
|
22
|
+
resolve();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
write(input) {
|
|
26
|
+
this.internalBuffer.push(input);
|
|
27
|
+
}
|
|
28
|
+
_write(input) {
|
|
29
|
+
let strInfo = input, padding = 4 - (strInfo.length % 4);
|
|
30
|
+
while (strInfo.length % 4 !== 3)
|
|
31
|
+
strInfo += ' ';
|
|
32
|
+
strInfo += padding;
|
|
33
|
+
const buffer = new Int32Array(this.buffer);
|
|
34
|
+
const enc = new TextEncoder();
|
|
35
|
+
const data = enc.encode(strInfo);
|
|
36
|
+
buffer.set(new Int32Array(data.buffer.slice(data.byteOffset), 0));
|
|
37
|
+
}
|
|
38
|
+
eof() {
|
|
39
|
+
}
|
|
40
|
+
run(code) {
|
|
41
|
+
return new Promise(async (resolve, reject) => {
|
|
42
|
+
const interrupt = new Uint8Array(this.interruptBuffer), _uid = ++this.uid;
|
|
43
|
+
const handler = (event) => {
|
|
44
|
+
if (_uid !== this.uid) {
|
|
45
|
+
this.worker.onmessage = null;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const { id, output, results, log, error, buffer } = event.data;
|
|
49
|
+
if (buffer && this.internalBuffer.length)
|
|
50
|
+
this._write(this.internalBuffer.splice(0, 1)[0]);
|
|
51
|
+
if (output)
|
|
52
|
+
this.output(output);
|
|
53
|
+
if (results) {
|
|
54
|
+
this.elapse = Date.now() - this.begin;
|
|
55
|
+
resolve(results);
|
|
56
|
+
}
|
|
57
|
+
if (log)
|
|
58
|
+
console.log(log);
|
|
59
|
+
if (error) {
|
|
60
|
+
this.elapse = Date.now() - this.begin;
|
|
61
|
+
reject(error);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
interrupt[0] = 0;
|
|
65
|
+
this.worker.onmessage = handler;
|
|
66
|
+
this.begin = Date.now();
|
|
67
|
+
this.worker.postMessage({
|
|
68
|
+
code,
|
|
69
|
+
buffer: this.buffer,
|
|
70
|
+
interrupt: this.interruptBuffer,
|
|
71
|
+
context: {}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
terminate() {
|
|
76
|
+
new Uint8Array(this.interruptBuffer)[0] = 2;
|
|
77
|
+
}
|
|
78
|
+
async clear() {
|
|
79
|
+
this.terminate();
|
|
80
|
+
this.internalBuffer = [];
|
|
81
|
+
if (this.worker)
|
|
82
|
+
this.worker.onmessage = null;
|
|
83
|
+
const buffer = new Int32Array(this.buffer);
|
|
84
|
+
buffer.fill(0);
|
|
85
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export default Python;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
let stdinBufferClang, interruptBufferClang, clang;
|
|
2
|
+
async function loadClang(path, log) {
|
|
3
|
+
const { default: Clang } = await import('../../clang');
|
|
4
|
+
clang = new Clang({
|
|
5
|
+
stdout: (output) => postMessage({ output }),
|
|
6
|
+
stdin: () => {
|
|
7
|
+
while (true) {
|
|
8
|
+
postMessage({ buffer: true });
|
|
9
|
+
const res = Atomics.wait(stdinBufferClang, 0, 0, 100);
|
|
10
|
+
if (res === 'not-equal') {
|
|
11
|
+
try {
|
|
12
|
+
const cpy = new Int32Array(stdinBufferClang.byteLength);
|
|
13
|
+
cpy.set(stdinBufferClang);
|
|
14
|
+
stdinBufferClang.fill(0);
|
|
15
|
+
const dec = new TextDecoder();
|
|
16
|
+
const strInfo = dec.decode(cpy).replace(/\x00/g, ''), padding = parseInt(strInfo.slice(-1));
|
|
17
|
+
return strInfo.slice(0, -padding);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
postMessage({ log: { e } });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
log, path,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
self.onmessage = async (event) => {
|
|
29
|
+
const { code, buffer, load, interrupt, log, path } = event.data;
|
|
30
|
+
if (load) {
|
|
31
|
+
await loadClang(path, log);
|
|
32
|
+
postMessage({ load: true });
|
|
33
|
+
}
|
|
34
|
+
else if (code) {
|
|
35
|
+
stdinBufferClang = new Int32Array(buffer);
|
|
36
|
+
interruptBufferClang = new Uint8Array(interrupt);
|
|
37
|
+
try {
|
|
38
|
+
await clang.compileLinkRun(code);
|
|
39
|
+
self.postMessage({ results: true });
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
self.postMessage({ error: error.message });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
let stdinBufferPyodide, interruptBufferPyodide, pyodide;
|
|
2
|
+
async function loadPyodideAndPackages(path) {
|
|
3
|
+
const { loadPyodide } = await import('pyodide');
|
|
4
|
+
pyodide = await loadPyodide({ indexURL: path + '/pyodide' });
|
|
5
|
+
}
|
|
6
|
+
self.onmessage = async (event) => {
|
|
7
|
+
const { code, buffer, load, interrupt, path } = event.data;
|
|
8
|
+
if (load) {
|
|
9
|
+
await loadPyodideAndPackages(path);
|
|
10
|
+
await pyodide.loadPackagesFromImports(code);
|
|
11
|
+
postMessage({ load: true });
|
|
12
|
+
}
|
|
13
|
+
else if (code) {
|
|
14
|
+
const ts = Date.now();
|
|
15
|
+
stdinBufferPyodide = new Int32Array(buffer);
|
|
16
|
+
interruptBufferPyodide = new Uint8Array(interrupt);
|
|
17
|
+
pyodide.setInterruptBuffer(interruptBufferPyodide);
|
|
18
|
+
self['__pyodide__input_' + ts] = (output) => {
|
|
19
|
+
if (output)
|
|
20
|
+
postMessage({ output });
|
|
21
|
+
while (true) {
|
|
22
|
+
postMessage({ buffer: true });
|
|
23
|
+
const res = Atomics.wait(stdinBufferPyodide, 0, 0, 100);
|
|
24
|
+
if (res === 'not-equal') {
|
|
25
|
+
try {
|
|
26
|
+
const cpy = new Int32Array(stdinBufferPyodide.byteLength);
|
|
27
|
+
cpy.set(stdinBufferPyodide);
|
|
28
|
+
stdinBufferPyodide.fill(0);
|
|
29
|
+
const dec = new TextDecoder();
|
|
30
|
+
const strInfo = dec.decode(cpy).replace(/\x00/g, ''), padding = parseInt(strInfo.slice(-1));
|
|
31
|
+
return strInfo.slice(0, -padding);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
postMessage({ log: { e } });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
self['__pyodide__output_' + ts] = (...data) => {
|
|
40
|
+
let sep = ' ', end = '\r\n', output = '', clear = [];
|
|
41
|
+
for (const i of data) {
|
|
42
|
+
if (i.end !== undefined)
|
|
43
|
+
end = i.end.toString();
|
|
44
|
+
else if (i.sep !== undefined)
|
|
45
|
+
sep = i.sep.toString();
|
|
46
|
+
else
|
|
47
|
+
clear.push(i);
|
|
48
|
+
}
|
|
49
|
+
for (let i = 0; i < clear.length; i++) {
|
|
50
|
+
if (typeof clear[i] === 'string' || (!clear[i].end && !clear[i].sep)) {
|
|
51
|
+
output += clear[i].toString();
|
|
52
|
+
if (i < clear.length - 1)
|
|
53
|
+
output += sep;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
output += end;
|
|
57
|
+
postMessage({ output });
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
let results = await pyodide.runPythonAsync(`import asyncio
|
|
61
|
+
from js import __pyodide__input_${ts}, __pyodide__output_${ts}
|
|
62
|
+
|
|
63
|
+
input = __pyodide__input_${ts}
|
|
64
|
+
print = __pyodide__output_${ts}
|
|
65
|
+
|
|
66
|
+
__builtins__.input = __pyodide__input_${ts}
|
|
67
|
+
__builtins__.print = __pyodide__output_${ts}
|
|
68
|
+
|
|
69
|
+
${code}`);
|
|
70
|
+
self.postMessage({ results: true });
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
self.postMessage({ error: error.message });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script>import { onMount } from "svelte";
|
|
2
|
+
import { Theme, registerAllPlugins } from "./";
|
|
3
|
+
import { createEventDispatcher } from "svelte";
|
|
4
|
+
import { load } from "../playground";
|
|
5
|
+
import "xterm/css/xterm.css";
|
|
6
|
+
const dispatch = createEventDispatcher();
|
|
7
|
+
let ref, clientWidth, clientHeight, term, finish = true, input = "", sandbox, first = true;
|
|
8
|
+
export const terminal = {
|
|
9
|
+
clear() {
|
|
10
|
+
term.clear();
|
|
11
|
+
term.write(`\x1B[?25l`);
|
|
12
|
+
term.write("\x1B[0m");
|
|
13
|
+
term.options.cursorBlink = false;
|
|
14
|
+
first = true;
|
|
15
|
+
},
|
|
16
|
+
async run(language, code, log = true) {
|
|
17
|
+
if (sandbox)
|
|
18
|
+
await sandbox.clear();
|
|
19
|
+
input = "";
|
|
20
|
+
finish = false;
|
|
21
|
+
sandbox = await load(language, path);
|
|
22
|
+
await sandbox.clear();
|
|
23
|
+
sandbox.output = (output) => {
|
|
24
|
+
term.write(output.replaceAll("\n", "\r\n"));
|
|
25
|
+
};
|
|
26
|
+
term.options.cursorBlink = true;
|
|
27
|
+
if (!first)
|
|
28
|
+
term.write(`\r
|
|
29
|
+
\x1B[0m`);
|
|
30
|
+
await sandbox.load(path, code, log);
|
|
31
|
+
term.focus();
|
|
32
|
+
first = false;
|
|
33
|
+
sandbox.run(code).then(() => {
|
|
34
|
+
dispatch("finish");
|
|
35
|
+
finish = true;
|
|
36
|
+
term.write(`\r
|
|
37
|
+
Process finished after ${sandbox.elapse}ms\r
|
|
38
|
+
\x1B[?25l`);
|
|
39
|
+
term.options.cursorBlink = false;
|
|
40
|
+
}).catch((msg) => {
|
|
41
|
+
dispatch("finish");
|
|
42
|
+
finish = true;
|
|
43
|
+
term.write(`\r
|
|
44
|
+
\x1B[1;3;31m${msg}`);
|
|
45
|
+
term.options.cursorBlink = false;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
export let dark = false, path = "";
|
|
50
|
+
$:
|
|
51
|
+
if (term) {
|
|
52
|
+
if (dark)
|
|
53
|
+
term.options.theme = Theme.Tango_Dark;
|
|
54
|
+
else
|
|
55
|
+
term.options.theme = Theme.Tango_Light;
|
|
56
|
+
}
|
|
57
|
+
let plugin;
|
|
58
|
+
$:
|
|
59
|
+
if (plugin) {
|
|
60
|
+
void 0, clientHeight;
|
|
61
|
+
try {
|
|
62
|
+
plugin.fit.fit();
|
|
63
|
+
} catch (e) {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
onMount(() => {
|
|
67
|
+
import("xterm").then(async ({ Terminal }) => {
|
|
68
|
+
term = new Terminal({
|
|
69
|
+
theme: dark ? Theme.Tango_Dark : Theme.Tango_Light,
|
|
70
|
+
cursorBlink: false,
|
|
71
|
+
allowTransparency: true,
|
|
72
|
+
fontFamily: "'D2 coding', monospace",
|
|
73
|
+
fontWeight: "bold",
|
|
74
|
+
allowProposedApi: true
|
|
75
|
+
});
|
|
76
|
+
term.open(ref);
|
|
77
|
+
term.onKey((e) => {
|
|
78
|
+
if (finish)
|
|
79
|
+
return;
|
|
80
|
+
const ev = e.domEvent;
|
|
81
|
+
const printable = !ev.altKey && !ev.ctrlKey && !ev.metaKey;
|
|
82
|
+
if (ev.key === "Enter") {
|
|
83
|
+
term.write("\r\n");
|
|
84
|
+
sandbox.write(input + "\n");
|
|
85
|
+
input = "";
|
|
86
|
+
} else if (ev.key === "Backspace") {
|
|
87
|
+
if (term._core.buffer.x > 0) {
|
|
88
|
+
term.write("\b \b");
|
|
89
|
+
if (input.length > 0) {
|
|
90
|
+
input = input.substring(0, input.length - 1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else if (printable) {
|
|
94
|
+
if (e.key >= String.fromCharCode(32) && e.key <= String.fromCharCode(126) || e.key >= "\xA0") {
|
|
95
|
+
input += e.key;
|
|
96
|
+
term.write(e.key);
|
|
97
|
+
}
|
|
98
|
+
} else if (ev.ctrlKey && ev.key === "c") {
|
|
99
|
+
sandbox.kill();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
plugin = await registerAllPlugins(term);
|
|
103
|
+
});
|
|
104
|
+
dispatch("load");
|
|
105
|
+
return async () => {
|
|
106
|
+
term.dispose();
|
|
107
|
+
if (sandbox)
|
|
108
|
+
await sandbox.clear();
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<main>
|
|
114
|
+
<div bind:this={ref} bind:clientWidth bind:clientHeight></div>
|
|
115
|
+
</main>
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
<style>
|
|
119
|
+
main {
|
|
120
|
+
padding: 10px;
|
|
121
|
+
width: calc(100% - 20px);
|
|
122
|
+
height: calc(100% - 20px);
|
|
123
|
+
overflow: hidden;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
div {
|
|
127
|
+
width: 100%;
|
|
128
|
+
height: 100%;
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import 'xterm/css/xterm.css';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
terminal?: {
|
|
6
|
+
clear(): void;
|
|
7
|
+
run(language: any, code: any, log?: boolean): Promise<void>;
|
|
8
|
+
} | undefined;
|
|
9
|
+
dark?: boolean | undefined;
|
|
10
|
+
path?: string | undefined;
|
|
11
|
+
};
|
|
12
|
+
events: {
|
|
13
|
+
finish: CustomEvent<any>;
|
|
14
|
+
load: CustomEvent<any>;
|
|
15
|
+
} & {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {};
|
|
19
|
+
};
|
|
20
|
+
export type TerminalProps = typeof __propDef.props;
|
|
21
|
+
export type TerminalEvents = typeof __propDef.events;
|
|
22
|
+
export type TerminalSlots = typeof __propDef.slots;
|
|
23
|
+
export default class Terminal extends SvelteComponentTyped<TerminalProps, TerminalEvents, TerminalSlots> {
|
|
24
|
+
get terminal(): {
|
|
25
|
+
clear(): void;
|
|
26
|
+
run(language: any, code: any, log?: boolean): Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export {};
|