prepack
Version:
Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.
189 lines (145 loc) • 7.51 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createMockReactRelay = createMockReactRelay;
var _index = require("../../values/index.js");
var _singletons = require("../../singletons.js");
var _utils = require("../prepack/utils.js");
var _index2 = require("../../methods/index.js");
var _invariant = _interopRequireDefault(require("../../invariant.js"));
var _utils2 = require("../../react/utils.js");
var _parser = require("@babel/parser");
var _utils3 = require("./utils.js");
var _generator = require("../../utils/generator.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 reactRelayCode = `
function createReactRelay(React) {
function mapObject(obj, func) {
var newObj = {};
Object.keys(obj).forEach(function(key) {
newObj[key] = func(obj[key]);
});
return newObj;
}
function isReactComponent(component) {
return !!(
component &&
typeof component.prototype === 'object' &&
component.prototype &&
component.prototype.isReactComponent
);
}
function getReactComponent(Component) {
if (isReactComponent(Component)) {
return Component;
} else {
return null;
}
}
function getComponentName(Component) {
let name;
const ComponentClass = getReactComponent(Component);
if (ComponentClass) {
name = ComponentClass.displayName || ComponentClass.name;
} else if (typeof Component === 'function') {
name = Component.displayName || Component.name || 'StatelessComponent';
} else {
name = 'ReactElement';
}
return String(name);
}
function createFragmentContainer(Component, fragmentSpec) {
var componentName = getComponentName(Component);
var containerName = \`Relay(\${componentName})\`;
return function(props, context) {
var relay = context.relay;
var {
createFragmentSpecResolver,
getFragment: getFragmentFromTag,
} = relay.environment.unstable_internal;
var fragments = mapObject(fragmentSpec, getFragmentFromTag);
var resolver = createFragmentSpecResolver(
relay,
containerName,
fragments,
props,
);
var relayProp = {
isLoading: resolver.isLoading(),
environment: relay.environment,
};
var newProps = Object.assign({}, props, resolver.resolve(), {
relay: relayProp,
});
return React.createElement(Component, newProps);
};
}
return {
createFragmentContainer,
};
}
`;
let reactRelayAst = (0, _parser.parseExpression)(reactRelayCode, {
plugins: ["flow"]
});
function createReactRelayContainer(realm, reactRelay, containerName, reactRelayFirstRenderValue, relayRequireName) {
// we create a ReactRelay container function that returns an abstract object
// allowing us to reconstruct this ReactReact.createSomeContainer(...) again
// we also pass a reactHint so the reconciler can properly deal with this
(0, _utils3.addMockFunctionToObject)(realm, reactRelay, relayRequireName, containerName, (funcValue, args) => {
let value = _index.AbstractValue.createTemporalFromBuildFunction(realm, _index.FunctionValue, [reactRelay, new _index.StringValue(realm, containerName), ...args], (0, _generator.createOperationDescriptor)("REACT_RELAY_MOCK_CONTAINER"), {
skipInvariant: true,
isPure: true
});
(0, _invariant.default)(value instanceof _index.AbstractValue);
let firstRenderContainerValue = (0, _index2.Get)(realm, reactRelayFirstRenderValue, containerName);
let firstRenderValue = realm.intrinsics.undefined;
if (firstRenderContainerValue instanceof _index.ECMAScriptSourceFunctionValue) {
let firstRenderContainerValueCall = firstRenderContainerValue.$Call;
(0, _invariant.default)(firstRenderContainerValueCall !== undefined);
firstRenderValue = firstRenderContainerValueCall(realm.intrinsics.undefined, args);
(0, _invariant.default)(firstRenderValue instanceof _index.ECMAScriptSourceFunctionValue);
}
realm.react.abstractHints.set(value, (0, _utils2.createReactHintObject)(reactRelay, containerName, args, firstRenderValue));
return value;
});
}
function createMockReactRelay(realm, relayRequireName) {
let reactRelayFirstRenderFactory = _singletons.Environment.GetValue(realm, realm.$GlobalEnv.evaluate(reactRelayAst, false));
(0, _invariant.default)(reactRelayFirstRenderFactory instanceof _index.ECMAScriptSourceFunctionValue);
let factory = reactRelayFirstRenderFactory.$Call;
(0, _invariant.default)(factory !== undefined);
(0, _invariant.default)(realm.fbLibraries.react instanceof _index.ObjectValue, "mock ReactRelay cannot be required before mock React");
let reactRelayFirstRenderValue = factory(realm.intrinsics.undefined, [realm.fbLibraries.react]);
(0, _invariant.default)(reactRelayFirstRenderValue instanceof _index.ObjectValue); // we set refuseSerialization to true so we don't serialize the below properties straight away
let reactRelay = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype, `require("${relayRequireName}")`, true); // for QueryRenderer, we want to leave the component alone but process it's "render" prop
let queryRendererComponent = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").QueryRenderer`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "QueryRenderer", queryRendererComponent);
let graphql = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").graphql`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "graphql", graphql);
let reactRelayContainers = ["createFragmentContainer", "createPaginationContainer", "createRefetchContainer"];
for (let reactRelayContainer of reactRelayContainers) {
createReactRelayContainer(realm, reactRelay, reactRelayContainer, reactRelayFirstRenderValue, relayRequireName);
}
let commitLocalUpdate = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").commitLocalUpdate`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "commitLocalUpdate", commitLocalUpdate);
let commitMutation = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").commitMutation`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "commitMutation", commitMutation);
let fetchQuery = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").fetchQuery`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "fetchQuery", fetchQuery);
let requestSubscription = (0, _utils.createAbstract)(realm, "function", `require("${relayRequireName}").requestSubscription`);
_singletons.Create.CreateDataPropertyOrThrow(realm, reactRelay, "requestSubscription", requestSubscription); // we set refuseSerialization back to false
reactRelay.refuseSerialization = false;
reactRelay.makeFinal();
return reactRelay;
}
//# sourceMappingURL=relay-mocks.js.map