reactronic
Version:
Reactronic - Transactional Reactive State Management
92 lines (91 loc) • 2.66 kB
JavaScript
import { misuse } from "./util/Dbg.js";
import { runTransactional, runNonReactive } from "./System.js";
export function refs(owner) {
return new Proxy(owner, RefGettingProxy);
}
export function toggleRefs(owner) {
return new Proxy(owner, BoolRefGettingProxy);
}
export function customToggleRefs(owner, value1, value2) {
const handler = new CustomToggleRefGettingProxy(value1, value2);
return new Proxy(owner, handler);
}
export class Ref {
constructor(owner, name, index = -1) {
this.owner = owner;
this.name = name;
this.index = index;
}
get variable() {
if (this.index < 0)
return this.owner[this.name];
else
return this.owner[this.name][this.index];
}
set variable(value) {
if (this.index < 0)
this.owner[this.name] = value;
else
this.owner[this.name][this.index] = value;
}
nonReactively() {
return runNonReactive(() => this.variable);
}
signalling() {
return this.variable;
}
nonSignalling() {
throw misuse("not implemented");
}
static sameRefs(v1, v2) {
return v1.owner === v2.owner && v1.name === v2.name && v1.index === v2.index;
}
static similarRefs(v1, v2) {
return v1.owner.constructor === v2.owner.constructor && v1.name === v2.name && v1.index === v2.index;
}
}
export class ToggleRef extends Ref {
constructor(owner, name, valueOn, valueOff) {
super(owner, name);
this.valueOn = valueOn;
this.valueOff = valueOff;
}
toggle() {
const o = this.owner;
const p = this.name;
runTransactional({ hint: `toggle ${o.constructor.name}.${p}` }, () => {
const v = o[p];
const isOn = v === this.valueOn || (v instanceof Ref && this.valueOn instanceof Ref &&
Ref.sameRefs(v, this.valueOn));
if (!isOn)
o[p] = this.valueOn;
else
o[p] = this.valueOff;
});
}
}
const RefGettingProxy = {
get: (obj, prop) => {
return new Ref(obj, prop);
},
};
const BoolRefGettingProxy = {
get: (obj, prop) => {
return new ToggleRef(obj, prop, true, false);
},
};
class CustomToggleRefGettingProxy {
constructor(value1, value2) {
this.value1 = value1;
this.value2 = value2;
}
get(obj, prop) {
return new ToggleRef(obj, prop, this.value1, this.value2);
}
}
Object.defineProperty(Object.prototype, "$$", {
configurable: false, enumerable: false,
get() {
return new Proxy(this, RefGettingProxy);
},
});