first commit
This commit is contained in:
255
build/node_modules/prepack/lib/react/utils.js
generated
vendored
Normal file
255
build/node_modules/prepack/lib/react/utils.js
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isReactElement = isReactElement;
|
||||
exports.getReactSymbol = getReactSymbol;
|
||||
exports.isTagName = isTagName;
|
||||
exports.isReactComponent = isReactComponent;
|
||||
exports.valueIsClassComponent = valueIsClassComponent;
|
||||
exports.valueIsReactLibraryObject = valueIsReactLibraryObject;
|
||||
exports.valueIsLegacyCreateClassComponent = valueIsLegacyCreateClassComponent;
|
||||
exports.addKeyToReactElement = addKeyToReactElement;
|
||||
exports.getUniqueReactElementKey = getUniqueReactElementKey;
|
||||
exports.mapOverArrayValue = mapOverArrayValue;
|
||||
exports.convertSimpleClassComponentToFunctionalComponent = convertSimpleClassComponentToFunctionalComponent;
|
||||
|
||||
var _realm = require("../realm.js");
|
||||
|
||||
var _index = require("../values/index.js");
|
||||
|
||||
var _index2 = require("../methods/index.js");
|
||||
|
||||
var _BinaryExpression = require("../evaluators/BinaryExpression.js");
|
||||
|
||||
require("../serializer/types.js");
|
||||
|
||||
var _invariant = require("../invariant.js");
|
||||
|
||||
var _invariant2 = _interopRequireDefault(_invariant);
|
||||
|
||||
var _singletons = require("../singletons.js");
|
||||
|
||||
var _babelTraverse = require("babel-traverse");
|
||||
|
||||
var _babelTraverse2 = _interopRequireDefault(_babelTraverse);
|
||||
|
||||
var _babelTypes = require("babel-types");
|
||||
|
||||
var t = _interopRequireWildcard(_babelTypes);
|
||||
|
||||
var _errors = require("../errors.js");
|
||||
|
||||
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 _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.
|
||||
*/
|
||||
|
||||
function isReactElement(val) {
|
||||
if (val instanceof _index.ObjectValue && val.properties.has("$$typeof")) {
|
||||
var realm = val.$Realm;
|
||||
var $$typeof = (0, _index2.Get)(realm, val, "$$typeof");
|
||||
var globalObject = realm.$GlobalObject;
|
||||
var globalSymbolValue = (0, _index2.Get)(realm, globalObject, "Symbol");
|
||||
|
||||
if (globalSymbolValue === realm.intrinsics.undefined) {
|
||||
if ($$typeof instanceof _index.NumberValue) {
|
||||
return $$typeof.value === 0xeac7;
|
||||
}
|
||||
} else if ($$typeof instanceof _index.SymbolValue) {
|
||||
var symbolFromRegistry = realm.globalSymbolRegistry.find(function (e) {
|
||||
return e.$Symbol === $$typeof;
|
||||
});
|
||||
return symbolFromRegistry !== undefined && symbolFromRegistry.$Key === "react.element";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getReactSymbol(symbolKey, realm) {
|
||||
var reactSymbol = realm.react.symbols.get(symbolKey);
|
||||
if (reactSymbol !== undefined) {
|
||||
return reactSymbol;
|
||||
}
|
||||
var SymbolFor = realm.intrinsics.Symbol.properties.get("for");
|
||||
if (SymbolFor !== undefined) {
|
||||
var SymbolForDescriptor = SymbolFor.descriptor;
|
||||
|
||||
if (SymbolForDescriptor !== undefined) {
|
||||
var SymbolForValue = SymbolForDescriptor.value;
|
||||
if (SymbolForValue !== undefined && typeof SymbolForValue.$Call === "function") {
|
||||
reactSymbol = SymbolForValue.$Call(realm.intrinsics.Symbol, [new _index.StringValue(realm, symbolKey)]);
|
||||
realm.react.symbols.set(symbolKey, reactSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
(0, _invariant2.default)(reactSymbol instanceof _index.SymbolValue, "Symbol(\"" + symbolKey + "\") could not be found in realm");
|
||||
return reactSymbol;
|
||||
}
|
||||
|
||||
function isTagName(ast) {
|
||||
return ast.type === "JSXIdentifier" && /^[a-z]|\-/.test(ast.name);
|
||||
}
|
||||
|
||||
function isReactComponent(name) {
|
||||
return name.length > 0 && name[0] === name[0].toUpperCase();
|
||||
}
|
||||
|
||||
function valueIsClassComponent(realm, value) {
|
||||
if (!(value instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
if (value.$Prototype instanceof _index.ObjectValue) {
|
||||
var prototype = (0, _index2.Get)(realm, value.$Prototype, "prototype");
|
||||
if (prototype instanceof _index.ObjectValue) {
|
||||
return prototype.properties.has("isReactComponent");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// logger isn't typed otherwise it will increase flow cycle length :()
|
||||
function valueIsReactLibraryObject(realm, value, logger) {
|
||||
if (realm.react.reactLibraryObject === value) {
|
||||
return true;
|
||||
}
|
||||
// we check that the object is the React or React-like library by checking for
|
||||
// core properties that should exist on it
|
||||
var reactVersion = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "version");
|
||||
}, undefined, false);
|
||||
if (!(reactVersion instanceof _index.StringValue)) {
|
||||
return false;
|
||||
}
|
||||
var reactCreateElement = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "createElement");
|
||||
}, undefined, false);
|
||||
if (!(reactCreateElement instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
var reactCloneElement = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "cloneElement");
|
||||
}, undefined, false);
|
||||
if (!(reactCloneElement instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
var reactIsValidElement = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "isValidElement");
|
||||
}, undefined, false);
|
||||
if (!(reactIsValidElement instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
var reactComponent = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "Component");
|
||||
}, undefined, false);
|
||||
if (!(reactComponent instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
var reactChildren = logger.tryQuery(function () {
|
||||
return (0, _index2.Get)(realm, value, "Children");
|
||||
}, undefined, false);
|
||||
if (!(reactChildren instanceof _index.ObjectValue)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function valueIsLegacyCreateClassComponent(realm, value) {
|
||||
if (!(value instanceof _index.FunctionValue)) {
|
||||
return false;
|
||||
}
|
||||
var prototype = (0, _index2.Get)(realm, value, "prototype");
|
||||
|
||||
if (prototype instanceof _index.ObjectValue) {
|
||||
return prototype.properties.has("__reactAutoBindPairs");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function addKeyToReactElement(realm, reactSerializerState, reactElement) {
|
||||
// we need to apply a key when we're branched
|
||||
var currentKeyValue = (0, _index2.Get)(realm, reactElement, "key") || realm.intrinsics.null;
|
||||
var uniqueKey = getUniqueReactElementKey("", reactSerializerState.usedReactElementKeys);
|
||||
var newKeyValue = new _index.StringValue(realm, uniqueKey);
|
||||
if (currentKeyValue !== realm.intrinsics.null) {
|
||||
newKeyValue = (0, _BinaryExpression.computeBinary)(realm, "+", currentKeyValue, newKeyValue);
|
||||
}
|
||||
// TODO: This might not be safe in DEV because these objects are frozen (Object.freeze).
|
||||
// We should probably go behind the scenes in this case to by-pass that.
|
||||
reactElement.$Set("key", newKeyValue, reactElement);
|
||||
}
|
||||
// we create a unique key for each JSXElement to prevent collisions
|
||||
// otherwise React will detect a missing/conflicting key at runtime and
|
||||
// this can break the reconcilation of JSXElements in arrays
|
||||
function getUniqueReactElementKey(index, usedReactElementKeys) {
|
||||
var key = void 0;
|
||||
do {
|
||||
key = Math.random().toString(36).replace(/[^a-z]+/g, "").substring(0, 2);
|
||||
} while (usedReactElementKeys.has(key));
|
||||
usedReactElementKeys.add(key);
|
||||
if (index !== undefined) {
|
||||
return "" + key + index;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
// a helper function to map over ArrayValues
|
||||
function mapOverArrayValue(realm, array, mapFunc) {
|
||||
var lengthValue = (0, _index2.Get)(realm, array, "length");
|
||||
(0, _invariant2.default)(lengthValue instanceof _index.NumberValue, "Invalid length on ArrayValue during reconcilation");
|
||||
var length = lengthValue.value;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var elementProperty = array.properties.get("" + i);
|
||||
var elementPropertyDescriptor = elementProperty && elementProperty.descriptor;
|
||||
(0, _invariant2.default)(elementPropertyDescriptor, "Invalid ArrayValue[" + i + "] descriptor");
|
||||
var elementValue = elementPropertyDescriptor.value;
|
||||
if (elementValue instanceof _index.Value) {
|
||||
mapFunc(elementValue, elementPropertyDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertSimpleClassComponentToFunctionalComponent(realm, componentType, additionalFunctionEffects) {
|
||||
var prototype = componentType.properties.get("prototype");
|
||||
(0, _invariant2.default)(prototype);
|
||||
(0, _invariant2.default)(prototype.descriptor);
|
||||
prototype.descriptor.configurable = true;
|
||||
_singletons.Properties.DeletePropertyOrThrow(realm, componentType, "prototype");
|
||||
// set the prototype back to an object
|
||||
componentType.$Prototype = realm.intrinsics.FunctionPrototype;
|
||||
// give the function the functional components params
|
||||
componentType.$FormalParameters = [t.identifier("props"), t.identifier("context")];
|
||||
// add a transform to occur after the additional function has serialized the body of the class
|
||||
additionalFunctionEffects.transforms.push(function (body) {
|
||||
// as this was a class before and is now a functional component, we need to replace
|
||||
// this.props and this.context to props and context, via the function arugments
|
||||
var funcNode = t.functionExpression(null, [], t.blockStatement(body));
|
||||
|
||||
(0, _babelTraverse2.default)(t.file(t.program([t.expressionStatement(funcNode)])), {
|
||||
"Identifier|ThisExpression": function IdentifierThisExpression(path) {
|
||||
var node = path.node;
|
||||
if (t.isIdentifier(node) && node.name === "this" || t.isThisExpression(node)) {
|
||||
var parentPath = path.parentPath;
|
||||
var parentNode = parentPath.node;
|
||||
|
||||
if (t.isMemberExpression(parentNode)) {
|
||||
// remove the "this" from the member
|
||||
parentPath.replaceWith(parentNode.property);
|
||||
} else {
|
||||
throw new _errors.FatalError("conversion of a simple class component to functional component failed due to \"this\" not being replaced");
|
||||
}
|
||||
}
|
||||
}
|
||||
}, undefined, undefined, undefined);
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
Reference in New Issue
Block a user