UNPKG

bloom-layout

Version:
290 lines (232 loc) 9.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); exports.default = createClassProxy; var _find = require('lodash/find'); var _find2 = _interopRequireDefault(_find); var _createPrototypeProxy = require('./createPrototypeProxy'); var _createPrototypeProxy2 = _interopRequireDefault(_createPrototypeProxy); var _bindAutoBindMethods = require('./bindAutoBindMethods'); var _bindAutoBindMethods2 = _interopRequireDefault(_bindAutoBindMethods); var _deleteUnknownAutoBindMethods = require('./deleteUnknownAutoBindMethods'); var _deleteUnknownAutoBindMethods2 = _interopRequireDefault(_deleteUnknownAutoBindMethods); var _supportsProtoAssignment = require('./supportsProtoAssignment'); var _supportsProtoAssignment2 = _interopRequireDefault(_supportsProtoAssignment); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var RESERVED_STATICS = ['length', 'displayName', 'name', 'arguments', 'caller', 'prototype', 'toString']; function isEqualDescriptor(a, b) { if (!a && !b) { return true; } if (!a || !b) { return false; } for (var key in a) { if (a[key] !== b[key]) { return false; } } return true; } function getDisplayName(Component) { var displayName = Component.displayName || Component.name; return displayName && displayName !== 'ReactComponent' ? displayName : 'Unknown'; } // This was originally a WeakMap but we had issues with React Native: // https://github.com/gaearon/react-proxy/issues/50#issuecomment-192928066 var allProxies = []; function findProxy(Component) { var pair = (0, _find2.default)(allProxies, function (_ref) { var _ref2 = _slicedToArray(_ref, 1); var key = _ref2[0]; return key === Component; }); return pair ? pair[1] : null; } function addProxy(Component, proxy) { allProxies.push([Component, proxy]); } function proxyClass(InitialComponent) { // Prevent double wrapping. // Given a proxy class, return the existing proxy managing it. var existingProxy = findProxy(InitialComponent); if (existingProxy) { return existingProxy; } var CurrentComponent = undefined; var ProxyComponent = undefined; var savedDescriptors = {}; function instantiate(factory, context, params) { var component = factory(); try { return component.apply(context, params); } catch (err) { (function () { // Native ES6 class instantiation var instance = new (Function.prototype.bind.apply(component, [null].concat(_toConsumableArray(params))))(); Object.keys(instance).forEach(function (key) { if (RESERVED_STATICS.indexOf(key) > -1) { return; } context[key] = instance[key]; }); })(); } } var displayName = getDisplayName(InitialComponent); try { // Create a proxy constructor with matching name ProxyComponent = new Function('factory', 'instantiate', 'return function ' + displayName + '() {\n return instantiate(factory, this, arguments);\n }')(function () { return CurrentComponent; }, instantiate); } catch (err) { // Some environments may forbid dynamic evaluation ProxyComponent = function ProxyComponent() { return instantiate(function () { return CurrentComponent; }, this, arguments); }; } try { Object.defineProperty(ProxyComponent, 'name', { value: displayName }); } catch (err) {} // Proxy toString() to the current constructor ProxyComponent.toString = function toString() { return CurrentComponent.toString(); }; var prototypeProxy = undefined; if (InitialComponent.prototype && InitialComponent.prototype.isReactComponent) { // Point proxy constructor to the proxy prototype prototypeProxy = (0, _createPrototypeProxy2.default)(); ProxyComponent.prototype = prototypeProxy.get(); } function update(NextComponent) { if (typeof NextComponent !== 'function') { throw new Error('Expected a constructor.'); } if (NextComponent === CurrentComponent) { return; } // Prevent proxy cycles var existingProxy = findProxy(NextComponent); if (existingProxy) { return update(existingProxy.__getCurrent()); } // Save the next constructor so we call it var PreviousComponent = CurrentComponent; CurrentComponent = NextComponent; // Try to infer displayName displayName = getDisplayName(NextComponent); ProxyComponent.displayName = displayName; try { Object.defineProperty(ProxyComponent, 'name', { value: displayName }); } catch (err) {} // Set up the same prototype for inherited statics ProxyComponent.__proto__ = NextComponent.__proto__; // Copy over static methods and properties added at runtime if (PreviousComponent) { Object.getOwnPropertyNames(PreviousComponent).forEach(function (key) { if (RESERVED_STATICS.indexOf(key) > -1) { return; } var prevDescriptor = Object.getOwnPropertyDescriptor(PreviousComponent, key); var savedDescriptor = savedDescriptors[key]; if (!isEqualDescriptor(prevDescriptor, savedDescriptor)) { Object.defineProperty(NextComponent, key, prevDescriptor); } }); } // Copy newly defined static methods and properties Object.getOwnPropertyNames(NextComponent).forEach(function (key) { if (RESERVED_STATICS.indexOf(key) > -1) { return; } var prevDescriptor = PreviousComponent && Object.getOwnPropertyDescriptor(PreviousComponent, key); var savedDescriptor = savedDescriptors[key]; // Skip redefined descriptors if (prevDescriptor && savedDescriptor && !isEqualDescriptor(savedDescriptor, prevDescriptor)) { Object.defineProperty(NextComponent, key, prevDescriptor); Object.defineProperty(ProxyComponent, key, prevDescriptor); return; } if (prevDescriptor && !savedDescriptor) { Object.defineProperty(ProxyComponent, key, prevDescriptor); return; } var nextDescriptor = _extends({}, Object.getOwnPropertyDescriptor(NextComponent, key), { configurable: true }); savedDescriptors[key] = nextDescriptor; Object.defineProperty(ProxyComponent, key, nextDescriptor); }); // Remove static methods and properties that are no longer defined Object.getOwnPropertyNames(ProxyComponent).forEach(function (key) { if (RESERVED_STATICS.indexOf(key) > -1) { return; } // Skip statics that exist on the next class if (NextComponent.hasOwnProperty(key)) { return; } // Skip non-configurable statics var proxyDescriptor = Object.getOwnPropertyDescriptor(ProxyComponent, key); if (proxyDescriptor && !proxyDescriptor.configurable) { return; } var prevDescriptor = PreviousComponent && Object.getOwnPropertyDescriptor(PreviousComponent, key); var savedDescriptor = savedDescriptors[key]; // Skip redefined descriptors if (prevDescriptor && savedDescriptor && !isEqualDescriptor(savedDescriptor, prevDescriptor)) { return; } delete ProxyComponent[key]; }); if (prototypeProxy) { // Update the prototype proxy with new methods var mountedInstances = prototypeProxy.update(NextComponent.prototype); // Set up the constructor property so accessing the statics work ProxyComponent.prototype.constructor = NextComponent; // We might have added new methods that need to be auto-bound mountedInstances.forEach(_bindAutoBindMethods2.default); mountedInstances.forEach(_deleteUnknownAutoBindMethods2.default); } }; function get() { return ProxyComponent; } function getCurrent() { return CurrentComponent; } update(InitialComponent); var proxy = { get: get, update: update }; addProxy(ProxyComponent, proxy); Object.defineProperty(proxy, '__getCurrent', { configurable: false, writable: false, enumerable: false, value: getCurrent }); return proxy; } function createFallback(Component) { var CurrentComponent = Component; return { get: function get() { return CurrentComponent; }, update: function update(NextComponent) { CurrentComponent = NextComponent; } }; } function createClassProxy(Component) { return Component.__proto__ && (0, _supportsProtoAssignment2.default)() ? proxyClass(Component) : createFallback(Component); }