UNPKG

ember-legacy-class-transform

Version:
137 lines 4.1 kB
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) {}