UNPKG

ember-cli-ajh

Version:

Command line tool for developing ambitious ember.js apps

145 lines (139 loc) 4.52 kB
'use strict'; var customError = require('es5-ext/error/custom') , defineLength = require('es5-ext/function/_define-length') , d = require('d') , ee = require('event-emitter').methods , resolveResolve = require('./resolve-resolve') , resolveNormalize = require('./resolve-normalize') , apply = Function.prototype.apply, call = Function.prototype.call , create = Object.create, hasOwnProperty = Object.prototype.hasOwnProperty , defineProperties = Object.defineProperties , on = ee.on, emit = ee.emit; module.exports = function (original, length, options) { var cache = create(null), conf, memLength, get, set, del, clear, extDel, normalizer , getListeners, setListeners, deleteListeners, memoized, resolve; if (length !== false) memLength = length; else if (isNaN(original.length)) memLength = 1; else memLength = original.length; if (options.normalizer) { normalizer = resolveNormalize(options.normalizer); get = normalizer.get; set = normalizer.set; del = normalizer.delete; clear = normalizer.clear; } if (options.resolvers != null) resolve = resolveResolve(options.resolvers); if (get) { memoized = defineLength(function (arg) { var id, result, args = arguments; if (resolve) args = resolve(args); id = get(args); if (id !== null) { if (hasOwnProperty.call(cache, id)) { if (getListeners) conf.emit('get', id, args, this); return cache[id]; } } if (args.length === 1) result = call.call(original, this, args[0]); else result = apply.call(original, this, args); if (id === null) { id = get(args); if (id !== null) throw customError("Circular invocation", 'CIRCULAR_INVOCATION'); id = set(args); } else if (hasOwnProperty.call(cache, id)) { throw customError("Circular invocation", 'CIRCULAR_INVOCATION'); } cache[id] = result; if (setListeners) conf.emit('set', id); return result; }, memLength); } else if (length === 0) { memoized = function () { var result; if (hasOwnProperty.call(cache, 'data')) { if (getListeners) conf.emit('get', 'data', arguments, this); return cache.data; } if (!arguments.length) result = call.call(original, this); else result = apply.call(original, this, arguments); if (hasOwnProperty.call(cache, 'data')) { throw customError("Circular invocation", 'CIRCULAR_INVOCATION'); } cache.data = result; if (setListeners) conf.emit('set', 'data'); return result; }; } else { memoized = function (arg) { var result, args = arguments, id; if (resolve) args = resolve(arguments); id = String(args[0]); if (hasOwnProperty.call(cache, id)) { if (getListeners) conf.emit('get', id, args, this); return cache[id]; } if (args.length === 1) result = call.call(original, this, args[0]); else result = apply.call(original, this, args); if (hasOwnProperty.call(cache, id)) { throw customError("Circular invocation", 'CIRCULAR_INVOCATION'); } cache[id] = result; if (setListeners) conf.emit('set', id); return result; }; } conf = { original: original, memoized: memoized, get: function (args) { if (resolve) args = resolve(args); if (get) return get(args); return String(args[0]); }, has: function (id) { return hasOwnProperty.call(cache, id); }, delete: function (id) { var result; if (!hasOwnProperty.call(cache, id)) return; if (del) del(id); result = cache[id]; delete cache[id]; if (deleteListeners) conf.emit('delete', id, result); }, clear: function () { var oldCache = cache; if (clear) clear(); cache = create(null); conf.emit('clear', oldCache); }, on: function (type, listener) { if (type === 'get') getListeners = true; else if (type === 'set') setListeners = true; else if (type === 'delete') deleteListeners = true; return on.call(this, type, listener); }, emit: emit, updateEnv: function () { original = conf.original; } }; if (get) { extDel = defineLength(function (arg) { var id, args = arguments; if (resolve) args = resolve(args); id = get(args); if (id === null) return; conf.delete(id); }, memLength); } else if (length === 0) { extDel = function () { return conf.delete('data'); }; } else { extDel = function (arg) { if (resolve) arg = resolve(arguments)[0]; return conf.delete(arg); }; } defineProperties(memoized, { __memoized__: d(true), delete: d(extDel), clear: d(conf.clear) }); return conf; };