first commit
This commit is contained in:
337
build/node_modules/prepack/lib/serializer/ResidualReactElements.js
generated
vendored
Normal file
337
build/node_modules/prepack/lib/serializer/ResidualReactElements.js
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ResidualReactElements = undefined;
|
||||
|
||||
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"); } }; }();
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var _realm = require("../realm.js");
|
||||
|
||||
var _ResidualHeapSerializer = require("./ResidualHeapSerializer.js");
|
||||
|
||||
var _hoisting = require("../react/hoisting.js");
|
||||
|
||||
var _index = require("../methods/index.js");
|
||||
|
||||
var _babelTypes = require("babel-types");
|
||||
|
||||
var t = _interopRequireWildcard(_babelTypes);
|
||||
|
||||
var _index2 = require("../values/index.js");
|
||||
|
||||
var _jsx = require("../react/jsx.js");
|
||||
|
||||
var _logger = require("./logger.js");
|
||||
|
||||
var _invariant = require("../invariant.js");
|
||||
|
||||
var _invariant2 = _interopRequireDefault(_invariant);
|
||||
|
||||
var _errors = require("../errors");
|
||||
|
||||
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; } }
|
||||
|
||||
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); } }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var ResidualReactElements = exports.ResidualReactElements = function () {
|
||||
function ResidualReactElements(realm, residualHeapSerializer) {
|
||||
_classCallCheck(this, ResidualReactElements);
|
||||
|
||||
this.realm = realm;
|
||||
this.residualHeapSerializer = residualHeapSerializer;
|
||||
this.logger = residualHeapSerializer.logger;
|
||||
this.reactOutput = realm.react.output || "create-element";
|
||||
this._lazilyHoistedNodes = undefined;
|
||||
}
|
||||
|
||||
_createClass(ResidualReactElements, [{
|
||||
key: "serializeReactElement",
|
||||
value: function serializeReactElement(val) {
|
||||
var typeValue = (0, _index.Get)(this.realm, val, "type");
|
||||
var keyValue = (0, _index.Get)(this.realm, val, "key");
|
||||
var refValue = (0, _index.Get)(this.realm, val, "ref");
|
||||
var propsValue = (0, _index.Get)(this.realm, val, "props");
|
||||
|
||||
(0, _invariant2.default)(typeValue !== null, "ReactElement type of null");
|
||||
|
||||
var attributes = [];
|
||||
var children = [];
|
||||
|
||||
if (keyValue !== null) {
|
||||
var keyExpr = this.residualHeapSerializer.serializeValue(keyValue);
|
||||
if (keyExpr.type !== "NullLiteral") {
|
||||
if (this.reactOutput === "jsx") {
|
||||
this._addSerializedValueToJSXAttriutes("key", keyExpr, attributes);
|
||||
} else if (this.reactOutput === "create-element") {
|
||||
this._addSerializedValueToObjectProperty("key", keyExpr, attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (refValue !== null) {
|
||||
var refExpr = this.residualHeapSerializer.serializeValue(refValue);
|
||||
if (refExpr.type !== "NullLiteral") {
|
||||
if (this.reactOutput === "jsx") {
|
||||
this._addSerializedValueToJSXAttriutes("ref", refExpr, attributes);
|
||||
} else if (this.reactOutput === "create-element") {
|
||||
this._addSerializedValueToObjectProperty("ref", refExpr, attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propsValue instanceof _index2.ObjectValue) {
|
||||
// the propsValue is visited to get the properties, but we don't emit it as the object
|
||||
this.residualHeapSerializer.serializedValues.add(propsValue);
|
||||
// have to case propsValue to ObjectValue or Flow complains that propsValues can be null/undefined
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = propsValue.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var _ref = _step.value;
|
||||
|
||||
var _ref2 = _slicedToArray(_ref, 2);
|
||||
|
||||
var key = _ref2[0];
|
||||
var propertyBinding = _ref2[1];
|
||||
|
||||
var desc = propertyBinding.descriptor;
|
||||
if (desc === undefined) continue; // deleted
|
||||
(0, _invariant2.default)(!(0, _index.IsAccessorDescriptor)(this.realm, desc), "expected descriptor to be a non-accessor property");
|
||||
|
||||
(0, _invariant2.default)(key !== "key" && key !== "ref", "\"" + key + "\" is a reserved prop name");
|
||||
|
||||
if (key === "children" && desc.value !== undefined) {
|
||||
var childrenValue = desc.value;
|
||||
if (childrenValue instanceof _index2.ArrayValue) {
|
||||
this.residualHeapSerializer.serializedValues.add(childrenValue);
|
||||
var childrenLength = (0, _index.Get)(this.realm, childrenValue, "length");
|
||||
var childrenLengthValue = 0;
|
||||
if (childrenLength instanceof _index2.NumberValue) {
|
||||
childrenLengthValue = childrenLength.value;
|
||||
for (var i = 0; i < childrenLengthValue; i++) {
|
||||
var child = (0, _index.Get)(this.realm, childrenValue, "" + i);
|
||||
if (child instanceof _index2.Value) {
|
||||
children.push(this._serializeReactElementChild(child));
|
||||
} else {
|
||||
this.logger.logError(val, "ReactElement \"props.children[" + i + "]\" failed to serialize due to a non-value");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// otherwise it must be a value, as desc.value !== undefined.
|
||||
children.push(this._serializeReactElementChild(childrenValue));
|
||||
continue;
|
||||
}
|
||||
if (desc.value instanceof _index2.Value) {
|
||||
if (this.reactOutput === "jsx") {
|
||||
this._addSerializedValueToJSXAttriutes(key, this.residualHeapSerializer.serializeValue(desc.value), attributes);
|
||||
} else if (this.reactOutput === "create-element") {
|
||||
this._addSerializedValueToObjectProperty(key, this.residualHeapSerializer.serializeValue(desc.value), attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var reactLibraryObject = this.realm.react.reactLibraryObject;
|
||||
var shouldHoist = this.residualHeapSerializer.currentFunctionBody !== this.residualHeapSerializer.mainBody && (0, _hoisting.canHoistReactElement)(this.realm, val);
|
||||
|
||||
var id = this.residualHeapSerializer.getSerializeObjectIdentifier(val);
|
||||
// this identifier is used as the deafult, but also passed to the hoisted factory function
|
||||
var originalCreateElementIdentifier = null;
|
||||
// this name is used when hoisting, and is passed into the factory function, rather than the original
|
||||
var hoistedCreateElementIdentifier = null;
|
||||
var reactElement = void 0;
|
||||
|
||||
if (this.reactOutput === "jsx") {
|
||||
reactElement = this._serializeReactElementToJSXElement(val, typeValue, attributes, children, reactLibraryObject);
|
||||
} else if (this.reactOutput === "create-element") {
|
||||
// if there is no React library, then we should throw and error, as it is needed for createElement output
|
||||
if (reactLibraryObject === undefined) {
|
||||
throw new _errors.FatalError("unable to serialize JSX to createElement due to React not being referenced in scope");
|
||||
}
|
||||
var createElement = (0, _index.Get)(this.realm, reactLibraryObject, "createElement");
|
||||
originalCreateElementIdentifier = this.residualHeapSerializer.serializeValue(createElement);
|
||||
if (shouldHoist) {
|
||||
// if we haven't created a _lazilyHoistedNodes before, then this is the first time
|
||||
// so we only create the hoisted identifier once
|
||||
if (this._lazilyHoistedNodes === undefined) {
|
||||
// create a new unique instance
|
||||
hoistedCreateElementIdentifier = t.identifier(this.residualHeapSerializer.intrinsicNameGenerator.generate());
|
||||
} else {
|
||||
hoistedCreateElementIdentifier = this._lazilyHoistedNodes.createElementIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
reactElement = this._serializeReactElementToCreateElement(val, typeValue, attributes, children, shouldHoist ? hoistedCreateElementIdentifier : originalCreateElementIdentifier);
|
||||
} else {
|
||||
(0, _invariant2.default)(false, "Unknown reactOutput specified");
|
||||
}
|
||||
// if we are hoisting this React element, put the assignment in the body
|
||||
// also ensure we are in an additional function
|
||||
if (shouldHoist) {
|
||||
// if the currentHoistedReactElements is not defined, we create it an emit the function call
|
||||
// this should only occur once per additional function
|
||||
if (this._lazilyHoistedNodes === undefined) {
|
||||
var funcId = t.identifier(this.residualHeapSerializer.functionNameGenerator.generate());
|
||||
this._lazilyHoistedNodes = {
|
||||
id: funcId,
|
||||
createElementIdentifier: hoistedCreateElementIdentifier,
|
||||
nodes: []
|
||||
};
|
||||
var statement = t.expressionStatement(t.logicalExpression("&&", t.binaryExpression("===", id, t.unaryExpression("void", t.numericLiteral(0), true)),
|
||||
// pass the createElementIdentifier if it's not null
|
||||
t.callExpression(funcId, originalCreateElementIdentifier ? [originalCreateElementIdentifier] : [])));
|
||||
this.residualHeapSerializer.emitter.emit(statement);
|
||||
}
|
||||
// we then push the reactElement and its id into our list of elements to process after
|
||||
// the current additional function has serialzied
|
||||
(0, _invariant2.default)(this._lazilyHoistedNodes !== undefined);
|
||||
(0, _invariant2.default)(Array.isArray(this._lazilyHoistedNodes.nodes));
|
||||
this._lazilyHoistedNodes.nodes.push({ id: id, astNode: reactElement });
|
||||
} else {
|
||||
var declar = t.variableDeclaration("var", [t.variableDeclarator(id, reactElement)]);
|
||||
this.residualHeapSerializer.emitter.emit(declar);
|
||||
}
|
||||
return reactElement;
|
||||
}
|
||||
}, {
|
||||
key: "_addSerializedValueToJSXAttriutes",
|
||||
value: function _addSerializedValueToJSXAttriutes(prop, expr, attributes) {
|
||||
attributes.push((0, _jsx.convertKeyValueToJSXAttribute)(prop, expr));
|
||||
}
|
||||
}, {
|
||||
key: "_addSerializedValueToObjectProperty",
|
||||
value: function _addSerializedValueToObjectProperty(prop, expr, attributes) {
|
||||
var key = void 0;
|
||||
|
||||
if (prop.includes("-")) {
|
||||
key = t.stringLiteral(prop);
|
||||
} else {
|
||||
key = t.identifier(prop);
|
||||
}
|
||||
attributes.push(t.objectProperty(key, expr));
|
||||
}
|
||||
}, {
|
||||
key: "_serializeReactElementToCreateElement",
|
||||
value: function _serializeReactElementToCreateElement(val, typeValue, attributes, children, createElementIdentifier) {
|
||||
var typeIdentifier = this.residualHeapSerializer.serializeValue(typeValue);
|
||||
var createElementArguments = [typeIdentifier];
|
||||
// check if we need to add attributes
|
||||
if (attributes.length !== 0) {
|
||||
// cast to any for createElementArguments as casting it to BabelNodeObjectProperty[] isn't working
|
||||
createElementArguments.push(t.objectExpression(attributes));
|
||||
}
|
||||
if (children.length !== 0) {
|
||||
if (attributes.length === 0) {
|
||||
createElementArguments.push(t.nullLiteral());
|
||||
}
|
||||
createElementArguments.push.apply(createElementArguments, _toConsumableArray(children));
|
||||
}
|
||||
// cast to any for createElementArguments as casting it to BabelNodeExpresion[] isn't working
|
||||
var createElementCall = t.callExpression(createElementIdentifier, createElementArguments);
|
||||
this._addBailOutMessageToBabelNode(val, createElementCall);
|
||||
return createElementCall;
|
||||
}
|
||||
}, {
|
||||
key: "_serializeReactElementToJSXElement",
|
||||
value: function _serializeReactElementToJSXElement(val, typeValue, attributes, children, reactLibraryObject) {
|
||||
if (reactLibraryObject !== undefined) {
|
||||
this.residualHeapSerializer.serializeValue(reactLibraryObject);
|
||||
}
|
||||
var identifier = (0, _jsx.convertExpressionToJSXIdentifier)(this.residualHeapSerializer.serializeValue(typeValue), true);
|
||||
var openingElement = t.jSXOpeningElement(identifier, attributes, children.length === 0);
|
||||
var closingElement = t.jSXClosingElement(identifier);
|
||||
|
||||
var jsxElement = t.jSXElement(openingElement, closingElement, children, children.length === 0);
|
||||
this._addBailOutMessageToBabelNode(val, jsxElement);
|
||||
return jsxElement;
|
||||
}
|
||||
}, {
|
||||
key: "_addBailOutMessageToBabelNode",
|
||||
value: function _addBailOutMessageToBabelNode(val, node) {
|
||||
// if there has been a bail-out, we create an inline BlockComment node before the JSX element
|
||||
if (val.$BailOutReason !== undefined) {
|
||||
// $BailOutReason contains an optional string of what to print out in the comment
|
||||
node.leadingComments = [{ type: "BlockComment", value: "" + val.$BailOutReason }];
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "_serializeReactElementChild",
|
||||
value: function _serializeReactElementChild(child) {
|
||||
var expr = this.residualHeapSerializer.serializeValue(child);
|
||||
|
||||
if (this.reactOutput === "jsx") {
|
||||
if (t.isStringLiteral(expr) || t.isNumericLiteral(expr)) {
|
||||
return t.jSXText(expr.value + "");
|
||||
} else if (t.isJSXElement(expr)) {
|
||||
return expr;
|
||||
}
|
||||
return t.jSXExpressionContainer(expr);
|
||||
} else if (this.reactOutput === "create-element") {
|
||||
return expr;
|
||||
}
|
||||
(0, _invariant2.default)(false, "Unknown reactOutput specified");
|
||||
}
|
||||
}, {
|
||||
key: "serializeLazyHoistedNodes",
|
||||
value: function serializeLazyHoistedNodes() {
|
||||
var entries = [];
|
||||
if (this._lazilyHoistedNodes !== undefined) {
|
||||
var _lazilyHoistedNodes = this._lazilyHoistedNodes,
|
||||
id = _lazilyHoistedNodes.id,
|
||||
nodes = _lazilyHoistedNodes.nodes,
|
||||
createElementIdentifier = _lazilyHoistedNodes.createElementIdentifier;
|
||||
// create a function that initializes all the hoisted nodes
|
||||
|
||||
var func = t.functionExpression(null,
|
||||
// use createElementIdentifier if it's not null
|
||||
createElementIdentifier ? [createElementIdentifier] : [], t.blockStatement(nodes.map(function (node) {
|
||||
return t.expressionStatement(t.assignmentExpression("=", node.id, node.astNode));
|
||||
})));
|
||||
// push it to the mainBody of the module
|
||||
entries.push(t.variableDeclaration("var", [t.variableDeclarator(id, func)]));
|
||||
// output all the empty variable declarations that will hold the nodes lazily
|
||||
entries.push.apply(entries, _toConsumableArray(nodes.map(function (node) {
|
||||
return t.variableDeclaration("var", [t.variableDeclarator(node.id)]);
|
||||
})));
|
||||
// reset the _lazilyHoistedNodes so other additional functions work
|
||||
this._lazilyHoistedNodes = undefined;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}]);
|
||||
|
||||
return ResidualReactElements;
|
||||
}();
|
||||
//# sourceMappingURL=ResidualReactElements.js.map
|
||||
Reference in New Issue
Block a user