From 23136ddc01a523d680873f786f2dcf81ffda15d4 Mon Sep 17 00:00:00 2001 From: SArpnt Date: Mon, 5 Aug 2024 21:51:03 -0400 Subject: [PATCH] general cleanup and bugfixing --- eleventy.config.js | 2 +- src/audio-worklet/audio-worklet.ts | 2 ++ src/audio-worklet/clean-globals.ts | 4 +++- src/embed.pug | 2 +- src/embed.ts | 2 +- src/index.pug | 2 +- src/{bytebeat.ts => interface.ts} | 24 ++++++++++++------------ src/library/load.ts | 2 +- src/oscillioscope.ts | 2 +- src/style.css | 18 ++++++++---------- 10 files changed, 31 insertions(+), 29 deletions(-) rename src/{bytebeat.ts => interface.ts} (95%) diff --git a/eleventy.config.js b/eleventy.config.js index 543ee37..814f4b6 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -20,7 +20,7 @@ module.exports = eleventyConfig => { eleventyConfig.on("eleventy.after", async ({ dir, results, runMode, outputMode }) => { await Promise.all([ esbuild.build({ - entryPoints: [`src/style.css`, `src/bytebeat.ts`, `src/embed.ts`], + entryPoints: [`src/style.css`, `src/interface.ts`, `src/embed.ts`], outdir: output, format: "esm", bundle: true, diff --git a/src/audio-worklet/audio-worklet.ts b/src/audio-worklet/audio-worklet.ts index eb16bb4..113b5e8 100644 --- a/src/audio-worklet/audio-worklet.ts +++ b/src/audio-worklet/audio-worklet.ts @@ -277,6 +277,8 @@ class BytebeatProcessor extends AudioWorkletProcessor { if (proxies.has(v)) { throw new TypeError("can't convert proxy to number"); } else { + // this does not cast BigInt, which matches the behaviour of + // placing it directly into a typed array // @ts-expect-error return +v; } diff --git a/src/audio-worklet/clean-globals.ts b/src/audio-worklet/clean-globals.ts index 13e9c59..3973b82 100644 --- a/src/audio-worklet/clean-globals.ts +++ b/src/audio-worklet/clean-globals.ts @@ -2,11 +2,12 @@ export function deleteGlobals() { // delete all single letter variables // a bytebeat might make some variables not enumerable, so this catches the important ones for (let i = 0; i < 26; i++) { + // @ts-expect-error delete globalThis[String.fromCharCode(65 + i)], globalThis[String.fromCharCode(97 + i)]; } // delete enumerable variables // @ts-expect-error - Object.keys(globalThis).forEach(k => { + Object.keys(globalThis).forEach((k: string & keyof typeof globalThis) => { // TODO: get rid of these global variables if (!["currentTime", "sampleRate"].includes(k)) { delete globalThis[k]; @@ -22,6 +23,7 @@ export function freezeExistingGlobals() { let t = typeof globalThis[k]; if ((t === "object" || t === "function") && k !== "globalThis") { if (t === "function" && Object.hasOwnProperty.call(globalThis[k], "prototype")) { + // @ts-expect-error Object.freeze(globalThis[k].prototype); } Object.freeze(globalThis[k]); diff --git a/src/embed.pug b/src/embed.pug index 6a85996..7100c8b 100644 --- a/src/embed.pug +++ b/src/embed.pug @@ -13,7 +13,7 @@ html(data-embed lang="en") globalThis.useLocalStorage = false; globalThis.useUrlData = false; script(src="/embed.js" defer type="module") - script(src="/bytebeat.js" defer type="module") + script(src="/interface.js" defer type="module") link(rel="modulepreload" as="audioworklet" href="/audio-worklet.js") body main#content diff --git a/src/embed.ts b/src/embed.ts index dfde4d6..8346af5 100644 --- a/src/embed.ts +++ b/src/embed.ts @@ -1,6 +1,6 @@ import { isPlainObject } from "./common.ts"; import elements from "./elements.ts"; -import { setCanvasWidth, autoSizeCanvas, getSong, setSong } from "./bytebeat.ts"; +import { setCanvasWidth, autoSizeCanvas, getSong, setSong } from "./interface.ts"; const nameids: [string, (show: boolean) => void, ...string[]][] = [ ["codeEditor", () => {}, "code-editor-container"], diff --git a/src/index.pug b/src/index.pug index 1d686dc..73c592d 100644 --- a/src/index.pug +++ b/src/index.pug @@ -8,7 +8,7 @@ html(lang="en") title Bytebeat composer link(href="/favicon.png" rel="shortcut icon") link(href="/style.css" type="text/css" rel="stylesheet") - script(src="/bytebeat.js" defer type="module") + script(src="/interface.js" defer type="module") link(rel="modulepreload" as="audioworklet" href="/audio-worklet.js") body main#content diff --git a/src/bytebeat.ts b/src/interface.ts similarity index 95% rename from src/bytebeat.ts rename to src/interface.ts index 5a5f840..518a0f1 100644 --- a/src/bytebeat.ts +++ b/src/interface.ts @@ -1,5 +1,7 @@ import { f32ToRound10, isPlainObject, Song, SongMode, StrongPartial } from "./common.ts"; import elements from "./elements.ts"; +// this shouldn't need to load when useUrlData is false, +// but if it was loaded conditionally then it can't inline import { fromUrlData, setUrlData } from "./url/mod.ts"; import { CodeEditor } from "./code-editor/mod.ts"; import { Oscillioscope } from "./oscillioscope.ts"; @@ -46,13 +48,15 @@ loadSettings(); } // XXX: global variables -let nextErrType = null; let nextErr = null; +let nextErrType = null; let nextErrPriority = undefined; let errorPriority = -Infinity; async function initAudioContext() { - let audioContextSampleRate = Number(searchParams.get("baseSampleRate")); + // null casts to 0 which is fine + // @ts-expect-error + let audioContextSampleRate = +searchParams.get("baseSampleRate"); // also true for NaN if (!(audioContextSampleRate > 0)) { audioContextSampleRate = 48000; // TODO this should be set to an lcm > 44100 @@ -129,7 +133,7 @@ export function getSong(): Song { return { code: codeEditor.getCode(), ...songData }; } -function handleMessage(e: MessageEvent) { +function handleMessage(e: MessageEvent) { if (isPlainObject(e.data)) { const data = e.data; if (data.clearCanvas) { @@ -182,11 +186,7 @@ function changeScale(amount: number) { if (amount) { osc.settings.scale = Math.max(osc.settings.scale + amount, 0); osc.clear(false); - if (osc.settings.scale <= 0) { - elements.scaleDown.setAttribute("disabled", true); - } else { - elements.scaleDown.removeAttribute("disabled"); - } + elements.scaleDown.toggleAttribute("disabled", osc.settings.scale <= 0); osc.showTimeCursor(timeCursorShouldBeVisible()); osc.moveTimeCursor(sample, playSpeed >= 0); @@ -330,7 +330,7 @@ function setSampleRateDivisor(sampleRateDivisor: number) { } } -function setVolume(save = true, value?: number) { +function setVolume(value?: number, save = true) { if (value !== undefined) { volume = value; // implicit cast @@ -351,7 +351,7 @@ type Settings = { timeUnit: TimeUnit; }; function loadDefaultSettings() { - setVolume(false); + setVolume(undefined, false); setTimeUnit(undefined, false); } function loadSettings(): Settings { @@ -362,7 +362,7 @@ function loadSettings(): Settings { timeUnit?: typeof timeUnit; }; try { - // FIXME: this should be validated + // TODO: this should be validated settings = JSON.parse(localStorage["settings"]); } catch (err) { console.error("Couldn't load settings!", localStorage["settings"]); @@ -377,7 +377,7 @@ function loadSettings(): Settings { osc.settings.scale = 5; } - setVolume(false, settings.volume); + setVolume(settings.volume, false); if (settings.timeUnit) { setTimeUnit(settings.timeUnit, false); diff --git a/src/library/load.ts b/src/library/load.ts index 806fb94..64ec447 100644 --- a/src/library/load.ts +++ b/src/library/load.ts @@ -1,5 +1,5 @@ import { library, Entry, InlineEntry } from "./library.ts"; -import { setSong } from "../bytebeat.js"; +import { setSong } from "../interface.ts"; function stripEntryToSong(entry: Entry) { const { sampleRate, mode } = entry; diff --git a/src/oscillioscope.ts b/src/oscillioscope.ts index 8d2f9a5..0795000 100644 --- a/src/oscillioscope.ts +++ b/src/oscillioscope.ts @@ -228,7 +228,7 @@ export class Oscillioscope { // TODO don't make this depend on play direction moveTimeCursor(time: number, playingForward: boolean) { - if (!this.timeCursor.hasAttribute("disabled")) { + if (!this.timeCursor.classList.contains("disabled")) { const width = this.ctx.canvas.width; if (playingForward) { this.timeCursor.style.removeProperty("right"); diff --git a/src/style.css b/src/style.css index 1f1488b..9d7e637 100644 --- a/src/style.css +++ b/src/style.css @@ -10,9 +10,9 @@ code, #code-editor, #code-editor .cm-scroller {font-family:"",monospace} #content {display:flex; flex-direction:column; height:100%} @media (min-width:1540px) { /* 1024 (canvas) + 4 (outline) + 512 (library) */ - html:not([data-embed]) #content { - flex-direction:row; - min-width:100%}} /* override js window resize event while still letting .container-fixed inherit max-width */ + /* override js window resize event while still letting .container-fixed inherit max-width */ + html:not([data-embed]) #content {flex-direction:row; min-width:100%} +} .container-fixed { display:flex; flex-direction:column; flex-shrink:0; @@ -24,9 +24,9 @@ html[data-embed] .container-fixed {height:100%} display:block; box-sizing:border-box; width:100%; height:256px; border:2px solid white; overflow:hidden; resize:vertical} @media (min-width:1540px) { /* 1024 (canvas) + 4 (outline) + 512 (library) */ - #code-editor-container { - resize:none; - height:100% !important}} /* override resize handle */ + /* override resize handle */ + #code-editor-container {resize:none; height:100% !important} +} html[data-embed] #code-editor-container {resize:none; height:100%} #code-editor {width:100%; height:100%; line-height:1; font-size:1rem} #code-editor:not(.cm-editor) { @@ -81,7 +81,7 @@ button, input {font-size:100%} #canvas-container { display:flex; position:relative; box-sizing:border-box; border:2px solid #fc4} -#canvas-container:not([data-disabled="true"]) {cursor:pointer} +#canvas-container:not([data-disabled]) {cursor:pointer} #canvas-main {width:100%; height:auto} @@ -112,9 +112,7 @@ button, input {font-size:100%} .container-scroll {overflow-y:auto; flex-grow:1} @media (min-width:1540px) { /* 1024 (canvas) + 4 (outline) + 512 (library) */ /* TODO: reorganize to merge identical media queries */ - .container-scroll { - padding-left:0.8rem; - } + .container-scroll {padding-left:0.8rem} } details > :not(summary) {margin-inline-start:1em}