some cleanup

This commit is contained in:
SArpnt 2024-03-13 18:11:33 -04:00
parent 33bbaae8a8
commit b135d1a53a
Signed by: SArpnt
SSH Key Fingerprint: SHA256:iDMeic8KkqqEsN4wODlgsk1d/oW1ojZ/cu/MEWyfLBw
2 changed files with 56 additions and 46 deletions

View File

@ -1,34 +1,34 @@
// note: imports don't work: https://bugzilla.mozilla.org/show_bug.cgi?id=1636121
function jsOptimize(script, isExpression = true) {
function jsOptimize(script: string, isExpression = true) {
script = script.trim();
{
// detect eval(unescape(escape(<const string>).replace(/u(..)/g, "$1%")))
let evalOptScript = script;
let replaces = 0;
evalOptScript = evalOptScript.replace(
let hadStart = false;
const withoutStart = script.replace(
/^eval\s*\(\s*unescape\s*\(\s*escape/,
() => (replaces++, ""),
() => (hadStart = true, ""),
);
if (replaces === 1) {
evalOptScript = evalOptScript.replace(
if (hadStart) {
let hadEnd = false
const withoutEnd = withoutStart.replace(
/\.replace\(\/u\(\.\.\)\/g,([`"'])\$1%\1\)\)\)$/,
() => (replaces++, ""),
() => (hadEnd = true, ""),
);
if (replaces === 2) {
let hasParens = false;
evalOptScript = evalOptScript.replace(
if (hadEnd) {
let hadParens = false;
const content = withoutEnd.replace(
/^\s*\((?<content>.*)\)\s*$/s,
(_, content) => ((hasParens = true), content),
(_, content) => (hadParens = true, content),
);
evalOptScript = evalOptScript
const part4 = content
.trim()
.match(hasParens ? /^(?<quote>[`"'])(?<content>.*)\1$/s : /^`(?<content>.*)`$/s);
if (evalOptScript) {
const quote = evalOptScript.groups.quote ?? "`";
const stringContent = evalOptScript.groups.content;
.match(hadParens ? /^(?<quote>[`"'])(?<content>.*)\1$/s : /^`(?<content>.*)`$/s);
if (part4) {
const quote = part4.groups.quote ?? "`";
const stringContent = part4.groups.content;
if (
!stringContent.includes(evalOptScript.groups.quote) &&
!stringContent.includes(part4.groups.quote) &&
!stringContent.includes("\\") // TODO: improve escape handling
) {
script = unescape(escape(stringContent).replace(/u(..)/g, "$1%"));
@ -283,7 +283,7 @@ class BytebeatProcessor extends AudioWorkletProcessor {
let time = this.sampleRatio * this.audioSample;
let byteSample = this.byteSample;
const drawBuffer = [];
const drawBuffer: { t: number, value: [number, number] }[] = [];
for (let i = 0; i < chDataLen; i++) {
time += this.sampleRatio;
const flooredTime = Math.floor(time / this.sampleRateDivisor) * this.sampleRateDivisor;

View File

@ -5,10 +5,8 @@ import { initCodeEditor, getCode, setCode } from "./code-editor/mod.ts";
const searchParams = new URLSearchParams(location.search);
const timeUnits = [
"t",
"s", // sec
];
const timeUnits = ["t", "s"] as const;
type TimeUnit = typeof timeUnits[number];
let audioCtx = null;
let audioWorklet = null;
@ -19,9 +17,12 @@ let nextErr = null;
let nextErrPriority = undefined;
let errorPriority = -Infinity;
let ctx = null;
let ctx: CanvasRenderingContext2D | null = null;
let drawSettings = { scale: null };
let drawBuffer = [];
let drawBuffer: { // TODO is this correct?
t: number,
value: [number, number],
}[] = [];
let drawImageData = null;
let byteSample = 0;
@ -35,40 +36,43 @@ let songData: {
mode: "Bytebeat",
};
let playSpeed = 1;
let volume = null;
let volume: number = null;
let timeUnit = null;
let timeUnit: TimeUnit | null = null;
let animationFrameId = null;
let elements: Awaited<typeof elementsPromise> | null = null; // TODO remove
(async function init() {
await initAudioContext();
const audioPromise = initAudioContext();
elements = await elementsPromise;
initCodeEditor(refreshCode);
ctx = elements.canvas.getContext("2d", { alpha: false });
if (globalThis.loadLibrary !== false) {
import("./library/load.ts");
}
ctx = elements.canvas.getContext("2d", { alpha: false });
handleWindowResize(true);
document.defaultView.addEventListener("resize", () => handleWindowResize(false));
document.defaultView.addEventListener("resize", handleWindowResize);
loadSettings();
let urlData: Song | undefined;
if (window.location.hash && globalThis.useUrlData !== false) {
urlData = await fromUrlData(window.location.hash);
}
await audioPromise;
setSong(urlData, false);
updateCounterValue();
})();
async function initAudioContext() {
let audioContextSampleRate = Number(searchParams.get("audioContextSampleRate"));
let audioContextSampleRate = Number(searchParams.get("baseSampleRate"));
if (!(audioContextSampleRate > 0)) {
// also true for NaN
audioContextSampleRate = 48000; // TODO this should be set to an lcm > 44100
@ -76,7 +80,7 @@ async function initAudioContext() {
audioCtx = new AudioContext({
latencyHint:
(searchParams.get("audioContextLatencyHint") as AudioContextLatencyCategory) ?? "balanced",
(searchParams.get("latencyHint") as AudioContextLatencyCategory) ?? "balanced",
sampleRate: audioContextSampleRate,
});
@ -158,7 +162,7 @@ function refreshCode() {
audioWorklet.port.postMessage({ code: getCode().trim() });
}
}
function handleWindowResize(force: boolean) {
function handleWindowResize(force?: boolean) {
autoSizeCanvas(force);
}
function autoSizeCanvas(force: boolean = false) {
@ -187,7 +191,7 @@ function setCanvasWidth(width: number, force: boolean = false) {
}
}
function animationFrame() {
drawGraphics();
drawGraphics(ctx);
if (nextErr) {
showErrorMessage(nextErrType, nextErr, nextErrPriority);
}
@ -256,7 +260,7 @@ function setVolume(save = true, value?: number) {
function clearCanvas(clear = true) {
if (ctx) {
ctx.fillRect(0, 0, elements.canvas.width, elements.canvas.height);
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
if (clear) {
clearDrawBuffer();
}
@ -275,8 +279,8 @@ function getXpos(t) {
function getTimeFromXpos(x) {
return x * (1 << drawSettings.scale);
}
function drawGraphics() {
const { width, height } = elements.canvas;
function drawGraphics(ctx: CanvasRenderingContext2D) {
const { width, height } = ctx.canvas;
const bufferLen = drawBuffer.length;
if (!bufferLen) {
@ -619,9 +623,19 @@ function saveSettings() {
});
}
}
function loadSettings() {
type Settings = {
drawSettings: typeof drawSettings,
volume: number,
timeUnit: TimeUnit,
}
function loadSettings(): Settings {
if (localStorage.settings && globalThis.useLocalStorage !== false) {
let settings;
let settings: {
drawSettings: typeof drawSettings,
volume: typeof volume,
timeUnit: typeof timeUnit,
};
try {
settings = JSON.parse(localStorage.settings);
} catch (err) {
@ -637,11 +651,8 @@ function loadSettings() {
drawSettings.scale = 5;
}
if (Object.hasOwnProperty.call(settings, "volume")) {
setVolume(false, settings.volume);
} else {
setVolume(false);
}
setVolume(false, settings.volume);
setVolume(false);
if (Object.hasOwnProperty.call(settings, "timeUnit")) {
setTimeUnit(settings.timeUnit, false);
@ -656,7 +667,6 @@ function loadDefaultSettings() {
drawSettings.scale = 5;
setVolume(false);
setTimeUnit(undefined, false);
saveSettings();
}
// used in html