react-native-web-headroom
Version:
React Native Web Headroom
174 lines (128 loc) • 5.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = isStatelessComponent;
var _getPropertyValuePath = require('./getPropertyValuePath');
var _getPropertyValuePath2 = _interopRequireDefault(_getPropertyValuePath);
var _isReactComponentClass = require('./isReactComponentClass');
var _isReactComponentClass2 = _interopRequireDefault(_isReactComponentClass);
var _isReactCreateClassCall = require('./isReactCreateClassCall');
var _isReactCreateClassCall2 = _interopRequireDefault(_isReactCreateClassCall);
var _isReactCreateElementCall = require('./isReactCreateElementCall');
var _isReactCreateElementCall2 = _interopRequireDefault(_isReactCreateElementCall);
var _isReactCloneElementCall = require('./isReactCloneElementCall');
var _isReactCloneElementCall2 = _interopRequireDefault(_isReactCloneElementCall);
var _isReactChildrenElementCall = require('./isReactChildrenElementCall');
var _isReactChildrenElementCall2 = _interopRequireDefault(_isReactChildrenElementCall);
var _recast = require('recast');
var _recast2 = _interopRequireDefault(_recast);
var _resolveToValue = require('./resolveToValue');
var _resolveToValue2 = _interopRequireDefault(_resolveToValue);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* Copyright (c) 2015, 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 types = _recast2.default.types.namedTypes;
var reNonLexicalBlocks = /^If|^Else|^Switch/;
var validPossibleStatelessComponentTypes = ['Property', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'];
function isJSXElementOrReactCreateElement(path) {
return path.node.type === 'JSXElement' || path.node.type === 'CallExpression' && (0, _isReactCreateElementCall2.default)(path) || path.node.type === 'CallExpression' && (0, _isReactCloneElementCall2.default)(path) || path.node.type === 'CallExpression' && (0, _isReactChildrenElementCall2.default)(path);
}
function returnsJSXElementOrReactCreateElementCall(path) {
var visited = false;
// early exit for ArrowFunctionExpressions
if (isJSXElementOrReactCreateElement(path.get('body'))) {
return true;
}
function isSameBlockScope(p) {
var block = p;
do {
block = block.parent;
// jump over non-lexical blocks
if (reNonLexicalBlocks.test(block.parent.node.type)) {
block = block.parent;
}
} while (!types.BlockStatement.check(block.node) && /Function|Property/.test(block.parent.parent.node.type) && !reNonLexicalBlocks.test(block.parent.node.type));
// special case properties
if (types.Property.check(path.node)) {
return block.node === path.get('value', 'body').node;
}
return block.node === path.get('body').node;
}
_recast2.default.visit(path, {
visitReturnStatement(returnPath) {
var resolvedPath = (0, _resolveToValue2.default)(returnPath.get('argument'));
if (isJSXElementOrReactCreateElement(resolvedPath) && isSameBlockScope(returnPath)) {
visited = true;
return false;
}
if (resolvedPath.node.type === 'CallExpression') {
var calleeValue = (0, _resolveToValue2.default)(resolvedPath.get('callee'));
if (returnsJSXElementOrReactCreateElementCall(calleeValue)) {
visited = true;
return false;
}
var resolvedValue = void 0;
var namesToResolve = [calleeValue.get('property')];
if (calleeValue.node.type === 'MemberExpression') {
if (calleeValue.get('object').node.type === 'Identifier') {
resolvedValue = (0, _resolveToValue2.default)(calleeValue.get('object'));
} else if (types.MemberExpression.check(calleeValue.node)) {
do {
calleeValue = calleeValue.get('object');
namesToResolve.unshift(calleeValue.get('property'));
} while (types.MemberExpression.check(calleeValue.node));
resolvedValue = (0, _resolveToValue2.default)(calleeValue.get('object'));
}
}
if (resolvedValue && types.ObjectExpression.check(resolvedValue.node)) {
var resolvedMemberExpression = namesToResolve.reduce(function (result, path) {
// eslint-disable-line no-shadow
if (!path) {
return result;
}
if (result) {
result = (0, _getPropertyValuePath2.default)(result, path.node.name);
if (result && types.Identifier.check(result.node)) {
return (0, _resolveToValue2.default)(result);
}
}
return result;
}, resolvedValue);
if (!resolvedMemberExpression || returnsJSXElementOrReactCreateElementCall(resolvedMemberExpression)) {
visited = true;
return false;
}
}
}
this.traverse(returnPath);
}
});
return visited;
}
/**
* Returns `true` if the path represents a function which returns a JSXElement
*/
function isStatelessComponent(path) {
var node = path.node;
if (validPossibleStatelessComponentTypes.indexOf(node.type) === -1) {
return false;
}
if (node.type === 'Property') {
if ((0, _isReactCreateClassCall2.default)(path.parent) || (0, _isReactComponentClass2.default)(path.parent)) {
return false;
}
}
if (returnsJSXElementOrReactCreateElementCall(path)) {
return true;
}
return false;
}