245 lines
7.9 KiB
JavaScript
245 lines
7.9 KiB
JavaScript
|
'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 = proxyClass;
|
||
|
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', '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;
|
||
|
}
|
||
|
|
||
|
// 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 prototypeProxy = (0, _createPrototypeProxy2.default)();
|
||
|
var CurrentComponent = undefined;
|
||
|
var ProxyComponent = undefined;
|
||
|
|
||
|
var staticDescriptors = {};
|
||
|
function wasStaticModifiedByUser(key) {
|
||
|
// Compare the descriptor with the one we previously set ourselves.
|
||
|
var currentDescriptor = Object.getOwnPropertyDescriptor(ProxyComponent, key);
|
||
|
return !isEqualDescriptor(staticDescriptors[key], currentDescriptor);
|
||
|
}
|
||
|
|
||
|
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];
|
||
|
});
|
||
|
})();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
// Create a proxy constructor with matching name
|
||
|
ProxyComponent = new Function('factory', 'instantiate', 'return function ' + (InitialComponent.name || 'ProxyComponent') + '() {\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);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Point proxy constructor to the proxy prototype
|
||
|
ProxyComponent.prototype = prototypeProxy.get();
|
||
|
|
||
|
// Proxy toString() to the current constructor
|
||
|
ProxyComponent.toString = function toString() {
|
||
|
return CurrentComponent.toString();
|
||
|
};
|
||
|
|
||
|
function update(NextComponent) {
|
||
|
if (typeof NextComponent !== 'function') {
|
||
|
throw new Error('Expected a constructor.');
|
||
|
}
|
||
|
|
||
|
// Prevent proxy cycles
|
||
|
var existingProxy = findProxy(NextComponent);
|
||
|
if (existingProxy) {
|
||
|
return update(existingProxy.__getCurrent());
|
||
|
}
|
||
|
|
||
|
// Save the next constructor so we call it
|
||
|
CurrentComponent = NextComponent;
|
||
|
|
||
|
// 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 = ProxyComponent;
|
||
|
|
||
|
// Set up the same prototype for inherited statics
|
||
|
ProxyComponent.__proto__ = NextComponent.__proto__;
|
||
|
|
||
|
// Copy static methods and properties
|
||
|
Object.getOwnPropertyNames(NextComponent).forEach(function (key) {
|
||
|
if (RESERVED_STATICS.indexOf(key) > -1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var staticDescriptor = _extends({}, Object.getOwnPropertyDescriptor(NextComponent, key), {
|
||
|
configurable: true
|
||
|
});
|
||
|
|
||
|
// Copy static unless user has redefined it at runtime
|
||
|
if (!wasStaticModifiedByUser(key)) {
|
||
|
Object.defineProperty(ProxyComponent, key, staticDescriptor);
|
||
|
staticDescriptors[key] = staticDescriptor;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Remove old static methods and properties
|
||
|
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 descriptor = Object.getOwnPropertyDescriptor(ProxyComponent, key);
|
||
|
if (descriptor && !descriptor.configurable) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Delete static unless user has redefined it at runtime
|
||
|
if (!wasStaticModifiedByUser(key)) {
|
||
|
delete ProxyComponent[key];
|
||
|
delete staticDescriptors[key];
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Try to infer displayName
|
||
|
ProxyComponent.displayName = NextComponent.displayName || NextComponent.name;
|
||
|
|
||
|
// We might have added new methods that need to be auto-bound
|
||
|
mountedInstances.forEach(_bindAutoBindMethods2.default);
|
||
|
mountedInstances.forEach(_deleteUnknownAutoBindMethods2.default);
|
||
|
|
||
|
// Let the user take care of redrawing
|
||
|
return mountedInstances;
|
||
|
};
|
||
|
|
||
|
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);
|
||
|
}
|