Files
flipper/static/transforms/flipper-requires.js
Daniel Büchele 992ad68517 error plugin import from outside
Summary:
Plugins can not require files outside their folder, to make sure they don't pull in any dependencies from Flipper which are not exported by the main app.

However, those imports simply resolve to `undefined`. This diff adds a check in the babel-transform for plugins and throws an error if something from outside the plugin is required.

Reviewed By: passy

Differential Revision: D10297980

fbshipit-source-id: 1606f3211103281f9f4aa7bb2f3ca4d085d0ea1b
2018-10-11 07:11:18 -07:00

72 lines
2.1 KiB
JavaScript

/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
const {resolve, dirname} = require('path');
// do not apply this transform for these paths
const EXCLUDE_PATHS = [
'/node_modules/react-devtools-core/',
'relay-devtools/DevtoolsUI',
];
function isExcludedPath(path) {
for (const epath of EXCLUDE_PATHS) {
if (path.indexOf(epath) > -1) {
return true;
}
}
return false;
} // $FlowFixMe
module.exports = ({types: t}) => ({
visitor: {
// $FlowFixMe
CallExpression(path, state) {
if (isExcludedPath(state.file.opts.filename)) {
return;
}
const node = path.node;
const args = node.arguments || [];
if (
node.callee.name === 'require' &&
args.length === 1 &&
t.isStringLiteral(args[0])
) {
if (args[0].value === 'flipper') {
path.replaceWith(t.identifier('window.Flipper'));
} else if (args[0].value === 'react') {
path.replaceWith(t.identifier('window.React'));
} else if (args[0].value === 'react-dom') {
path.replaceWith(t.identifier('window.ReactDOM'));
} else if (
// require a file not a pacakge
args[0].value.indexOf('/') > -1 &&
// in the plugin itself and not inside one of its dependencies
state.file.opts.filename.indexOf('node_modules') === -1 &&
// the resolved path for this file is outside the plugins root
!resolve(dirname(state.file.opts.filename), args[0].value).startsWith(
state.file.opts.root,
)
) {
throw new Error(
'Plugins cannot require files from outside their folder.',
);
}
}
},
Identifier(path, state) {
if (
path.node.name === 'React' &&
path.parentPath.node.id !== path.node &&
!isExcludedPath(state.file.opts.filename)
) {
path.replaceWith(t.identifier('window.React'));
}
},
},
});