1
0

Support syscalls in sandboxed iframes

This commit is contained in:
Zef Hemel 2023-01-16 10:40:16 +01:00
parent 9c0525e683
commit ef7830662e
7 changed files with 98 additions and 100 deletions

View File

@ -374,11 +374,9 @@ functions:
showLogsCommand: showLogsCommand:
path: ./debug.ts:showLogsCommand path: ./debug.ts:showLogsCommand
command: command:
name: "Debug: Show Logs" name: "Show Logs"
key: "Ctrl-Alt-l" key: "Ctrl-Alt-l"
mac: "Cmd-Alt-l" mac: "Cmd-Alt-l"
events:
- log:reload
hideBhsCommand: hideBhsCommand:
path: ./debug.ts:hideBhsCommand path: ./debug.ts:hideBhsCommand
command: command:

View File

@ -1,10 +1,4 @@
import { sandbox } from "$sb/plugos-syscall/mod.ts"; import { editor, markdown } from "$sb/silverbullet-syscall/mod.ts";
import {
editor,
markdown,
sandbox as serverSandbox,
system,
} from "$sb/silverbullet-syscall/mod.ts";
export async function parsePageCommand() { export async function parsePageCommand() {
console.log( console.log(
@ -18,22 +12,13 @@ export async function parsePageCommand() {
} }
export async function showLogsCommand() { export async function showLogsCommand() {
// Running in client/server mode? await editor.showPanel(
const clientServer = !!(await system.getEnv()); "bhs",
1,
if (clientServer) { `
const clientLogs = await sandbox.getLogs();
const serverLogs = await serverSandbox.getServerLogs();
await editor.showPanel(
"bhs",
1,
`
<style> <style>
#reload {
width: 75%;
}
#close { #close {
width: 20%; width: 100%;
} }
#client-log-header { #client-log-header {
position: absolute; position: absolute;
@ -63,87 +48,43 @@ export async function showLogsCommand() {
overflow: scroll; overflow: scroll;
} }
</style> </style>
<button onclick="self.reloadLogs()" id="reload">Reload</button>
<button onclick="self.close()" id="close">Close</button> <button onclick="self.close()" id="close">Close</button>
<div id="client-log-header">Client logs (max 100)</div> <div id="client-log-header">Client logs (max 100)</div>
<div id="client-log"> <div id="client-log">Loading...</div>
<pre>${
clientLogs
.map((le) => `[${le.level}] ${le.message}`)
.join("\n")
}</pre>
</div>
<div id="server-log-header">Server logs (max 100)</div> <div id="server-log-header">Server logs (max 100)</div>
<div id="server-log"> <div id="server-log">Loading...</div>`,
<pre>${ `
serverLogs const clientDiv = document.getElementById("client-log");
.map((le) => `[${le.level}] ${le.message}`)
.join("\n")
}</pre>
</div>`,
`
var clientDiv = document.getElementById("client-log");
clientDiv.scrollTop = clientDiv.scrollHeight; clientDiv.scrollTop = clientDiv.scrollHeight;
var serverDiv = document.getElementById("server-log"); const serverDiv = document.getElementById("server-log");
serverDiv.scrollTop = serverDiv.scrollHeight; serverDiv.scrollTop = serverDiv.scrollHeight;
self.reloadLogs = () => {
sendEvent("log:reload");
};
self.close = () => { self.close = () => {
sendEvent("log:hide"); sendEvent("log:hide");
}; };
syscall("system.getEnv").then((env) => {
const clientServerMode = !!env;
if (!clientServerMode) {
// Running in hybrid mode (mobile), so let's ignore server logs (they're the same as client logs)
serverDiv.style.display = "none";
clientDiv.style.width = "100%";
document.getElementById("server-log-header").style.display = "none";
}
setInterval(() => {
Promise.resolve().then(async () => {
if(clientServerMode) {
const serverLogs = await syscall("sandbox.getServerLogs");
serverDiv.innerHTML = "<pre>" + serverLogs.map((le) => "[" + le.level + "] " + le.message).join("\\n") + "</pre>";
}
const clientLogs = await syscall("sandbox.getLogs");
clientDiv.innerHTML = "<pre>" + clientLogs.map((le) => "[" + le.level + "] " + le.message).join("\\n") + "</pre>";
}).catch(console.error);
}, 1000);
});
`, `,
); );
} else {
const logs = await sandbox.getLogs();
await editor.showPanel(
"bhs",
1,
`
<style>
#reload {
width: 75%;
}
#close {
width: 20%;
}
#log-header {
position: absolute;
left: 0;
top: 35px;
}
#log {
position: absolute;
left: 0;
top: 60px;
bottom: 0;
width: 100%;
overflow: scroll;
}
</style>
<button onclick="self.reloadLogs()" id="reload">Reload</button>
<button onclick="self.close()" id="close">Close</button>
<div id="log-header">Logs (max 100)</div>
<div id="log">
<pre>${
logs
.map((le) => `[${le.level}] ${le.message}`)
.join("\n")
}</pre>
</div>`,
`
var clientDiv = document.getElementById("log");
clientDiv.scrollTop = clientDiv.scrollHeight;
self.reloadLogs = () => {
sendEvent("log:reload");
};
self.close = () => {
sendEvent("log:hide");
};
`,
);
}
} }
export async function hideBhsCommand() { export async function hideBhsCommand() {

View File

@ -8,6 +8,22 @@ export const panelHtml = `<!DOCTYPE html>
<meta charset="UTF-8"> <meta charset="UTF-8">
<base target="_top"> <base target="_top">
<script> <script>
const pendingRequests = new Map();
let syscallReqId = 0;
self.syscall = async (name, ...args) => {
return await new Promise((resolve, reject) => {
syscallReqId++;
pendingRequests.set(syscallReqId, { resolve, reject });
window.parent.postMessage({
type: "syscall",
id: syscallReqId,
name,
args,
}, "*");
});
};
window.addEventListener("message", (message) => { window.addEventListener("message", (message) => {
const data = message.data; const data = message.data;
switch (data.type) { switch (data.type) {
@ -20,6 +36,28 @@ window.addEventListener("message", (message) => {
console.error("Error evaling script", e); console.error("Error evaling script", e);
} }
} }
break;
case "syscall-response":
{
const syscallId = data.id;
const lookup = pendingRequests.get(syscallId);
if (!lookup) {
console.log(
"Current outstanding requests",
pendingRequests,
"looking up",
syscallId,
);
throw Error("Invalid request id");
}
pendingRequests.delete(syscallId);
if (data.error) {
lookup.reject(new Error(data.error));
} else {
lookup.resolve(data.result);
}
}
break; break;
} }
}); });
@ -92,8 +130,27 @@ export function Panel({
if (!data) { if (!data) {
return; return;
} }
if (data.type === "event") { switch (data.type) {
editor.dispatchAppEvent(data.name, ...data.args); case "event":
editor.dispatchAppEvent(data.name, ...data.args);
break;
case "syscall": {
const { id, name, args } = data;
editor.system.localSyscall("core", name, args).then((result) => {
iFrameRef.current!.contentWindow!.postMessage({
type: "syscall-response",
id,
result,
});
}).catch((e: any) => {
iFrameRef.current!.contentWindow!.postMessage({
type: "syscall-response",
id,
error: e.message,
});
});
break;
}
} }
}; };
globalThis.addEventListener("message", messageListener); globalThis.addEventListener("message", messageListener);

View File

@ -130,8 +130,8 @@ export class Editor {
.dispatchEvent("editor:updated") .dispatchEvent("editor:updated")
.catch((e) => console.error("Error dispatching editor:updated event", e)); .catch((e) => console.error("Error dispatching editor:updated event", e));
}, 1000); }, 1000);
private system: System<SilverBulletHooks>; system: System<SilverBulletHooks>;
private mdExtensions: MDExt[] = []; mdExtensions: MDExt[] = [];
urlPrefix: string; urlPrefix: string;
indexPage: string; indexPage: string;

View File

@ -41,7 +41,6 @@
<body> <body>
<div id="sb-root"></div> <div id="sb-root"></div>
<h1>SUPPP</h1>
</body> </body>
</html> </html>

View File

@ -139,6 +139,7 @@
.sb-bhs { .sb-bhs {
height: 300px; height: 300px;
width: 100%; width: 100%;
z-index: 1000;
.sb-panel { .sb-panel {
height: 100%; height: 100%;

View File

@ -16,10 +16,12 @@
.sb-panel { .sb-panel {
border-left: 1px solid #eee; border-left: 1px solid #eee;
background-color: #fff;
} }
.sb-bhs { .sb-bhs {
border-top: rgb(193, 193, 193) 1px solid; border-top: rgb(193, 193, 193) 1px solid;
background-color: #fff;
} }
.sb-modal { .sb-modal {