separate console interface, fix prototype objects

This commit is contained in:
Reimar 2025-10-14 08:34:55 +02:00
parent 6b5f984299
commit 102c270b78
3 changed files with 61 additions and 46 deletions

View File

@ -48,7 +48,7 @@ export class CodeRunner {
} }
evaluateCode(code) { evaluateCode(code) {
// Move evalScope to globalThis // Move evalScope to global scope
const oldGlobalThis = {}; const oldGlobalThis = {};
for (const prop in this.evalScope) { for (const prop in this.evalScope) {
if (!Object.hasOwn(this.evalScope, prop)) continue; if (!Object.hasOwn(this.evalScope, prop)) continue;

View File

@ -38,14 +38,14 @@ const playgroundConsole = new PlaygroundConsole(
); );
addEventListener("DOMContentLoaded", () => { addEventListener("DOMContentLoaded", () => {
playgroundConsole.log("Karlkode 1.0"); playgroundConsole.getInterface().log("Karlkode 1.0");
}); });
const codeStopper = new CodeStopper(); const codeStopper = new CodeStopper();
const assetProvider = new AssetProvider(); const assetProvider = new AssetProvider();
const codeRunner = new CodeRunner(playgroundConsole, codeStopper); const codeRunner = new CodeRunner(playgroundConsole.getInterface(), codeStopper);
const assetEditor = new AssetEditor(document.querySelector("#asset-editor-container"), []); const assetEditor = new AssetEditor(document.querySelector("#asset-editor-container"), []);
new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, codeRunner); new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, codeRunner);
@ -53,7 +53,7 @@ new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, co
const htmlExporter = new HtmlExporter(assetProvider); const htmlExporter = new HtmlExporter(assetProvider);
const gamelib = new Gamelib( const gamelib = new Gamelib(
playgroundConsole, playgroundConsole.getInterface(),
codeStopper, codeStopper,
assetProvider, assetProvider,
document.querySelector("canvas"), document.querySelector("canvas"),
@ -89,7 +89,9 @@ loadButton.onclick = async () => {
`unreachable: something went wrong ! files.length > 1 : files.length = ${files.length}`, `unreachable: something went wrong ! files.length > 1 : files.length = ${files.length}`,
); );
} }
const items = KarlkoderCodec.de(await fetch(URL.createObjectURL(files[0])).then((x) => x.bytes())); const items = KarlkoderCodec.de(
await fetch(URL.createObjectURL(files[0])).then((x) => x.bytes()),
);
const assets = items const assets = items
.filter((x) => x.tag === "asset") .filter((x) => x.tag === "asset")
.map((x) => { .map((x) => {

View File

@ -9,7 +9,7 @@ export class PlaygroundConsole {
}; };
} }
#formatStacktrace(stack) { formatStacktrace(stack) {
return stack return stack
.replaceAll(globalThis.origin + "/", "") .replaceAll(globalThis.origin + "/", "")
.replace( .replace(
@ -18,7 +18,7 @@ export class PlaygroundConsole {
); );
} }
#getTypeName(arg) { getTypeName(arg) {
if (arg instanceof Error) { if (arg instanceof Error) {
return "error"; return "error";
} }
@ -30,7 +30,7 @@ export class PlaygroundConsole {
return typeof arg; return typeof arg;
} }
#addKeyValue(_entryType, parent, property, arg) { addKeyValue(_entryType, parent, property, arg) {
if (property) { if (property) {
const keyEl = document.createElement("span"); const keyEl = document.createElement("span");
keyEl.className = property === "__proto__" ? "prototype" : "property"; keyEl.className = property === "__proto__" ? "prototype" : "property";
@ -42,11 +42,11 @@ export class PlaygroundConsole {
const value = document.createElement("span"); const value = document.createElement("span");
value.textContent = argString; value.textContent = argString;
value.dataset.type = this.#getTypeName(arg); value.dataset.type = this.getTypeName(arg);
parent.appendChild(value); parent.appendChild(value);
} }
#addEntry(entryType, property, parent, ...args) { addEntry(entryType, property, parent, ...args) {
for (const arg of args) { for (const arg of args) {
// For objects, show a collapsed list of properties // For objects, show a collapsed list of properties
if (typeof arg === "object" && arg !== null) { if (typeof arg === "object" && arg !== null) {
@ -55,7 +55,7 @@ export class PlaygroundConsole {
summary.dataset.type = "object"; summary.dataset.type = "object";
summary.style.marginLeft = "-1rem"; summary.style.marginLeft = "-1rem";
this.#addKeyValue(entryType, summary, property, arg); this.addKeyValue(entryType, summary, property, arg);
const details = document.createElement("details"); const details = document.createElement("details");
details.className = entryType; details.className = entryType;
@ -66,14 +66,12 @@ export class PlaygroundConsole {
if (arg instanceof Error) { if (arg instanceof Error) {
// Add error stack trace // Add error stack trace
const el = document.createElement("p"); const el = document.createElement("p");
el.innerHTML = this.#formatStacktrace(arg.stack); el.innerHTML = this.formatStacktrace(arg.stack);
details.appendChild(el); details.appendChild(el);
} else { } else {
// Add object properties // Add object properties
for (const prop in arg) { for (const prop of Object.getOwnPropertyNames(arg)) {
if (!Object.hasOwn(arg, prop)) continue; this.addEntry(
this.#addEntry(
entryType, entryType,
prop, prop,
details, details,
@ -82,10 +80,9 @@ export class PlaygroundConsole {
} }
// Add prototype if one exists // Add prototype if one exists
if ( const prototype = Object.getPrototypeOf(arg);
Object.getPrototypeOf(arg) && Object.keys(Object.getPrototypeOf(arg)).length if (prototype && Object.getOwnPropertyNames(prototype).length > 0) {
) { this.addEntry(entryType, "__proto__", details, prototype);
this.#addEntry(entryType, "__proto__", details, Object.getPrototypeOf(arg));
} }
} }
@ -97,46 +94,62 @@ export class PlaygroundConsole {
// For non-object values, show it directly // For non-object values, show it directly
const wrapper = document.createElement("p"); const wrapper = document.createElement("p");
wrapper.className = entryType; wrapper.className = entryType;
this.#addKeyValue(entryType, wrapper, property, arg); this.addKeyValue(entryType, wrapper, property, arg);
parent.appendChild(wrapper); parent.appendChild(wrapper);
} }
} }
#addTopLevelEntry(entryType, ...args) { addTopLevelEntry(entryType, ...args) {
this.#addEntry(entryType, "", this.elem, ...args); this.addEntry(entryType, "", this.elem, ...args);
this.elem.scrollTop = this.elem.scrollHeight; this.elem.scrollTop = this.elem.scrollHeight;
} }
addInput() { addInput() {
this.#addTopLevelEntry("input", ...arguments); this.addTopLevelEntry("input", ...arguments);
} }
log() { getInterface() {
this.#addTopLevelEntry("log", ...arguments); return new PlaygroundConsoleInterface(this);
}
dir() {
this.#addTopLevelEntry("dir", ...arguments);
}
debug() {
this.#addTopLevelEntry("debug", ...arguments);
}
info() {
this.#addTopLevelEntry("info", ...arguments);
}
warn() {
this.#addTopLevelEntry("warn", ...arguments);
}
error() {
this.#addTopLevelEntry("error", ...arguments);
} }
clear() { clear() {
this.elem.textContent = ""; this.elem.textContent = "";
} }
} }
class PlaygroundConsoleInterface {
#console;
constructor(console) {
this.#console = console;
}
log() {
this.#console.addTopLevelEntry("log", ...arguments);
}
dir() {
this.#console.addTopLevelEntry("dir", ...arguments);
}
debug() {
this.#console.addTopLevelEntry("debug", ...arguments);
}
info() {
this.#console.addTopLevelEntry("info", ...arguments);
}
warn() {
this.#console.addTopLevelEntry("warn", ...arguments);
}
error() {
this.#console.addTopLevelEntry("error", ...arguments);
}
clear() {
this.#console.clear();
}
}