UNPKG

prepack

Version:

Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.

575 lines (488 loc) 19.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createMockReact = createMockReact; var _babylon = require("babylon"); var _index = require("../../domains/index.js"); var _index2 = require("../../values/index.js"); var _index3 = require("../../methods/index.js"); var _singletons = require("../../singletons.js"); var _utils = require("../../react/utils.js"); var _elements = require("../../react/elements.js"); var _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); var _invariant = require("../../invariant"); var _invariant2 = _interopRequireDefault(_invariant); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } // most of the code here was taken from https://github.com/facebook/react/blob/master/packages/react/src/ReactElement.js let reactCode = ` function createReact(REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, REACT_PORTAL_TYPE, ReactCurrentOwner) { function makeEmptyFunction(arg) { return function() { return arg; }; } var emptyFunction = function() {}; emptyFunction.thatReturns = makeEmptyFunction; emptyFunction.thatReturnsFalse = makeEmptyFunction(false); emptyFunction.thatReturnsTrue = makeEmptyFunction(true); emptyFunction.thatReturnsNull = makeEmptyFunction(null); emptyFunction.thatReturnsThis = function() { return this; }; emptyFunction.thatReturnsArgument = function(arg) { return arg; }; var hasOwnProperty = Object.prototype.hasOwnProperty; var RESERVED_PROPS = { key: true, ref: true, __self: true, __source: true, }; var ReactElement = function(type, key, ref, self, source, owner, props) { return { // This tag allow us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, // Built-in properties that belong on the element type: type, key: key, ref: ref, props: props, // Record the component responsible for creating this element. _owner: owner, }; }; function hasValidRef(config) { return config.ref !== undefined; } function hasValidKey(config) { return config.key !== undefined; } function Component(props, context) { this.props = props; this.context = context; this.refs = {}; } Component.prototype.isReactComponent = {}; function PureComponent(props, context) { this.props = props; this.context = context; this.refs = {}; } PureComponent.prototype.isReactComponent = {}; PureComponent.prototype.isPureReactComponent = true; var userProvidedKeyEscapeRegex = /\/+/g; function escapeUserProvidedKey(text) { return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/'); } function escape(key) { const escapeRegex = /[=:]/g; const escaperLookup = { '=': '=0', ':': '=2', }; const escapedString = ('' + key).replace(escapeRegex, function(match) { return escaperLookup[match]; }); return '$' + escapedString; } var SEPARATOR = '.'; var SUBSEPARATOR = ':'; var POOL_SIZE = 10; var traverseContextPool = []; function getPooledTraverseContext( mapResult, keyPrefix, mapFunction, mapContext, ) { if (traverseContextPool.length) { const traverseContext = traverseContextPool.pop(); traverseContext.result = mapResult; traverseContext.keyPrefix = keyPrefix; traverseContext.func = mapFunction; traverseContext.context = mapContext; traverseContext.count = 0; return traverseContext; } else { return { result: mapResult, keyPrefix: keyPrefix, func: mapFunction, context: mapContext, count: 0, }; } } function releaseTraverseContext(traverseContext) { traverseContext.result = null; traverseContext.keyPrefix = null; traverseContext.func = null; traverseContext.context = null; traverseContext.count = 0; if (traverseContextPool.length < POOL_SIZE) { traverseContextPool.push(traverseContext); } } function traverseAllChildren(children, callback, traverseContext) { if (children == null) { return 0; } return traverseAllChildrenImpl(children, '', callback, traverseContext); } function getComponentKey(component, index) { // Do some typechecking here since we call this blindly. We want to ensure // that we don't block potential future ES APIs. if ( typeof component === 'object' && component !== null && component.key != null ) { // Explicit key return escape(component.key); } // Implicit key determined by the index in the set return index.toString(36); } function traverseAllChildrenImpl( children, nameSoFar, callback, traverseContext, ) { const type = typeof children; if (type === 'undefined' || type === 'boolean') { // All of the above are perceived as null. children = null; } let invokeCallback = false; if (children === null) { invokeCallback = true; } else { switch (type) { case 'string': case 'number': invokeCallback = true; break; case 'object': switch (children.$$typeof) { case REACT_ELEMENT_TYPE: case REACT_PORTAL_TYPE: invokeCallback = true; } } } if (invokeCallback) { callback( traverseContext, children, // If it's the only child, treat the name as if it was wrapped in an array // so that it's consistent if the number of children grows. nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar, ); return 1; } let child; let nextName; let subtreeCount = 0; // Count of children found in the current subtree. const nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR; if (Array.isArray(children)) { for (let i = 0; i < children.length; i++) { child = children[i]; nextName = nextNamePrefix + getComponentKey(child, i); subtreeCount += traverseAllChildrenImpl( child, nextName, callback, traverseContext, ); } } else { const iteratorFn = getIteratorFn(children); if (typeof iteratorFn === 'function') { var iterator = iteratorFn.call(children); let step; let ii = 0; while (!(step = iterator.next()).done) { child = step.value; nextName = nextNamePrefix + getComponentKey(child, ii++); subtreeCount += traverseAllChildrenImpl( child, nextName, callback, traverseContext, ); } } else if (type === 'object') { let addendum = ''; var childrenString = '' + children; } } return subtreeCount; } function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) { var escapedPrefix = ''; if (prefix != null) { escapedPrefix = escapeUserProvidedKey(prefix) + '/'; } const traverseContext = getPooledTraverseContext( array, escapedPrefix, func, context, ); traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); releaseTraverseContext(traverseContext); } function forEachSingleChild(bookKeeping, child, name) { const {func, context} = bookKeeping; func.call(context, child, bookKeeping.count++); } function forEachChildren(children, forEachFunc, forEachContext) { if (children == null) { return children; } var traverseContext = getPooledTraverseContext( null, null, forEachFunc, forEachContext, ); traverseAllChildren(children, forEachSingleChild, traverseContext); releaseTraverseContext(traverseContext); } function mapChildren(children, func, context) { if (children == null) { return children; } var result = []; mapIntoWithKeyPrefixInternal(children, result, null, func, context); return result; } function countChildren(children) { return traverseAllChildren(children, emptyFunction.thatReturnsNull, null); } function onlyChild(children) { return children; } function toArray(children) { var result = []; mapIntoWithKeyPrefixInternal( children, result, null, emptyFunction.thatReturnsArgument, ); return result; } function cloneElement(element, config, children) { var propName; // Original props are copied var props = Object.assign({}, element.props); // Reserved names are extracted var key = element.key; var ref = element.ref; // Self is preserved since the owner is preserved. var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a // transpiler, and the original source is probably a better indicator of the // true owner. var source = element._source; // Owner will be preserved, unless ref is overridden var owner = element._owner; if (config != null) { if (hasValidRef(config)) { // Silently steal the ref from the parent. ref = config.ref; owner = ReactCurrentOwner.current; } if (hasValidKey(config)) { key = '' + config.key; } // Remaining properties override existing props var defaultProps; if (element.type && element.type.defaultProps) { defaultProps = element.type.defaultProps; } for (propName in config) { if ( hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName) ) { if (config[propName] === undefined && defaultProps !== undefined) { // Resolve default props props[propName] = defaultProps[propName]; } else { props[propName] = config[propName]; } } } } // Children can be more than one argument, and those are transferred onto // the newly allocated props object. var childrenLength = arguments.length - 2; if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } return ReactElement(element.type, key, ref, self, source, owner, props); } function isValidElement(object) { return ( typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE ); } function shim() { } shim.isRequired = shim; function getShim() { return shim; }; var ReactPropTypes = { array: shim, bool: shim, func: shim, number: shim, object: shim, string: shim, symbol: shim, any: shim, arrayOf: getShim, element: shim, instanceOf: getShim, node: shim, objectOf: getShim, oneOf: getShim, oneOfType: getShim, shape: getShim, exact: getShim }; ReactPropTypes.checkPropTypes = shim; ReactPropTypes.PropTypes = ReactPropTypes; return { Children: { forEach: forEachChildren, map: mapChildren, count: countChildren, only: onlyChild, toArray, }, Component, PureComponent, Fragment: REACT_FRAGMENT_TYPE, cloneElement, isValidElement, version: "16.2.0", PropTypes: ReactPropTypes, }; } `; /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ let reactAst = (0, _babylon.parseExpression)(reactCode, { plugins: ["flow"] }); function createMockReact(realm, reactRequireName) { let reactFactory = _singletons.Environment.GetValue(realm, realm.$GlobalEnv.evaluate(reactAst, false)); (0, _invariant2.default)(reactFactory instanceof _index2.ECMAScriptSourceFunctionValue); let currentOwner = realm.react.currentOwner = new _index2.ObjectValue(realm, realm.intrinsics.ObjectPrototype, "currentOwner"); // this is to get around Flow getting confused let factory = reactFactory.$Call; (0, _invariant2.default)(factory !== undefined); let reactValue = factory(realm.intrinsics.undefined, [(0, _utils.getReactSymbol)("react.element", realm), (0, _utils.getReactSymbol)("react.fragment", realm), (0, _utils.getReactSymbol)("react.portal", realm), currentOwner]); (0, _invariant2.default)(reactValue instanceof _index2.ObjectValue); reactValue.intrinsicName = `require("${reactRequireName}")`; (0, _invariant2.default)(reactValue instanceof _index2.ObjectValue); let reactComponentValue = (0, _index3.Get)(realm, reactValue, "Component"); reactComponentValue.intrinsicName = `require("${reactRequireName}").Component`; (0, _invariant2.default)(reactComponentValue instanceof _index2.ECMAScriptFunctionValue); let reactPureComponentValue = (0, _index3.Get)(realm, reactValue, "PureComponent"); reactPureComponentValue.intrinsicName = `require("${reactRequireName}").PureComponent`; (0, _invariant2.default)(reactPureComponentValue instanceof _index2.ECMAScriptFunctionValue); reactComponentValue.$FunctionKind = "normal"; (0, _invariant2.default)(reactComponentValue instanceof _index2.ObjectValue); let reactComponentPrototypeValue = (0, _index3.Get)(realm, reactComponentValue, "prototype"); reactComponentPrototypeValue.intrinsicName = `require("${reactRequireName}").Component.prototype`; let reactPureComponentPrototypeValue = (0, _index3.Get)(realm, reactPureComponentValue, "prototype"); reactPureComponentPrototypeValue.intrinsicName = `require("${reactRequireName}").PureComponent.prototype`; let reactCloneElementValue = (0, _index3.Get)(realm, reactValue, "cloneElement"); reactCloneElementValue.intrinsicName = `require("${reactRequireName}").cloneElement`; reactValue.refuseSerialization = true; let reactElementValue = new _index2.NativeFunctionValue(realm, undefined, `createElement`, 0, (context, [type, config, ...children]) => { (0, _invariant2.default)(type instanceof _index2.Value); (0, _invariant2.default)(config instanceof _index2.ObjectValue || config instanceof _index2.AbstractObjectValue || config instanceof _index2.AbstractValue || config instanceof _index2.NullValue); if (Array.isArray(children)) { if (children.length === 0) { children = realm.intrinsics.undefined; } else if (children.length === 1) { children = children[0]; } else { let array = _singletons.Create.ArrayCreate(realm, 0); let length = children.length; for (let i = 0; i < length; i++) { _singletons.Create.CreateDataPropertyOrThrow(realm, array, "" + i, children[i]); } children = array; } } (0, _invariant2.default)(children instanceof _index2.Value); return (0, _elements.createReactElement)(realm, type, config, children); }); reactValue.$DefineOwnProperty("createElement", { value: reactElementValue, writable: false, enumerable: false, configurable: true }); reactElementValue.intrinsicName = `require("${reactRequireName}").createElement`; let reactContextValue = new _index2.NativeFunctionValue(realm, undefined, `createContext`, 0, (_, [defaultValue = realm.intrinsics.undefined]) => { (0, _invariant2.default)(defaultValue instanceof _index2.Value); let consumerObject = new _index2.ObjectValue(realm, realm.intrinsics.ObjectPrototype); let providerObject = new _index2.ObjectValue(realm, realm.intrinsics.ObjectPrototype); let consumer = _index2.AbstractValue.createTemporalFromBuildFunction(realm, _index2.ObjectValue, [reactContextValue, defaultValue], ([methodNode, defaultValueNode]) => { return t.callExpression(methodNode, [defaultValueNode]); }); (0, _invariant2.default)(consumer instanceof _index2.AbstractObjectValue); consumer.values = new _index.ValuesDomain(new Set([consumerObject])); let provider = _index2.AbstractValue.createTemporalFromBuildFunction(realm, _index2.ObjectValue, [consumer], ([consumerNode]) => { return t.memberExpression(consumerNode, t.identifier("Provider")); }); (0, _invariant2.default)(provider instanceof _index2.AbstractObjectValue); provider.values = new _index.ValuesDomain(new Set([providerObject])); _singletons.Properties.Set(realm, consumerObject, "$$typeof", (0, _utils.getReactSymbol)("react.context", realm), true); _singletons.Properties.Set(realm, consumerObject, "currentValue", defaultValue, true); _singletons.Properties.Set(realm, consumerObject, "defaultValue", defaultValue, true); _singletons.Properties.Set(realm, consumerObject, "changedBits", new _index2.NumberValue(realm, 0), true); _singletons.Properties.Set(realm, consumerObject, "Consumer", consumer, true); _singletons.Properties.Set(realm, providerObject, "$$typeof", (0, _utils.getReactSymbol)("react.provider", realm), true); _singletons.Properties.Set(realm, providerObject, "context", consumer, true); _singletons.Properties.Set(realm, consumerObject, "Provider", provider, true); return consumer; }); reactValue.$DefineOwnProperty("createContext", { value: reactContextValue, writable: false, enumerable: false, configurable: true }); reactContextValue.intrinsicName = `require("${reactRequireName}").createContext`; let reactIsValidElementValue = (0, _index3.Get)(realm, reactValue, "isValidElement"); reactIsValidElementValue.intrinsicName = `require("${reactRequireName}").isValidElement`; let reactChildrenValue = (0, _index3.Get)(realm, reactValue, "Children"); reactChildrenValue.intrinsicName = `require("${reactRequireName}").Children`; let reactPropTypesValue = (0, _index3.Get)(realm, reactValue, "PropTypes"); reactPropTypesValue.intrinsicName = `require("${reactRequireName}").PropTypes`; reactValue.refuseSerialization = false; return reactValue; } //# sourceMappingURL=react-mocks.js.map