UNPKG

infamous

Version:

A CSS3D/WebGL UI library.

108 lines (91 loc) 3.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Mixin; exports.WithDefault = WithDefault; exports.Cached = Cached; exports.HasInstance = HasInstance; exports.ApplyDefault = ApplyDefault; exports.Dedupe = Dedupe; var _lowclass = _interopRequireDefault(require("lowclass")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function Mixin(factory, Default) { factory = Cached(factory); factory = HasInstance(factory); factory = Dedupe(factory); factory = WithDefault(factory, Default || (0, _lowclass.default)()); factory = ApplyDefault(factory); return factory(); } function WithDefault(classFactory, Default) { return Base => { Base = Base || Default; return classFactory(Base); }; } function Cached(classFactory) { const classCache = new WeakMap(); return Base => { let Class = classCache.get(Base); if (!Class) { classCache.set(Base, Class = classFactory(Base)); } return Class; }; } function HasInstance(classFactory) { let instanceofSymbol; return Base => { const Class = classFactory(Base); if (typeof Symbol === 'undefined' || !Symbol.hasInstance) return Class; if (Object.getOwnPropertySymbols(Class).includes(Symbol.hasInstance)) return Class; if (!instanceofSymbol) instanceofSymbol = Symbol('instanceofSymbol'); Class[instanceofSymbol] = true; Object.defineProperty(Class, Symbol.hasInstance, { value: function (obj) { // we do this check because a subclass of `Class` may not have // it's own `[Symbol.hasInstance]()` method, therefore `this` // will be the subclass, not this `Class`, when the prototype // lookup on the subclass finds the `[Symbol.hasInstance]()` // method of this `Class`. In this case, we don't wsnt to run // our logic here, so we delegate to the super class of this // `Class` to take over with the instanceof check. In many // cases, the super class `[Symbol.hasInstance]()` method will // be `Function.prototype[Symbol.hasInstance]` which will // perform the standard check. if (this !== Class) // This is effectively a `super` call. return Object.getPrototypeOf(Class)[Symbol.hasInstance].call(this, obj); let currentProto = obj; while (currentProto) { const descriptor = Object.getOwnPropertyDescriptor(currentProto, "constructor"); if (descriptor && descriptor.value && descriptor.value.hasOwnProperty(instanceofSymbol)) return true; currentProto = Object.getPrototypeOf(currentProto); } return false; } }); return Class; }; } // requires WithDefault or a classFactory that can accept no args function ApplyDefault(classFactory) { const DefaultClass = classFactory(); DefaultClass.mixin = classFactory; return classFactory; } // requires ApplyDefault function Dedupe(classFactory) { const map = new WeakMap(); return Base => { if (hasMixin(Base, classFactory, map)) return Base; const Class = classFactory(Base); map.set(Class, classFactory); return Class; }; } function hasMixin(Class, mixin, map) { while (Class) { if (map.get(Class) === mixin) return true; Class = Class.__proto__; } return false; }