ember-material-icons
Version:
Google Material icons for your ember-cli app
199 lines (159 loc) • 4.96 kB
text/typescript
import { ComputedReferenceBlueprint, Meta } from '@glimmer/object-reference';
import { EMPTY_CACHE, ClassMeta } from './object';
import { Descriptor, Blueprint } from './mixin';
export interface ComputedGetCallback {
(): any;
}
export interface LegacyComputedGetCallback {
(key: string): any;
}
export interface ComputedSetCallback {
(val: any);
}
export interface LegacyComputedSetCallback {
(key: string, val: any);
}
export interface ComputedDescriptor {
get?: ComputedGetCallback | LegacyComputedGetCallback;
set?: ComputedSetCallback | LegacyComputedSetCallback;
}
type ComputedArgument = ComputedGetCallback | ComputedDescriptor;
export class ComputedBlueprint extends Blueprint {
private accessor: ComputedDescriptor;
private deps: string[][];
private metadata: Object = {};
constructor(accessor: ComputedDescriptor, deps: string[][] = []) {
super();
this.accessor = accessor;
this.deps = deps;
}
descriptor(target: Object, key: string, classMeta: ClassMeta): Descriptor {
classMeta.addReferenceTypeFor(key, ComputedReferenceBlueprint(key, this.deps));
classMeta.addPropertyMetadata(key, this.metadata);
classMeta.addSlotFor(key);
return new Computed(this.accessor);
}
property(...paths: string[]) {
this.deps = paths.map(d => d.split('.'));
return this;
}
meta(object: Object) {
this.metadata = object;
return this;
}
volatile() {
return this;
}
}
class Computed implements Descriptor {
enumerable: boolean;
configurable: boolean;
private accessor: ComputedDescriptor;
"5d90f84f-908e-4a42-9749-3d0f523c262c" = true;
constructor(accessor: ComputedDescriptor) {
this.accessor = accessor;
}
define(prototype: Object, key: string, home: Object) {
Object.defineProperty(prototype, key, wrapAccessor(home, key, this.accessor));
}
}
function wrapAccessor(home: Object, accessorName: string, _desc: ComputedDescriptor): PropertyDescriptor {
let superDesc = getPropertyDescriptor(home, accessorName);
let originalGet: ComputedGetCallback;
let originalSet: ComputedSetCallback;
let desc: PropertyDescriptor = {
enumerable: true,
configurable: true,
};
if (_desc.get && _desc.get.length > 0) {
originalGet = function() { return _desc.get.call(this, accessorName); };
} else {
originalGet = <ComputedGetCallback>_desc.get;
}
if (_desc.set && _desc.set.length > 1) {
originalSet = function(value) {
return _desc.set.call(this, accessorName, value);
};
} else {
originalSet = <ComputedGetCallback>_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(desc: ComputedDescriptor): ComputedBlueprint;
export function computed(getter: ComputedGetCallback | LegacyComputedGetCallback): ComputedBlueprint;
export function computed(...args): ComputedBlueprint;
export function computed(...args) {
let last: ComputedArgument = args.pop();
let deps = args;
if (typeof last === 'function') {
return new ComputedBlueprint({
get: <ComputedGetCallback | LegacyComputedGetCallback>last
}).property(...deps);
} else if (typeof last === 'object') {
return new ComputedBlueprint(<ComputedDescriptor>last).property(...deps);
} else {
throw new TypeError("computed expects a function or an object as last argument");
}
}
export function observer(...args) {
}