"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