99 lines
2.5 KiB
JavaScript
99 lines
2.5 KiB
JavaScript
import { tryOnScopeDispose } from "@vueuse/core";
|
|
|
|
//#region src/client/composables/rustRepl.ts
|
|
const wsUrl = "wss://play.rust-lang.org/websocket";
|
|
const payloadType = {
|
|
connected: "websocket/connected",
|
|
request: "output/execute/wsExecuteRequest",
|
|
execute: {
|
|
begin: "output/execute/wsExecuteBegin",
|
|
stderr: "output/execute/wsExecuteStderr",
|
|
stdout: "output/execute/wsExecuteStdout",
|
|
end: "output/execute/wsExecuteEnd"
|
|
}
|
|
};
|
|
let ws = null;
|
|
let isOpen = false;
|
|
let uuid = 0;
|
|
function connect() {
|
|
if (isOpen) return Promise.resolve();
|
|
ws = new WebSocket(wsUrl);
|
|
uuid = 0;
|
|
ws.addEventListener("open", () => {
|
|
isOpen = true;
|
|
send(payloadType.connected, { iAcceptThisIsAnUnsupportedApi: true }, {
|
|
websocket: true,
|
|
sequenceNumber: uuid
|
|
});
|
|
});
|
|
ws.addEventListener("close", () => {
|
|
isOpen = false;
|
|
ws = null;
|
|
});
|
|
tryOnScopeDispose(() => ws?.close());
|
|
return new Promise((resolve) => {
|
|
function connected(e) {
|
|
if (JSON.parse(e.data).type === payloadType.connected) {
|
|
ws?.removeEventListener("message", connected);
|
|
resolve();
|
|
}
|
|
}
|
|
ws?.addEventListener("message", connected);
|
|
});
|
|
}
|
|
function send(type, payload, meta) {
|
|
const msg = {
|
|
type,
|
|
meta,
|
|
payload
|
|
};
|
|
ws?.send(JSON.stringify(msg));
|
|
}
|
|
async function rustExecute(code, { onEnd, onError, onStderr, onStdout, onBegin }) {
|
|
await connect();
|
|
const meta = { sequenceNumber: uuid++ };
|
|
const payload = {
|
|
backtrace: false,
|
|
channel: "stable",
|
|
crateType: "bin",
|
|
edition: "2021",
|
|
mode: "release",
|
|
tests: false,
|
|
code
|
|
};
|
|
send(payloadType.request, payload, meta);
|
|
let stdout = "";
|
|
let stderr = "";
|
|
function onMessage(e) {
|
|
const { type, payload: payload$1, meta: _meta = {} } = JSON.parse(e.data);
|
|
if (_meta.sequenceNumber !== meta.sequenceNumber) return;
|
|
if (type === payloadType.execute.begin) onBegin?.();
|
|
if (type === payloadType.execute.stdout) {
|
|
stdout += payload$1;
|
|
if (stdout.endsWith("\n")) {
|
|
onStdout?.(stdout);
|
|
stdout = "";
|
|
}
|
|
}
|
|
if (type === payloadType.execute.stderr) {
|
|
stderr += payload$1;
|
|
if (stderr.endsWith("\n")) {
|
|
if (stderr.startsWith("error:")) {
|
|
const index = stderr.indexOf("\n");
|
|
onStderr?.(stderr.slice(0, index));
|
|
onStderr?.(stderr.slice(index + 1));
|
|
} else onStderr?.(stderr);
|
|
stderr = "";
|
|
}
|
|
}
|
|
if (type === payloadType.execute.end) {
|
|
if (payload$1.success === false) onError?.(payload$1.exitDetail);
|
|
ws?.removeEventListener("message", onMessage);
|
|
onEnd?.();
|
|
}
|
|
}
|
|
ws?.addEventListener("message", onMessage);
|
|
}
|
|
|
|
//#endregion
|
|
export { rustExecute }; |