1 | 'use strict';
|
2 |
|
3 | var _babelTemplate = require('babel-template');
|
4 |
|
5 | var _babelTemplate2 = _interopRequireDefault(_babelTemplate);
|
6 |
|
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
8 |
|
9 | var buildRegistration = (0, _babelTemplate2.default)('__REACT_HOT_LOADER__.register(ID, NAME, FILENAME);');
|
10 | var buildSemi = (0, _babelTemplate2.default)(';');
|
11 |
|
12 |
|
13 |
|
14 | var buildTagger = (0, _babelTemplate2.default)('\nvar UNUSED = (function () {\n if (typeof __REACT_HOT_LOADER__ === \'undefined\') {\n return;\n }\n\n REGISTRATIONS\n})();\n');
|
15 |
|
16 | var buildNewClassProperty = function buildNewClassProperty(t, classPropertyName, newMethodName, isAsync) {
|
17 | var returnExpression = t.callExpression(t.memberExpression(t.thisExpression(), newMethodName), [t.spreadElement(t.identifier('params'))]);
|
18 |
|
19 | if (isAsync) {
|
20 | returnExpression = t.awaitExpression(returnExpression);
|
21 | }
|
22 |
|
23 | var newArrowFunction = t.arrowFunctionExpression([t.restElement(t.identifier('params'))], returnExpression, isAsync);
|
24 | return t.classProperty(classPropertyName, newArrowFunction);
|
25 | };
|
26 |
|
27 | var classPropertyOptOutVistor = {
|
28 | MetaProperty: function MetaProperty(path, state) {
|
29 | var node = path.node;
|
30 |
|
31 |
|
32 | if (node.meta.name === 'new' && node.property.name === 'target') {
|
33 | state.optOut = true;
|
34 | }
|
35 | },
|
36 | ReferencedIdentifier: function ReferencedIdentifier(path, state) {
|
37 | var node = path.node;
|
38 |
|
39 |
|
40 | if (node.name === 'arguments') {
|
41 | state.optOut = true;
|
42 | }
|
43 | }
|
44 | };
|
45 |
|
46 | module.exports = function plugin(args) {
|
47 |
|
48 | if (this && this.callback) {
|
49 | throw new Error('React Hot Loader: You are erroneously trying to use a Babel plugin ' + 'as a Webpack loader. We recommend that you use Babel, ' + 'remove "react-hot-loader/babel" from the "loaders" section ' + 'of your Webpack configuration, and instead add ' + '"react-hot-loader/babel" to the "plugins" section of your .babelrc file. ' + 'If you prefer not to use Babel, replace "react-hot-loader/babel" with ' + '"react-hot-loader/webpack" in the "loaders" section of your Webpack configuration. ');
|
50 | }
|
51 | var t = args.types;
|
52 |
|
53 |
|
54 |
|
55 | if (process.env.NODE_ENV === 'production') {
|
56 | return { visitor: {} };
|
57 | }
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | function shouldRegisterBinding(binding) {
|
63 | var _binding$path = binding.path,
|
64 | type = _binding$path.type,
|
65 | node = _binding$path.node;
|
66 |
|
67 | switch (type) {
|
68 | case 'FunctionDeclaration':
|
69 | case 'ClassDeclaration':
|
70 | case 'VariableDeclaration':
|
71 | return true;
|
72 | case 'VariableDeclarator':
|
73 | {
|
74 | var init = node.init;
|
75 |
|
76 | if (t.isCallExpression(init) && init.callee.name === 'require') {
|
77 | return false;
|
78 | }
|
79 | return true;
|
80 | }
|
81 | default:
|
82 | return false;
|
83 | }
|
84 | }
|
85 |
|
86 | var REGISTRATIONS = Symbol();
|
87 | return {
|
88 | visitor: {
|
89 | ExportDefaultDeclaration: function ExportDefaultDeclaration(path, _ref) {
|
90 | var file = _ref.file;
|
91 |
|
92 |
|
93 |
|
94 | if (path.node.declaration.id) {
|
95 | return;
|
96 | }
|
97 |
|
98 |
|
99 |
|
100 | var id = path.scope.generateUidIdentifier('default');
|
101 | var expression = t.isExpression(path.node.declaration) ? path.node.declaration : t.toExpression(path.node.declaration);
|
102 | path.insertBefore(t.variableDeclaration('const', [t.variableDeclarator(id, expression)]));
|
103 | path.node.declaration = id;
|
104 |
|
105 |
|
106 |
|
107 | path.parent[REGISTRATIONS].push(buildRegistration({
|
108 | ID: id,
|
109 | NAME: t.stringLiteral('default'),
|
110 | FILENAME: t.stringLiteral(file.opts.filename)
|
111 | }));
|
112 | },
|
113 |
|
114 |
|
115 | Program: {
|
116 | enter: function enter(_ref2, _ref3) {
|
117 | var node = _ref2.node,
|
118 | scope = _ref2.scope;
|
119 | var file = _ref3.file;
|
120 |
|
121 | node[REGISTRATIONS] = [];
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | for (var id in scope.bindings) {
|
127 | var binding = scope.bindings[id];
|
128 | if (shouldRegisterBinding(binding)) {
|
129 | node[REGISTRATIONS].push(buildRegistration({
|
130 | ID: binding.identifier,
|
131 | NAME: t.stringLiteral(id),
|
132 | FILENAME: t.stringLiteral(file.opts.filename)
|
133 | }));
|
134 | }
|
135 | }
|
136 |
|
137 | },
|
138 | exit: function exit(_ref4) {
|
139 | var node = _ref4.node,
|
140 | scope = _ref4.scope;
|
141 |
|
142 | var registrations = node[REGISTRATIONS];
|
143 | node[REGISTRATIONS] = null;
|
144 |
|
145 |
|
146 |
|
147 | node.body.push(buildSemi());
|
148 | node.body.push(buildTagger({
|
149 | UNUSED: scope.generateUidIdentifier(),
|
150 | REGISTRATIONS: registrations
|
151 | }));
|
152 | node.body.push(buildSemi());
|
153 | }
|
154 | },
|
155 |
|
156 | Class: function Class(classPath) {
|
157 | var classBody = classPath.get('body');
|
158 |
|
159 | classBody.get('body').forEach(function (path) {
|
160 | if (path.isClassProperty()) {
|
161 | var node = path.node;
|
162 |
|
163 |
|
164 |
|
165 | if (node.static) {
|
166 | return;
|
167 | }
|
168 |
|
169 | var state = {
|
170 | optOut: false
|
171 | };
|
172 |
|
173 | path.traverse(classPropertyOptOutVistor, state);
|
174 |
|
175 | if (state.optOut) {
|
176 | return;
|
177 | }
|
178 |
|
179 |
|
180 | if (node.value && node.value.type === 'ArrowFunctionExpression') {
|
181 | var isAsync = node.value.async;
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | if (isAsync) {
|
189 | return;
|
190 | }
|
191 |
|
192 | var params = node.value.params;
|
193 | var newIdentifier = t.identifier('__' + node.key.name + '__REACT_HOT_LOADER__');
|
194 |
|
195 |
|
196 | var newMethodBody = node.value.body.type === 'BlockStatement' ? node.value.body : t.blockStatement([t.returnStatement(node.value.body)]);
|
197 |
|
198 |
|
199 |
|
200 | var newMethod = t.classMethod('method', newIdentifier, params, newMethodBody);
|
201 | newMethod.async = isAsync;
|
202 | path.insertAfter(newMethod);
|
203 |
|
204 |
|
205 |
|
206 | path.replaceWith(buildNewClassProperty(t, node.key, newIdentifier, isAsync));
|
207 | }
|
208 | }
|
209 | });
|
210 | }
|
211 | }
|
212 | };
|
213 | }; |
\ | No newline at end of file |