src/TransientProperty.js
import { assert } from "akutils";
import ObjectProperty from "./ObjectProperty";
import PrimitiveProperty from "./PrimitiveProperty";
import Shadow from "./Shadow";
import StateType from "./StateType";
import appDebug, { TransientKey as DebugKey } from "./debug";
const debug = appDebug(DebugKey);
const _data = "data";
const _desc = Symbol('desc');
const _id = "id";
const _lockId = Symbol('lockId');
const _locks = Symbol('locks');
const _subscribers = Symbol('subscribers');
const _trans = Symbol('trans');
const _transId = Symbol('id');
//const PrimaryLockName = "__primary__";
var nextLockId = 1;
export class TransientLock {
constructor(id, desc, trans) {
this[_lockId] = id;
this[_desc] = desc;
this[_trans] = trans;
}
desc() {
return this[_desc];
}
id() {
return this[_lockId];
}
is(desc) {
return this[_desc] === desc;
}
release() {
this[_trans]._removeLock(this);
}
trans() {
return this[_trans];
}
}
export class TransientShadow extends Shadow {
delete() {
const transRoot = this.$$().parent()._();
transRoot.delete(this.id);
}
isLocked() {
return this.$$().isLocked();
}
lock(desc) {
return this.$$().lock(desc);
}
}
/*
*/
export default class TransientProperty extends ObjectProperty {
constructor(id, property) {
super();
this._keyed.addProperty(_data, property);
this._keyed.set(_id, id);
this.setShadowClass(TransientShadow);
this[_transId] = id;
this[_locks] = [];
debug( d => d(`TransientProperty created: id=${ id }`) );
}
propertyWillUnshadow() {
delete this[_locks];
debug( d => d(`propertyWillUnshadow(): id=${ this[_transId] }`) );
}
get id() {
return this[_transId];
}
data() {
const transObj = this._();
return transObj && transObj.data;
}
isLocked() {
return this[_locks] && this[_locks].length > 0;
}
lock(desc=`lock:${nextLockId}`) {
return this._addLock(new TransientLock(nextLockId++, desc, this));
}
_removeLock(lock) {
if (!this[_locks]) { return }
this[_locks] = this[_locks].filter( l => l !== lock );
debug( d => d(`_removeLock(): id=${ this[_transId] }, locked=${ this.isLocked() }, desc=${ lock.desc() }`) );
}
_addLock(lock) {
assert( a => a.is(lock.trans() === this, "Lock transient object mismatch") );
if (!this[_locks]) { return null }
this[_locks].push(lock);
debug( d => d(`_addLock(): id=${ this[_transId] }, desc=${ lock.desc() }`) );
return lock;
}
}
StateType.defineType(TransientProperty, spec => {
spec.initialState({})
.properties({
[_id]: PrimitiveProperty.type,
})
.autoshadowOff
.readonly
.typeName("TransientProperty");
});