optimizing and squashing bugs in literate programs a whole bunch

This commit is contained in:
liquidex 2024-07-25 23:36:50 +02:00
parent e5c61490be
commit e9ae153266

View file

@ -1,6 +1,13 @@
import { CodeJar } from "treehouse/vendor/codejar.js"; import { CodeJar } from "treehouse/vendor/codejar.js";
import { compileSyntax, highlight } from "treehouse/components/literate-programming/highlight.js"; import { compileSyntax, highlight } from "treehouse/components/literate-programming/highlight.js";
const loggingEnabled = false;
function log(...message) {
if (loggingEnabled) {
console.log("[lp]", ...message);
}
}
let literatePrograms = new Map(); let literatePrograms = new Map();
function getLiterateProgram(name) { function getLiterateProgram(name) {
@ -64,8 +71,9 @@ class InputMode {
this.codeJar = CodeJar(frame, (frame) => this.highlight(frame)); this.codeJar = CodeJar(frame, (frame) => this.highlight(frame));
this.codeJar.onUpdate(() => { this.codeJar.onUpdate(() => {
log(`${this.frame.programName} input frame ${this.frame.frameIndex} update`);
for (let handler of frame.program.onChanged) { for (let handler of frame.program.onChanged) {
handler(frame.programName); handler(frame.programName, frame.frameIndex);
} }
}); });
@ -115,9 +123,18 @@ class OutputMode {
this.iframe.src = `${TREEHOUSE_SITE}/sandbox`; this.iframe.src = `${TREEHOUSE_SITE}/sandbox`;
this.frame.appendChild(this.iframe); this.frame.appendChild(this.iframe);
this.currentEvaluation = new Promise((resolve) => resolve());
this.completeCurrentEvaluation = () => {};
this.evaluationEnqueued = false;
this.iframe.contentWindow.treehouseSandboxInternals = { outputIndex: this.outputIndex }; this.iframe.contentWindow.treehouseSandboxInternals = { outputIndex: this.outputIndex };
this.iframe.contentWindow.addEventListener("message", (event) => { this.iframe.contentWindow.addEventListener("message", (event) => {
log(
`${this.frame.programName} output frame ${this.frame.frameIndex} (output index ${this.outputIndex}) recv`,
event.data,
);
let message = event.data; let message = event.data;
if (message.kind == "ready") { if (message.kind == "ready") {
this.evaluate(); this.evaluate();
@ -125,26 +142,47 @@ class OutputMode {
this.resize(); this.resize();
} else if (message.kind == "output" && message.outputIndex == this.outputIndex) { } else if (message.kind == "output" && message.outputIndex == this.outputIndex) {
if (message.output.kind == "error") { if (message.output.kind == "error") {
this.completeCurrentEvaluation();
this.error.textContent = messageOutputArrayToString(message.output.message); this.error.textContent = messageOutputArrayToString(message.output.message);
this.iframe.classList.add("hidden"); this.iframe.classList.add("hidden");
} else { } else {
this.addOutput(message.output); this.addOutput(message.output);
} }
} else if (message.kind == "evalComplete") { } else if (message.kind == "evalComplete") {
this.completeCurrentEvaluation();
this.error.textContent = ""; this.error.textContent = "";
this.flushConsoleClear(); this.flushConsoleClear();
} }
}); });
if (this.frame.placeholderImage != null) { if (this.frame.placeholderImage != null) {
this.frame.placeholderImage.classList.add("js"); this.frame.placeholderImage.classList.add("js", "loading");
this.frame.placeholderImage.classList.add("loading");
} }
this.frame.program.onChanged.push((_) => this.evaluate()); this.frame.program.onChanged.push((_, inputFrameIndex) => {
if (inputFrameIndex < this.frame.frameIndex) {
this.evaluateWhenPossible();
}
});
}
evaluateWhenPossible() {
if (!this.evaluationEnqueued) {
this.evaluationEnqueued = true;
this.currentEvaluation.then(() => {
this.evaluate();
this.evaluationEnqueued = false;
});
}
} }
evaluate() { evaluate() {
log(`${this.frame.programName} output frame ${this.frame.frameIndex} evaluate`);
this.currentEvaluation = new Promise((resolve) => {
this.completeCurrentEvaluation = resolve;
});
this.requestConsoleClear(); this.requestConsoleClear();
this.iframe.contentWindow.postMessage({ this.iframe.contentWindow.postMessage({
action: "eval", action: "eval",