UNPKG

ember-source

Version:

A JavaScript framework for creating ambitious web applications

92 lines (88 loc) 2.69 kB
const HAS_SUPER_PATTERN = /\.(_super|call\(this|apply\(this)/; const fnToString = Function.prototype.toString; const checkHasSuper = (() => { let sourceAvailable = fnToString.call(function () { return this; }).indexOf('return this') > -1; if (sourceAvailable) { return function checkHasSuper(func) { return HAS_SUPER_PATTERN.test(fnToString.call(func)); }; } return function checkHasSuper() { return true; }; })(); const HAS_SUPER_MAP = new WeakMap(); const ROOT = Object.freeze(function () {}); HAS_SUPER_MAP.set(ROOT, false); function hasSuper(func) { let hasSuper = HAS_SUPER_MAP.get(func); if (hasSuper === undefined) { hasSuper = checkHasSuper(func); HAS_SUPER_MAP.set(func, hasSuper); } return hasSuper; } class ObserverListenerMeta { listeners = undefined; observers = undefined; } const OBSERVERS_LISTENERS_MAP = new WeakMap(); function createObserverListenerMetaFor(fn) { let meta = OBSERVERS_LISTENERS_MAP.get(fn); if (meta === undefined) { meta = new ObserverListenerMeta(); OBSERVERS_LISTENERS_MAP.set(fn, meta); } return meta; } function observerListenerMetaFor(fn) { return OBSERVERS_LISTENERS_MAP.get(fn); } function setObservers(func, observers) { let meta = createObserverListenerMetaFor(func); meta.observers = observers; } function setListeners(func, listeners) { let meta = createObserverListenerMetaFor(func); meta.listeners = listeners; } const IS_WRAPPED_FUNCTION_SET = new WeakSet(); /** Wraps the passed function so that `this._super` will point to the superFunc when the function is invoked. This is the primitive we use to implement calls to super. @private @method wrap @for Ember @param {Function} func The function to call @param {Function} superFunc The super function. @return {Function} wrapped function. */ function wrap(func, superFunc) { if (!hasSuper(func)) { return func; } // ensure an unwrapped super that calls _super is wrapped with a terminal _super if (!IS_WRAPPED_FUNCTION_SET.has(superFunc) && hasSuper(superFunc)) { return _wrap(func, _wrap(superFunc, ROOT)); } return _wrap(func, superFunc); } function _wrap(func, superFunc) { function superWrapper() { let orig = this._super; this._super = superFunc; let ret = func.apply(this, arguments); this._super = orig; return ret; } IS_WRAPPED_FUNCTION_SET.add(superWrapper); let meta = OBSERVERS_LISTENERS_MAP.get(func); if (meta !== undefined) { OBSERVERS_LISTENERS_MAP.set(superWrapper, meta); } return superWrapper; } export { ROOT as R, setListeners as a, checkHasSuper as c, observerListenerMetaFor as o, setObservers as s, wrap as w };