More code documentation

This commit is contained in:
Talia 2024-06-24 13:04:42 +02:00
parent aa27cc0b34
commit 6088b976d8

View file

@ -115,7 +115,7 @@ export class Observable extends EventTarget {
/** /**
* @param {string} prop * @param {string} prop
* @param {function} callback * @param {function(any):void} callback
*/ */
subscribe(prop, callback) { subscribe(prop, callback) {
const controller = new AbortController() const controller = new AbortController()
@ -162,20 +162,27 @@ export class Observable extends EventTarget {
} }
export class ObservableObject extends Observable { export class ObservableObject extends Observable {
#shallow
constructor(target={}, {shallow, ...options}={}) { /**
* @param {Object} target
* @param {Object} options
*/
constructor(target={}, {shallow=true, ...options}={}) {
super(options) super(options)
this.#shallow = !!shallow Object.defineProperty(this, "target", target)
this[target] = target
this.values = new Proxy(target, { this.values = new Proxy(target, {
/**
* @param {Object} target
* @param {String} prop
* @param {any} value
*/
set: (target, prop, value) => { set: (target, prop, value) => {
const old = target[prop] const old = target[prop]
if (old === value) { if (old === value) {
return true return true
} else { } else {
if (this.enqueue(prop, old, value)) { if (this.enqueue(prop, old, value)) {
if (!this.#shallow) { if (!shallow) {
if (old instanceof Observable) this.disown(prop, old) if (old instanceof Observable) this.disown(prop, old)
if (value instanceof Observable) this.adopt(prop, value) if (value instanceof Observable) this.adopt(prop, value)
} }
@ -186,17 +193,26 @@ export class ObservableObject extends Observable {
} }
} }
}, },
/**
* @param {Object} target
* @param {String} prop
*/
get: (target, prop) => target[prop], get: (target, prop) => target[prop],
}) })
} }
proxy(prop, {get, set, ...options}={}) { /**
* @param {string} prop
* @param {Object} options
*/
proxy(prop, {get=undefined, set=undefined, ...options}={}) {
const proxy = new ProxiedObservableValue(this, prop, {values: this.values, ...options}) const proxy = new ProxiedObservableValue(this, prop, {values: this.values, ...options})
if (get) proxy.get = get if (get) proxy.get = get
if (set) proxy.set = set if (set) proxy.set = set
return proxy return proxy
} }
/** @param {Change[]} changes */
emit(...changes) { emit(...changes) {
this.dispatchEvent(new MultiChangeEvent(...changes)) this.dispatchEvent(new MultiChangeEvent(...changes))
} }
@ -204,6 +220,10 @@ export class ObservableObject extends Observable {
/** @type Map<Observable, Map<String, Function>> */ /** @type Map<Observable, Map<String, Function>> */
#nested = new Map() #nested = new Map()
/** Adopts an obsercable to be notified of its changes
* @param {string} prop
* @param {Observable} observable
*/
adopt(prop, observable) { adopt(prop, observable) {
let handlers = this.#nested.get(observable) let handlers = this.#nested.get(observable)
if (!handlers) { if (!handlers) {
@ -218,6 +238,10 @@ export class ObservableObject extends Observable {
observable.addEventListener("change", handler, {signal: this.signal}) observable.addEventListener("change", handler, {signal: this.signal})
} }
/** Undoes the adoption of a nested observable, cancelling the associated event hook
* @param {string} prop
* @param {Observable} observable
*/
disown(prop, observable) { disown(prop, observable) {
const handlers = this.#nested.get(observable) const handlers = this.#nested.get(observable)
const handler = handlers.get(prop) const handler = handlers.get(prop)
@ -232,6 +256,10 @@ export class ObservableObject extends Observable {
export class ObservableValue extends Observable { export class ObservableValue extends Observable {
#value #value
/**
* @param {any} value
* @param {Object} options
*/
constructor(value, options) { constructor(value, options) {
super(options) super(options)
this.#value = value this.#value = value
@ -245,26 +273,32 @@ export class ObservableValue extends Observable {
} }
/** /**
* @param {function(any):undefined} callback * @param {string} prop
* @param {function(any):undefined} _callback * @param {function(any):void} callback
*/ */
subscribe(callback, _callback) { subscribe(prop, callback) {
this.constructor.prototype.subscribe.call(this, "value", callback) // @ts-ignore
if (typeof(prop) == "function") [prop, callback] = ["value", prop]
this.constructor.prototype.subscribe.call(this, prop, callback)
} }
/** @param {Change[]} changes */
emit(...changes) { emit(...changes) {
this.dispatchEvent(new ValueChangeEvent(...changes)) this.dispatchEvent(new ValueChangeEvent(...changes))
} }
} }
class ProxiedObservableValue extends ObservableValue { class ProxiedObservableValue extends ObservableValue {
#backend
#values #values
#prop #prop
/**
* @param {Observable} backend
* @param {string} prop
*/
constructor(backend, prop, {values=backend, ...options}={}) { constructor(backend, prop, {values=backend, ...options}={}) {
super(options) super(options)
this.#backend = backend
this.#values = values this.#values = values
this.#prop = prop this.#prop = prop