avocado-old/packages/mixins/property.js

77 lines
1.7 KiB
JavaScript
Raw Normal View History

2019-03-17 23:45:48 -05:00
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.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));
}
class Property extends Superclass {
constructor(...args) {
super(...args);
2019-03-17 23:45:48 -05:00
if (undefined !== metaDefault) {
meta.set.call(this, metaDefault);
}
}
}
Object.defineProperty(Property.prototype, key, {
enumerable: true,
get: function() {
return meta.get.call(this);
},
set: function (value) {
const old = meta.get.call(this);
meta.set.call(this, value);
if (this.emit && !meta.eq.call(this, old, value)) {
this.emit(`${key}Changed`, old, value)
}
},
});
return Property;
}
}