diff --git a/fps-meter/bak/main.mjs b/fps-meter/bak/main.mjs index 1e0a872..845a773 100644 --- a/fps-meter/bak/main.mjs +++ b/fps-meter/bak/main.mjs @@ -1,5 +1,5 @@ -import { FpsTracker } from '../FpsTracker.mjs'; -import { CanvasFps } from '../CanvasFps.mjs'; +import { FpsTracker } from '../FpsTracker.js'; +import { CanvasFps } from './CanvasFps.js'; import { ThreadLocalRAFIterator, SendPostMessageRAF } from '../AnimationFrameIterator.js'; diff --git a/fps-meter/fps-meter.js b/fps-meter/fps-meter.js new file mode 100644 index 0000000..e69de29 diff --git a/lib/raf.js b/lib/raf.js deleted file mode 100644 index f8f170e..0000000 --- a/lib/raf.js +++ /dev/null @@ -1,13 +0,0 @@ -export async function raf() { - return new Promise(resolve => { - requestAnimationFrame(resolve); - }); -} - -export async function afterNextPaint() { - // TODO: experiment with scheduler.render() when available - await raf(); - // TODO: polyfill as needed - await scheduler.yield(); - -} \ No newline at end of file diff --git a/lib/scheduling-utils.js b/lib/scheduling-utils.js new file mode 100644 index 0000000..9aaaced --- /dev/null +++ b/lib/scheduling-utils.js @@ -0,0 +1,64 @@ +export async function raf(signal) { + return new Promise((resolve, reject) => { + // TODO: Alternative: if signal.aborted reject(signal.reason) + signal?.throwIfAborted(); + + // TODO: is it needed to remove abort eventlistener after successful resolve? + const rafid = requestAnimationFrame(resolve); + + signal?.addEventListener('abort', (ev) => { + cancelAnimationFrame(rafid); + // TODO: Is this useful? + reject(signal.reason); + }, { once: true }); + }); +} + +export async function afterNextPaint() { + // TODO: experiment with scheduler.render() when available + await raf(); + // TODO: polyfill as needed + await scheduler.yield(); +} + +export async function delay(ms) { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} + +export function block(ms) { + const taget = performance.now() + ms; + while (performance.now() < taget); +} + +export async function waitForEvent(target, eventName) { + return new Promise(resolve => { + target.addEventListener(eventName, resolve, { once: true }); + }); +} + +export async function idleUntilBeforeRender(opts = {}) { + // Default to highest priority, but you may want to use background + opts = { + priority: 'user-blocking', + ...opts, + }; + return new Promise(resolve => { + const contoller = new AbortController(); + + const rafid = requestAnimationFrame(() => { + contoller.abort(); + resolve(); + }); + + const taskid = scheduler.postTask(() => { + cancelAnimationFrame(rafid); + resolve(); + }, { + priority: 'user-blocking', + signal: contoller.signal, + }); + }); +} + diff --git a/live-expressions/lib/once-per-pageload.js b/live-expressions/lib/once-per-pageload.js index 1cbc7b5..2ddafa4 100644 --- a/live-expressions/lib/once-per-pageload.js +++ b/live-expressions/lib/once-per-pageload.js @@ -1,4 +1,4 @@ -import sha256 from "./str-to-hash"; +import sha256 from "../../lib/str-to-hash"; // This is mostly useful for DevTools live expressions export default function oncePerPageload(callback) { diff --git a/live-expressions/web-mightals.js b/live-expressions/web-mightals.js index 2060329..92844ed 100644 --- a/live-expressions/web-mightals.js +++ b/live-expressions/web-mightals.js @@ -1,4 +1,4 @@ -import { webMightals$ } from '../web-mightals.js'; +import { webMightals$ } from '../sandbox/web-mightals.js/index.js'; import oncePerPageload from "./lib/once-per-pageload.js"; function main() { diff --git a/sandbox/react-flushSync/hooks/useAbortSignallingTransition.js b/sandbox/react-flushSync/hooks/useAbortSignallingTransition.js index adb4478..45e433b 100644 --- a/sandbox/react-flushSync/hooks/useAbortSignallingTransition.js +++ b/sandbox/react-flushSync/hooks/useAbortSignallingTransition.js @@ -3,18 +3,22 @@ import useAwaitableTransition from "./useAwaitableTransition"; export default function useAbortSignallingTransition() { const [isPending, startAwaitableTransition] = useAwaitableTransition(); - const abortController = useRef(); + const abortController = useRef(new AbortController); const startAbortSignallingTransition = useCallback(async (callback) => { - abortController.current = new AbortController; + let prevAC = abortController.current; + let nextAC = new AbortController(); + abortController.current = nextAC; try { await startAwaitableTransition(callback); } catch(ex) { - abortController.current.abort(); + // abortController.current has already been updated by the time we catch, + // so use the previously saved `prevAC` value + prevAC.abort(); // throw ex; } }, [startAwaitableTransition]); - return [isPending, startAbortSignallingTransition, abortController.signal]; + return [isPending, startAbortSignallingTransition, abortController.current.signal]; }; \ No newline at end of file diff --git a/sandbox/soft-nav-test-dom-edit-append-tree/index.html b/sandbox/soft-nav-test-dom-edit-append-tree/index.html new file mode 100644 index 0000000..522e020 --- /dev/null +++ b/sandbox/soft-nav-test-dom-edit-append-tree/index.html @@ -0,0 +1,55 @@ + + + + + + +
Content
+ + + \ No newline at end of file diff --git a/sandbox/web-mightals.js/apps/web-vitals.js-experiment/index.html b/sandbox/web-vitals.js-experiment/index.html similarity index 100% rename from sandbox/web-mightals.js/apps/web-vitals.js-experiment/index.html rename to sandbox/web-vitals.js-experiment/index.html diff --git a/sandbox/web-mightals.js/apps/web-vitals.js-experiment/index.js b/sandbox/web-vitals.js-experiment/index.js similarity index 100% rename from sandbox/web-mightals.js/apps/web-vitals.js-experiment/index.js rename to sandbox/web-vitals.js-experiment/index.js