general cleanup and bugfixing

This commit is contained in:
SArpnt 2024-08-05 21:51:03 -04:00
parent 26ae64b723
commit 23136ddc01
Signed by: SArpnt
SSH key fingerprint: SHA256:iDMeic8KkqqEsN4wODlgsk1d/oW1ojZ/cu/MEWyfLBw
10 changed files with 31 additions and 29 deletions

View file

@ -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,

View file

@ -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;
}

View file

@ -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]);

View file

@ -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

View file

@ -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"],

View file

@ -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

View file

@ -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<any>) {
function handleMessage(e: MessageEvent<unknown>) {
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);

View file

@ -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;

View file

@ -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");

View file

@ -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}