Skip to content

Commit

Permalink
support all import cases
Browse files Browse the repository at this point in the history
  • Loading branch information
smelukov committed Oct 23, 2018
1 parent 308f35e commit f7b922c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 19 deletions.
65 changes: 50 additions & 15 deletions src/babel.prod.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const RHLPackage = 'react-hot-loader'

function isImportFromRHL(path, name) {
function isImportedFromRHL(path, name) {
const binding = path.scope.getBinding(name)
const bindingType = binding && binding.path.node.type

Expand All @@ -16,44 +16,79 @@ function isImportFromRHL(path, name) {
return false
}

function isRHLContext(file) {
function getRHLContext(file) {
const { modules } = file.metadata
const context = []

if (modules && Array.isArray(modules.imports)) {
const { imports } = modules

for (let i = 0; i < imports.length; i++) {
const { source } = imports[i]
const { source, specifiers } = imports[i]

if (source === RHLPackage) {
return true
for (let j = 0; j < specifiers.length; j++) {
const specifier = specifiers[j]

if (
(specifier.kind === 'named' && specifier.imported === 'hot') ||
specifier.kind === 'namespace'
) {
context.push(specifier)
}
}
}
}
}

return false
return context.length ? context : null
}

export default function plugin() {
function handleCall(path) {
if (!this.cancel) {
if (
path.node.callee.name === 'hot' &&
// ensure that this is `hot` from RHL
isImportFromRHL(path, 'hot') &&
path.parent.type === 'CallExpression' &&
path.parent.arguments[0] &&
path.parent.arguments[0].type === 'Identifier'
) {
path.parentPath.replaceWith(path.parent.arguments[0])
for (let i = 0; i < this.rhlContext.length; i++) {
const specifier = this.rhlContext[i]

if (specifier.kind === 'named') {
if (
path.node.callee.name === specifier.local &&
// ensure that this is `hot` from RHL
isImportedFromRHL(path, specifier.local) &&
path.parent.type === 'CallExpression' &&
path.parent.arguments[0] &&
path.parent.arguments[0].type === 'Identifier'
) {
path.parentPath.replaceWith(path.parent.arguments[0])
break
}
} else if (specifier.kind === 'namespace') {
if (
path.node.callee.callee &&
path.node.callee.callee.type === 'MemberExpression' &&
path.node.callee.callee.object.type === 'Identifier' &&
path.node.callee.callee.object.name === specifier.local &&
// ensure that this is `hot` from RHL
isImportedFromRHL(path, specifier.local) &&
path.node.callee.callee.property.type === 'Identifier' &&
path.node.callee.callee.property.name === 'hot' &&
path.node.arguments[0] &&
path.node.arguments[0].type === 'Identifier'
) {
path.replaceWith(path.node.arguments[0])
break
}
}
}
}
}

return {
pre() {
// ignore files that do not use RHL
if (!isRHLContext(this.file)) {
this.rhlContext = getRHLContext(this.file)

if (!this.rhlContext) {
this.cancel = true
}
},
Expand Down
18 changes: 16 additions & 2 deletions test/__babel_fixtures__/drop-hot.prod.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import React from 'react'
import { hot } from 'react-hot-loader'
import { hot, foo } from 'react-hot-loader'
import { hot as namedHot, foo as namedFoo } from 'react-hot-loader'
import { hot as namedHot2 } from 'react-hot-loader'
import * as RHL from 'react-hot-loader'
import * as RHL2 from 'react-hot-loader'

const App = () => <div>Hello World!</div>

export default hot(module)(App)
const a = hot(module)(App);
const b = namedHot(module)(App);
const c = namedHot2(module)(App);
const d = RHL.hot(module)(App);
const e = RHL2.hot(module)(App);

foo(module)(App);
namedFoo(module)(App);
RHL.foo(module)(App);

export { a, b, c, d, e };
46 changes: 44 additions & 2 deletions test/__snapshots__/babel.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -990,13 +990,20 @@ exports[`babel Targetting "es2015" tags potential React components drop hot.prod
Object.defineProperty(exports, \\"__esModule\\", {
value: true
});
exports.e = exports.d = exports.c = exports.b = exports.a = undefined;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactHotLoader = require('react-hot-loader');
var RHL = _interopRequireWildcard(_reactHotLoader);
var RHL2 = _interopRequireWildcard(_reactHotLoader);
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 }; }
var App = function App() {
Expand All @@ -1007,7 +1014,21 @@ var App = function App() {
);
};
exports.default = App;"
var a = App;
var b = App;
var c = App;
var d = App;
var e = App;
(0, _reactHotLoader.foo)(module)(App);
(0, _reactHotLoader.foo)(module)(App);
RHL.foo(module)(App);
exports.a = a;
exports.b = b;
exports.c = c;
exports.d = d;
exports.e = e;"
`;

exports[`babel Targetting "es2015" tags potential React components issue 246.js 1`] = `
Expand Down Expand Up @@ -1820,13 +1841,20 @@ exports[`babel Targetting "modern" tags potential React components drop hot.prod
Object.defineProperty(exports, \\"__esModule\\", {
value: true
});
exports.e = exports.d = exports.c = exports.b = exports.a = undefined;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactHotLoader = require('react-hot-loader');
var RHL = _interopRequireWildcard(_reactHotLoader);
var RHL2 = _interopRequireWildcard(_reactHotLoader);
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 }; }
const App = () => _react2.default.createElement(
Expand All @@ -1835,7 +1863,21 @@ const App = () => _react2.default.createElement(
'Hello World!'
);
exports.default = App;"
const a = App;
const b = App;
const c = App;
const d = App;
const e = App;
(0, _reactHotLoader.foo)(module)(App);
(0, _reactHotLoader.foo)(module)(App);
RHL.foo(module)(App);
exports.a = a;
exports.b = b;
exports.c = c;
exports.d = d;
exports.e = e;"
`;
exports[`babel Targetting "modern" tags potential React components issue 246.js 1`] = `
Expand Down

0 comments on commit f7b922c

Please sign in to comment.