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
JavaScript
"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