magic objects

proxied-state-each-blocks
Rich Harris 9 months ago committed by Dominic Gannaway
parent 2fa06447cf
commit fa8ca04d9c

@ -0,0 +1,75 @@
import { effect_active, get, set, increment, source } from './runtime.js';
/**
* @template T
* @param {T} value
* @returns {T}
*/
export function magic(value) {
if (value && typeof value === 'object') {
if (Array.isArray(value)) {
// TODO
}
return object(value);
}
return value;
}
/**
* @template {Record<string | symbol, any>} T
* @param {T} value
* @returns {T}
*/
function object(value) {
/** @type {Map<string | symbol, any>} */
const sources = new Map();
let version = source(0);
return new Proxy(value, {
get(target, prop, receiver) {
let s = sources.get(prop);
if (effect_active() && !s) {
s = source(magic(target[prop]));
sources.set(prop, s);
}
let value = s ? get(s) : target[prop];
if (typeof value === 'function') {
return (...args) => {
return value.apply(receiver, args);
};
}
return value;
},
set(target, prop, value) {
const s = sources.get(prop);
if (s) set(s, magic(value));
if (!(prop in target)) increment(version);
target[prop] = value;
return true;
},
deleteProperty(target, prop) {
const s = sources.get(prop);
if (s) set(s, undefined);
if (prop in target) increment(version);
return delete target[prop];
},
has(target, prop) {
get(version);
return Reflect.has(target, prop);
},
ownKeys(target) {
get(version);
return Reflect.ownKeys(target);
}
});
}

@ -56,3 +56,5 @@ export {
} from './client/operations.js';
export { raf } from './client/timing.js';
export { magic } from './client/magic.js';

@ -255,4 +255,12 @@ export function afterUpdate(fn) {
// TODO bring implementations in here
// (except probably untrack — do we want to expose that, if there's also a rune?)
export { flushSync, createRoot, mount, tick, untrack, onDestroy } from '../internal/index.js';
export {
flushSync,
createRoot,
mount,
tick,
untrack,
onDestroy,
magic
} from '../internal/index.js';

Loading…
Cancel
Save