{"version":3,"file":"mixwith.js","names":["System","register","a","MixinBuilder","c","d","e","f","g","h","i","j","k","l","m","n","o","p","setters","execute","_appliedMixin","_wrappedMixin","unwrap","wrapper","apply","superclass","mixin","application","prototype","isApplicationOf","proto","hasOwnProperty","hasMixin","Object","getPrototypeOf","wrap","setPrototypeOf","_cachedApplications","Cached","cachedApplications","Map","get","set","DeDupe","HasInstance","Symbol","hasInstance","defineProperty","value","BareMixin","s","Mixin","constructor","with","arguments","length","mixins","Array","reduce","mix"],"sources":["core/mixwith.js"],"sourcesContent":["'use strict';\n\n// used by apply() and isApplicationOf()\nconst _appliedMixin = '__mixwith_appliedMixin';\n\n/**\n * A function that returns a subclass of its argument.\n *\n * @example\n * const M = (superclass) => class extends superclass {\n * getMessage() {\n * return \"Hello\";\n * }\n * }\n *\n * @typedef {Function} MixinFunction\n * @param {Function} superclass\n * @return {Function} A subclass of `superclass`\n */\n\n// used by wrap() and unwrap()\nconst _wrappedMixin = '__mixwith_wrappedMixin';\n\n/**\n * Unwraps the function `wrapper` to return the original function wrapped by\n * one or more calls to `wrap`. Returns `wrapper` if it's not a wrapped\n * function.\n *\n * @function\n * @param {MixinFunction} wrapper A wrapped mixin produced by {@link wrap}\n * @return {MixinFunction} The originally wrapped mixin\n */\nexport const unwrap = wrapper => wrapper[_wrappedMixin] || wrapper;\n\n/**\n * Applies `mixin` to `superclass`.\n *\n * `apply` stores a reference from the mixin application to the unwrapped mixin\n * to make `isApplicationOf` and `hasMixin` work.\n *\n * This function is usefull for mixin wrappers that want to automatically enable\n * {@link hasMixin} support.\n *\n * @example\n * const Applier = (mixin) => wrap(mixin, (superclass) => apply(superclass, mixin));\n *\n * // M now works with `hasMixin` and `isApplicationOf`\n * const M = Applier((superclass) => class extends superclass {});\n *\n * class C extends M(Object) {}\n * let i = new C();\n * hasMixin(i, M); // true\n *\n * @function\n * @param {Function} superclass A class or constructor function\n * @param {MixinFunction} mixin The mixin to apply\n * @return {Function} A subclass of `superclass` produced by `mixin`\n */\nexport const apply = (superclass, mixin) => {\n const application = mixin(superclass);\n application.prototype[_appliedMixin] = unwrap(mixin);\n return application;\n};\n\n/**\n * Returns `true` iff `proto` is a prototype created by the application of\n * `mixin` to a superclass.\n *\n * `isApplicationOf` works by checking that `proto` has a reference to `mixin`\n * as created by `apply`.\n *\n * @function\n * @param {Object} proto A prototype object created by {@link apply}.\n * @param {MixinFunction} mixin A mixin function used with {@link apply}.\n * @return {boolean} whether `proto` is a prototype created by the application of\n * `mixin` to a superclass\n */\nexport const isApplicationOf = (proto, mixin) =>\n // eslint-disable-next-line\n proto.hasOwnProperty(_appliedMixin) && proto[_appliedMixin] === unwrap(mixin);\n\n/**\n * Returns `true` iff `o` has an application of `mixin` on its prototype\n * chain.\n *\n * @function\n * @param {Object} o An object\n * @param {MixinFunction} mixin A mixin applied with {@link apply}\n * @return {boolean} whether `o` has an application of `mixin` on its prototype\n * chain\n */\nexport const hasMixin = (o, mixin) => {\n while (o != null) {\n if (isApplicationOf(o, mixin)) {\n return true;\n }\n o = Object.getPrototypeOf(o);\n }\n return false;\n};\n\n/**\n * Sets up the function `mixin` to be wrapped by the function `wrapper`, while\n * allowing properties on `mixin` to be available via `wrapper`, and allowing\n * `wrapper` to be unwrapped to get to the original function.\n *\n * `wrap` does two things:\n * 1. Sets the prototype of `mixin` to `wrapper` so that properties set on\n * `mixin` inherited by `wrapper`.\n * 2. Sets a special property on `mixin` that points back to `mixin` so that\n * it can be retreived from `wrapper`\n *\n * @function\n * @param {MixinFunction} mixin A mixin function\n * @param {MixinFunction} wrapper A function that wraps {@link mixin}\n * @return {MixinFunction} `wrapper`\n */\nexport const wrap = (mixin, wrapper) => {\n Object.setPrototypeOf(wrapper, mixin);\n if (!mixin[_wrappedMixin]) {\n mixin[_wrappedMixin] = mixin;\n }\n return wrapper;\n};\n\nconst _cachedApplications = '__mixwith_cachedApplications';\n\n/**\n * Decorates `mixin` so that it caches its applications. When applied multiple\n * times to the same superclass, `mixin` will only create one subclass, memoize\n * it and return it for each application.\n *\n * Note: If `mixin` somehow stores properties its classes constructor (static\n * properties), or on its classes prototype, it will be shared across all\n * applications of `mixin` to a super class. It's reccomended that `mixin` only\n * access instance state.\n *\n * @function\n * @param {MixinFunction} mixin The mixin to wrap with caching behavior\n * @return {MixinFunction} a new mixin function\n */\nexport const Cached = mixin => wrap(mixin, (superclass) => {\n // Get or create a symbol used to look up a previous application of mixin\n // to the class. This symbol is unique per mixin definition, so a class will have N\n // applicationRefs if it has had N mixins applied to it. A mixin will have\n // exactly one _cachedApplicationRef used to store its applications.\n\n let cachedApplications = superclass[_cachedApplications];\n if (!cachedApplications) {\n superclass[_cachedApplications] = new Map();\n cachedApplications = superclass[_cachedApplications];\n }\n\n let application = cachedApplications.get(mixin);\n if (!application) {\n application = mixin(superclass);\n cachedApplications.set(mixin, application);\n }\n\n return application;\n});\n\n/**\n * Decorates `mixin` so that it only applies if it's not already on the\n * prototype chain.\n *\n * @function\n * @param {MixinFunction} mixin The mixin to wrap with deduplication behavior\n * @return {MixinFunction} a new mixin function\n */\nexport const DeDupe = mixin => wrap(mixin, superclass =>\n ((hasMixin(superclass.prototype, mixin))\n ? superclass\n : mixin(superclass)));\n\n/**\n * Adds [Symbol.hasInstance] (ES2015 custom instanceof support) to `mixin`.\n *\n * @function\n * @param {MixinFunction} mixin The mixin to add [Symbol.hasInstance] to\n * @return {MixinFunction} the given mixin function\n */\nexport const HasInstance = (mixin) => {\n if (Symbol && Symbol.hasInstance && !mixin[Symbol.hasInstance]) {\n Object.defineProperty(mixin, Symbol.hasInstance, {\n /**\n * Check if instance does already exists\n * @param {class} o -\n * @returns {boolean} -\n */\n value(o) {\n return hasMixin(o, mixin);\n },\n });\n }\n return mixin;\n};\n\n/**\n * A basic mixin decorator that applies the mixin with {@link apply} so that it\n * can be used with {@link isApplicationOf}, {@link hasMixin} and the other\n * mixin decorator functions.\n *\n * @function\n * @param {MixinFunction} mixin The mixin to wrap\n * @return {MixinFunction} a new mixin function\n */\nexport const BareMixin = mixin => wrap(mixin, s => apply(s, mixin));\n\n/**\n * Decorates a mixin function to add deduplication, application caching and\n * instanceof support.\n *\n * TODO: Mixin doesn't work as expected for components with applying multiple mixins because of caching.\n * Cached function is removed.\n *\n * @function\n * @param {MixinFunction} mixin The mixin to wrap\n * @return {MixinFunction} a new mixin function\n */\nexport const Mixin = mixin => DeDupe(BareMixin(mixin));\n\n/**\n * A fluent interface to apply a list of mixins to a superclass.\n *\n * ```javascript\n * class X extends mix(Object).with(A, B, C) {}\n * ```\n *\n * The mixins are applied in order to the superclass, so the prototype chain\n * will be: X->C'->B'->A'->Object.\n *\n * This is purely a convenience function. The above example is equivalent to:\n *\n * ```javascript\n * class X extends C(B(A(Object))) {}\n * ```\n */\nclass MixinBuilder {\n /**\n * @constructor\n * @param {function} superclass - Class that will be mixed with\n */\n constructor(superclass) {\n this.superclass = superclass || class { };\n }\n\n /**\n * Applies `mixins` in order to the superclass given to `mix()`.\n *\n * @param {Array.} mixins - mixins\n * @return {Function} a subclass of `superclass` with `mixins` applied\n */\n with(...mixins) {\n return mixins.reduce((c, m) => m(c), this.superclass);\n }\n}\n\nexport const mix = superclass => new MixinBuilder(superclass);\n"],"mappings":"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","ignoreList":[]}