@motion-core/motion-gpu
Version:
Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte, React, and Vue adapter entrypoints.
85 lines (84 loc) • 2.2 kB
JavaScript
//#region src/lib/core/current-value.ts
var NO_PENDING_ERROR = Symbol("motiongpu-current-no-error");
/**
* Creates a writable value with immediate subscription semantics.
* Accepted writes are delivered FIFO to a subscriber snapshot. `onChange` runs
* after that snapshot for each value, preserving the original callback order.
*/
function createCurrentWritable(initialValue, onChange) {
let current = initialValue;
let currentVersion = 0;
const subscribers = /* @__PURE__ */ new Set();
const deliveredVersions = /* @__PURE__ */ new Map();
const pendingValues = [];
let pendingIndex = 0;
let isFlushing = false;
const flush = () => {
if (isFlushing) return;
isFlushing = true;
let firstError = NO_PENDING_ERROR;
try {
while (pendingIndex < pendingValues.length) {
const { value, version } = pendingValues[pendingIndex];
pendingIndex += 1;
const snapshot = Array.from(subscribers);
for (const run of snapshot) {
if (!subscribers.has(run) || (deliveredVersions.get(run) ?? -1) >= version) continue;
deliveredVersions.set(run, version);
try {
run(value);
} catch (error) {
if (firstError === NO_PENDING_ERROR) firstError = error;
}
}
try {
onChange?.(value);
} catch (error) {
if (firstError === NO_PENDING_ERROR) firstError = error;
}
}
} finally {
pendingValues.length = 0;
pendingIndex = 0;
isFlushing = false;
}
if (firstError !== NO_PENDING_ERROR) throw firstError;
};
const set = (value) => {
if (Object.is(current, value)) return;
current = value;
currentVersion += 1;
pendingValues.push({
value,
version: currentVersion
});
flush();
};
return {
get current() {
return current;
},
subscribe(run) {
subscribers.add(run);
deliveredVersions.set(run, currentVersion);
try {
run(current);
} catch (error) {
subscribers.delete(run);
deliveredVersions.delete(run);
throw error;
}
return () => {
subscribers.delete(run);
deliveredVersions.delete(run);
};
},
set,
update(updater) {
set(updater(current));
}
};
}
//#endregion
export { createCurrentWritable };
//# sourceMappingURL=current-value.js.map