UNPKG

orionsoft-react-scripts

Version:

Orionsoft Configuration and scripts for Create React App.

207 lines (171 loc) 5.83 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = createPrototypeProxy; var _assign = require('lodash/assign'); var _assign2 = _interopRequireDefault(_assign); var _difference = require('lodash/difference'); var _difference2 = _interopRequireDefault(_difference); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function createPrototypeProxy() { var proxy = {}; var current = null; var mountedInstances = []; /** * Creates a proxied toString() method pointing to the current version's toString(). */ function proxyToString(name) { // Wrap to always call the current version return function toString() { if (typeof current[name] === 'function') { return current[name].toString(); } else { return '<method was deleted>'; } }; } /** * Creates a proxied method that calls the current version, whenever available. */ function proxyMethod(name) { // Wrap to always call the current version var proxiedMethod = function proxiedMethod() { if (typeof current[name] === 'function') { return current[name].apply(this, arguments); } }; // Copy properties of the original function, if any (0, _assign2.default)(proxiedMethod, current[name]); proxiedMethod.toString = proxyToString(name); try { Object.defineProperty(proxiedMethod, 'name', { value: name }); } catch (err) {} return proxiedMethod; } /** * Augments the original componentDidMount with instance tracking. */ function proxiedComponentDidMount() { mountedInstances.push(this); if (typeof current.componentDidMount === 'function') { return current.componentDidMount.apply(this, arguments); } } proxiedComponentDidMount.toString = proxyToString('componentDidMount'); /** * Augments the original componentWillUnmount with instance tracking. */ function proxiedComponentWillUnmount() { var index = mountedInstances.indexOf(this); // Unless we're in a weird environment without componentDidMount if (index !== -1) { mountedInstances.splice(index, 1); } if (typeof current.componentWillUnmount === 'function') { return current.componentWillUnmount.apply(this, arguments); } } proxiedComponentWillUnmount.toString = proxyToString('componentWillUnmount'); /** * Defines a property on the proxy. */ function defineProxyProperty(name, descriptor) { Object.defineProperty(proxy, name, descriptor); } /** * Defines a property, attempting to keep the original descriptor configuration. */ function defineProxyPropertyWithValue(name, value) { var _ref = Object.getOwnPropertyDescriptor(current, name) || {}; var _ref$enumerable = _ref.enumerable; var enumerable = _ref$enumerable === undefined ? false : _ref$enumerable; var _ref$writable = _ref.writable; var writable = _ref$writable === undefined ? true : _ref$writable; defineProxyProperty(name, { configurable: true, enumerable: enumerable, writable: writable, value: value }); } /** * Creates an auto-bind map mimicking the original map, but directed at proxy. */ function createAutoBindMap() { if (!current.__reactAutoBindMap) { return; } var __reactAutoBindMap = {}; for (var name in current.__reactAutoBindMap) { if (typeof proxy[name] === 'function' && current.__reactAutoBindMap.hasOwnProperty(name)) { __reactAutoBindMap[name] = proxy[name]; } } return __reactAutoBindMap; } /** * Creates an auto-bind map mimicking the original map, but directed at proxy. */ function createAutoBindPairs() { var __reactAutoBindPairs = []; for (var i = 0; i < current.__reactAutoBindPairs.length; i += 2) { var name = current.__reactAutoBindPairs[i]; var method = proxy[name]; if (typeof method === 'function') { __reactAutoBindPairs.push(name, method); } } return __reactAutoBindPairs; } /** * Applies the updated prototype. */ function update(next) { // Save current source of truth current = next; // Find changed property names var currentNames = Object.getOwnPropertyNames(current); var previousName = Object.getOwnPropertyNames(proxy); var removedNames = (0, _difference2.default)(previousName, currentNames); // Remove properties and methods that are no longer there removedNames.forEach(function (name) { delete proxy[name]; }); // Copy every descriptor currentNames.forEach(function (name) { var descriptor = Object.getOwnPropertyDescriptor(current, name); if (typeof descriptor.value === 'function') { // Functions require additional wrapping so they can be bound later defineProxyPropertyWithValue(name, proxyMethod(name)); } else { // Other values can be copied directly defineProxyProperty(name, descriptor); } }); // Track mounting and unmounting defineProxyPropertyWithValue('componentDidMount', proxiedComponentDidMount); defineProxyPropertyWithValue('componentWillUnmount', proxiedComponentWillUnmount); if (current.hasOwnProperty('__reactAutoBindMap')) { defineProxyPropertyWithValue('__reactAutoBindMap', createAutoBindMap()); } if (current.hasOwnProperty('__reactAutoBindPairs')) { defineProxyPropertyWithValue('__reactAutoBindPairs', createAutoBindPairs()); } // Set up the prototype chain proxy.__proto__ = next; return mountedInstances; } /** * Returns the up-to-date proxy prototype. */ function get() { return proxy; } return { update: update, get: get }; };