79 lines
1.7 KiB
JavaScript
79 lines
1.7 KiB
JavaScript
export function PropertyMixin(key, meta = {}) {
|
|
|
|
if (!meta || 'object' !== typeof meta) {
|
|
throw new TypeError(
|
|
`Expected meta for Property(${
|
|
key
|
|
}) to be object. ${
|
|
JSON.stringify(meta)
|
|
} given.`
|
|
);
|
|
}
|
|
|
|
return (Superclass) => {
|
|
|
|
if (Superclass.prototype[key]) {
|
|
throw new TypeError(`can't redefine Avocado property "${key}"`);
|
|
}
|
|
|
|
if ('identity' === meta.transformProperty) {
|
|
meta.transformProperty = (key) => key;
|
|
}
|
|
else if (!meta.transformProperty) {
|
|
meta.transformProperty = (key) => `${key}_PRIVATE_PROPERTY`;
|
|
}
|
|
|
|
meta.emit = meta.emit || function(...args) {
|
|
if (this.emit) {
|
|
this.emit(...args);
|
|
}
|
|
}
|
|
|
|
meta.eq = meta.eq || function (l, r) {
|
|
return l === r;
|
|
}
|
|
|
|
meta.get = meta.get || function(value) {
|
|
return this[meta.transformProperty(key)];
|
|
}
|
|
|
|
meta.set = meta.set || function(value) {
|
|
this[meta.transformProperty(key)] = value;
|
|
}
|
|
|
|
let metaDefault;
|
|
if (null === meta.default) {
|
|
metaDefault = null;
|
|
}
|
|
else if (undefined === meta.default) {
|
|
metaDefault = undefined;
|
|
}
|
|
else {
|
|
metaDefault = JSON.parse(JSON.stringify(meta.default));
|
|
}
|
|
|
|
return class Property extends Superclass {
|
|
|
|
constructor(...args) {
|
|
super(...args);
|
|
if (undefined !== metaDefault) {
|
|
meta.set.call(this, metaDefault);
|
|
}
|
|
}
|
|
|
|
get [key]() {
|
|
return meta.get.call(this);
|
|
}
|
|
|
|
set [key](value) {
|
|
const old = meta.get.call(this);
|
|
meta.set.call(this, value);
|
|
if (meta.track && meta.emit && !meta.eq.call(this, old, value)) {
|
|
meta.emit.call(this, `${key}Changed`, old, value);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|