rvx
Version:
A signal based rendering library
103 lines • 3.29 kB
JavaScript
import { $, batch, isTracking } from "../core/signals.js";
import { ProbeMap } from "./probes.js";
export function createReactiveArrayProxy(target, barrier) {
const length = $(target.length);
const indexProbes = new ProbeMap(i => target[i]);
return new Proxy(target, {
get(target, prop, recv) {
if (prop === "length") {
length.access();
return target.length;
}
const index = asCanonicalIndex(prop);
if (index !== undefined) {
indexProbes.access(index);
return barrier.wrap(target[index]);
}
if (Object.hasOwn(replacements, prop)) {
return replacements[prop];
}
return Reflect.get(target, prop, recv);
},
set(target, prop, value, recv) {
if (prop === "length") {
batch(() => {
const previous = target.length;
target.length = value;
for (let i = previous; i >= target.length; i--) {
indexProbes.update(i, undefined);
}
length.value = Number(value);
});
return true;
}
const index = asCanonicalIndex(prop);
if (index !== undefined) {
batch(() => {
value = barrier.unwrap(value);
target[index] = value;
indexProbes.update(index, value);
});
return true;
}
return Reflect.set(target, prop, value, recv);
},
has(target, prop) {
const cIndex = asCanonicalIndex(prop);
if (cIndex !== undefined) {
indexProbes.access(cIndex);
return cIndex in target;
}
return Reflect.has(target, prop);
},
deleteProperty(target, prop) {
const index = asCanonicalIndex(prop);
if (index !== undefined) {
batch(() => {
delete target[index];
indexProbes.update(index, undefined);
});
return true;
}
return Reflect.deleteProperty(target, prop);
},
ownKeys(target) {
if (isTracking()) {
length.access();
for (let i = 0; i < target.length; i++) {
indexProbes.access(i);
}
}
return Reflect.ownKeys(target);
},
});
}
const replacements = Object.create(null);
for (const key of [
"copyWithin",
"fill",
"pop",
"push",
"reverse",
"shift",
"sort",
"splice",
"unshift",
]) {
replacements[key] = function (...args) {
return batch(() => {
return Array.prototype[key].call(this, ...args);
});
};
}
function asCanonicalIndex(value) {
if (typeof value === "symbol") {
return undefined;
}
const index = Number(value);
if (Number.isSafeInteger(index) && index >= 0 && index <= 0xFFFFFFFF) {
return index;
}
return undefined;
}
//# sourceMappingURL=reactive-array-proxy.js.map