ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
137 lines • 4.1 kB
JavaScript
import { ComputedReferenceBlueprint, Meta } from '@glimmer/object-reference';
import { EMPTY_CACHE } from './object';
import { Blueprint } from './mixin';
export class ComputedBlueprint extends Blueprint {
constructor(accessor, deps = []) {
super();
this.metadata = {};
this.accessor = accessor;
this.deps = deps;
}
descriptor(_target, key, classMeta) {
classMeta.addReferenceTypeFor(key, ComputedReferenceBlueprint(key, this.deps));
classMeta.addPropertyMetadata(key, this.metadata);
classMeta.addSlotFor(key);
return new Computed(this.accessor);
}
property(...paths) {
this.deps = paths.map(d => d.split('.'));
return this;
}
meta(object) {
this.metadata = object;
return this;
}
volatile() {
return this;
}
}
class Computed {
constructor(accessor) {
this["5d90f84f-908e-4a42-9749-3d0f523c262c"] = true;
this.accessor = accessor;
}
define(prototype, key, home) {
Object.defineProperty(prototype, key, wrapAccessor(home, key, this.accessor));
}
}
function wrapAccessor(home, accessorName, _desc) {
let superDesc = getPropertyDescriptor(home, accessorName);
let originalGet;
let originalSet;
let desc = {
enumerable: true,
configurable: true
};
let get = _desc.get;
if (get && get.length > 0) {
originalGet = function () {
return get.call(this, accessorName);
};
} else {
originalGet = _desc.get;
}
let set = _desc.set;
if (set && set.length > 1) {
originalSet = function (value) {
return set.call(this, accessorName, value);
};
} else {
originalSet = _desc.set;
}
let cacheGet = function () {
if (Meta.exists(this)) {
let slot = Meta.for(this).getSlots()[accessorName];
if (slot !== EMPTY_CACHE) return slot;
}
return originalGet.call(this);
};
let cacheSet;
if (originalSet) {
cacheSet = function (value) {
let meta = Meta.for(this);
let slots = meta.getSlots();
let ret = originalSet.call(this, value);
if (ret !== undefined) {
slots[accessorName] = ret;
}
};
} else {
cacheSet = function (value) {
let meta = Meta.for(this);
let slots = meta.getSlots();
if (value !== undefined) slots[accessorName] = value;
};
}
if (!superDesc || 'value' in superDesc) {
desc.get = cacheGet;
desc.set = cacheSet;
return desc;
}
desc.get = function () {
let lastSuper = this._super;
this._super = function () {
return superDesc.get.call(this);
};
try {
return cacheGet.call(this);
} finally {
this._super = lastSuper;
}
};
desc.set = function (val) {
let lastSuper = this._super;
this._super = function () {
return superDesc.set.call(this, val);
};
try {
return cacheSet.call(this, val);
} finally {
this._super = lastSuper;
}
};
return desc;
}
function getPropertyDescriptor(subject, name) {
let pd = Object.getOwnPropertyDescriptor(subject, name);
let proto = Object.getPrototypeOf(subject);
while (typeof pd === 'undefined' && proto !== null) {
pd = Object.getOwnPropertyDescriptor(proto, name);
proto = Object.getPrototypeOf(proto);
}
return pd;
}
export function computed(...args) {
let last = args.pop();
let deps = args;
if (typeof last === 'function') {
return new ComputedBlueprint({
get: last
}).property(...deps);
} else if (typeof last === 'object') {
return new ComputedBlueprint(last).property(...deps);
} else {
throw new TypeError("computed expects a function or an object as last argument");
}
}
export function observer(..._args) {}