Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/cm/keyBindingUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ export function toCodeMirrorKey(combo) {
return strokes.length ? strokes.join(" ") : null;
}

// Conflict checks compare every binding with every other one each time the
// keymap is rebuilt (once per registered command), so cache the parsed form.
// Conflict checks compare every binding with every other one on each keymap
// rebuild, so cache the parsed form. The app has a few hundred binding strings;
// the cap only stops unbounded growth from repeated registrations of new keys.
const MAX_CANONICAL_KEY_CACHE_SIZE = 1000;
const canonicalKeyCache = new Map();

export function canonicalizeKeyBinding(combo) {
Expand All @@ -55,6 +57,9 @@ export function canonicalizeKeyBinding(combo) {
}
if (canonicalKeyCache.has(combo)) return canonicalKeyCache.get(combo);
const canonicalKey = toCodeMirrorKey(combo)?.toLowerCase() || null;
if (canonicalKeyCache.size >= MAX_CANONICAL_KEY_CACHE_SIZE) {
canonicalKeyCache.clear();
}
canonicalKeyCache.set(combo, canonicalKey);
return canonicalKey;
}
Expand Down
4 changes: 3 additions & 1 deletion src/lib/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ const CONSOLE_THEME_STATE = "__acode_console_theme.json";
* @param {Boolean} isConsole
* @param {"inapp"|"browser"} target
* @param {Boolean} runFile
* @param {EditorFile} [file] file to run, captured when the run was requested
*/
async function run(
isConsole = false,
target = appSettings.value.previewMode,
runFile = false,
file = editorManager.activeFile,
) {
/** @type {EditorFile} */
const activeFile = isConsole ? null : editorManager.activeFile;
const activeFile = isConsole ? null : file;

if (!isConsole && Url.extname(activeFile?.filename || "") === ".md") {
if (!(await activeFile?.canRun())) return;
Expand Down
15 changes: 10 additions & 5 deletions src/lib/runLazily.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
/**
* Runs/previews a file, loading the runner on first use. The runner pulls in
* markdown-it and the markdown preview, which are not needed at startup.
* @param {...any} args arguments for lib/run
* Runs/previews the active file, loading the runner on first use. The runner
* pulls in markdown-it and the markdown preview, which are not needed at
* startup.
* @param {boolean} [isConsole]
* @param {"inapp"|"browser"} [target]
* @param {boolean} [runFile]
*/
export default async function runLazily(...args) {
export default async function runLazily(isConsole, target, runFile) {
// Capture the file now: the user may switch tabs while the runner loads.
const file = isConsole ? null : editorManager.activeFile;
const { default: run } = await import(/* webpackChunkName: "run" */ "./run");
return run(...args);
return run(isConsole, target, runFile, file);
}
34 changes: 34 additions & 0 deletions tests/unit/runLazily.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect, it, vi } from "vitest";
import { loadSourceModule } from "../helpers/loadSourceModule";

function setup() {
const run = vi.fn();
const editorManager = { activeFile: { id: "requested" } };
const { default: runLazily } = loadSourceModule(
"src/lib/runLazily.js",
{ "./run": { __esModule: true, default: run } },
{ editorManager },
);
return { run, editorManager, runLazily };
}

it("runs the file that was active when the run was requested", async () => {
const { run, editorManager, runLazily } = setup();

const pending = runLazily(false, "inapp", true);
// The user switches tabs while the runner chunk is still loading.
editorManager.activeFile = { id: "switched" };
await pending;

expect(run).toHaveBeenCalledExactlyOnceWith(false, "inapp", true, {
id: "requested",
});
});

it("does not capture a file for the console", async () => {
const { run, runLazily } = setup();

await runLazily(true, "inapp");

expect(run).toHaveBeenCalledExactlyOnceWith(true, "inapp", undefined, null);
});
Loading