vasille-jsx
Version:
The first Developer eXperience Orientated front-end framework (JSX components)
167 lines (166 loc) • 4.52 kB
JavaScript
import { ArrayModel, Destroyable, MapModel, Reactive, SetModel } from "vasille";
import { ProxyReference, proxyObject } from "./objects.js";
const symbol = Symbol("proxy");
class Context extends Destroyable {
constructor() {
super(...arguments);
this.ctx = new Reactive({});
}
checkEnable(value) {
if (value && typeof value === "object" && value.constructor === Object) {
return this.enableObject(value);
}
return value;
}
checkDisable(value) {
if (value && typeof value === "object" && value.constructor === Object) {
this.disableObject(value);
}
}
enableObject(o) {
const ref = new ProxyReference(undefined);
o[symbol] = ref;
this.ctx.register(ref);
return proxyObject(o, ref);
}
disableObject(o) {
this.ctx.release(o[symbol]);
}
destroy() {
this.ctx.destroy();
}
}
export class ContextArray extends ArrayModel {
constructor(data) {
const ctx = new Context();
if (data instanceof Array) {
for (let i = 0; i < data.length; i++) {
data[i] = ctx.checkEnable(data[i]);
}
}
super(data);
this.ctx = ctx;
}
fill(value, start, end) {
value = this.ctx.checkEnable(value);
return super.fill(value, start, end);
}
pop() {
const value = super.pop();
this.ctx.checkDisable(value);
return value;
}
push(...items) {
for (let i = 0; i < items.length; i++) {
items[i] = this.ctx.checkEnable(items[i]);
}
return super.push(...items);
}
shift() {
const value = super.shift();
this.ctx.checkDisable(value);
return value;
}
splice(start, deleteCount, ...items) {
for (let i = 0; i < items.length; i++) {
items[i] = this.ctx.checkEnable(items[i]);
}
const removed = super.splice(start, deleteCount, ...items);
for (const item of removed) {
this.ctx.checkDisable(removed);
}
return removed;
}
unshift(...items) {
for (let i = 0; i < items.length; i++) {
items[i] = this.ctx.checkEnable(items[i]);
}
return super.unshift(...items);
}
replace(at, with_) {
this.ctx.checkDisable(this[at]);
with_ = this.ctx.checkEnable(with_);
return super.replace(at, with_);
}
destroy() {
super.destroy();
this.ctx.destroy();
}
}
export class ContextMap extends MapModel {
constructor(map) {
const ctx = new Context();
/* istanbul ignore else */
if (map) {
for (const item of map) {
item[1] = ctx.checkEnable(item[1]);
}
}
super(map);
this.ctx = ctx;
}
clear() {
for (const value of this.values()) {
this.ctx.checkDisable(value);
}
super.clear();
}
delete(key) {
this.ctx.checkDisable(this.get(key));
return super.delete(key);
}
set(key, value) {
this.ctx.checkDisable(this.get(key));
value = this.ctx.checkEnable(value);
return super.set(key, value);
}
destroy() {
super.destroy();
this.ctx.destroy();
}
}
export class ContextSet extends SetModel {
constructor(set) {
const ctx = new Context();
const real = new Map();
/* istanbul ignore else */
if (set) {
for (let i = 0; i < set.length; i++) {
real.set(set[i], (set[i] = ctx.checkEnable(set[i])));
}
}
super(set);
this.ctx = ctx;
this.real = real;
}
add(value) {
if (!this.real.has(value)) {
this.real.set(value, (value = this.ctx.checkEnable(value)));
return super.add(value);
}
return this;
}
has(value) {
return this.real.has(value);
}
clear() {
for (const item of this) {
this.ctx.checkDisable(item);
}
super.clear();
this.real.clear();
}
delete(value) {
const real = this.real.get(value);
if (real !== undefined) {
this.ctx.checkDisable(value);
this.real.delete(value);
return super.delete(real);
}
return false;
}
destroy() {
super.destroy();
this.ctx.destroy();
}
}