Skip to content

Commit ac79f8e

Browse files
authored
Check usage of arguments in methods (#250)
* Add failing test for wrong `arguments` transform * Check usage of `arguments` in methods Fixes #163. Although the issue mentions `class` transform, the problem likely was in the `manual-bind-to-arrow` transform; `class` transform had checks to avoid function transformation when `arguments` object was used in a method. * Moved the `doesNotUseArguments` function into a separate util.
1 parent c1fd826 commit ac79f8e

File tree

6 files changed

+62
-25
lines changed

6 files changed

+62
-25
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Component extends React.Component {
2+
constructor() {
3+
super();
4+
this.onClick = this.onClick.bind(this);
5+
}
6+
7+
onClick() {
8+
if (fn) {
9+
fn.apply(this, Array.prototype.slice.call(arguments, 1))
10+
}
11+
}
12+
}

transforms/__testfixtures__/manual-bind-to-arrow/manual-bind-to-arrow11.output.js

Whitespace-only changes.

transforms/__tests__/manual-bind-to-arrow-test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright 2015-present, Facebook, Inc.
33
*
44
* This source code is licensed under the MIT license found in the
5-
* LICENSE file in the root directory of this source tree.
5+
* LICENSE file in the root directory of this source tree.
66
*
77
*/
88

@@ -26,7 +26,8 @@ var TESTS = [
2626
7,
2727
8,
2828
9,
29-
10
29+
10,
30+
11
3031
];
3132

3233
TESTS.forEach(test => {

transforms/class.js

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = (file, api, options) => {
1515

1616
require('./utils/array-polyfills');
1717
const ReactUtils = require('./utils/ReactUtils')(j);
18+
const doesNotUseArguments = require('./utils/doesNotUseArguments')(j);
1819

1920
const printOptions = options.printOptions || {
2021
quote: 'single',
@@ -236,26 +237,6 @@ module.exports = (file, api, options) => {
236237
return true;
237238
};
238239

239-
const doesNotUseArguments = classPath => {
240-
const hasArguments =
241-
j(classPath)
242-
.find(j.Identifier, { name: 'arguments' })
243-
.size() > 0;
244-
if (hasArguments) {
245-
console.warn(
246-
file.path +
247-
': `' +
248-
ReactUtils.directlyGetComponentName(classPath) +
249-
'` ' +
250-
'was skipped because `arguments` was found in your functions. ' +
251-
'Arrow functions do not expose an `arguments` object; ' +
252-
'consider changing to use ES6 spread operator and re-run this script.'
253-
);
254-
return false;
255-
}
256-
return true;
257-
};
258-
259240
const isGetInitialStateConstructorSafe = getInitialState => {
260241
if (!getInitialState) {
261242
return true;

transforms/manual-bind-to-arrow.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
export default function transformer(file, api, options) {
2323
const j = api.jscodeshift;
24+
const doesNotUseArguments = require('./utils/doesNotUseArguments')(j);
2425

2526
const printOptions = options.printOptions || {};
2627
var root = j(file.source);
@@ -114,16 +115,18 @@ export default function transformer(file, api, options) {
114115
.filter(
115116
path =>
116117
path.node.key.type === 'Identifier' &&
117-
path.node.key.name === methodName
118+
path.node.key.name === methodName &&
119+
doesNotUseArguments(path, file.path)
118120
);
119121

120122
// Do not remove the binding if there's no corresponding method to turn
121-
// into an arrow function
123+
// into an arrow function, or if the method uses `arguments` keyword inside
124+
// it.
122125
if (methods.size() === 0) {
123126
return;
124127
}
125128
methods.replaceWith(path => createArrowProperty(path.node));
126-
129+
127130
// Remove the line
128131
// this.method = this.method.bind(this);
129132
j(path.parentPath).remove();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = function(j) {
12+
const ReactUtils = require('./ReactUtils')(j);
13+
14+
const doesNotUseArguments = (path, filepath) => {
15+
const hasArguments =
16+
j(path)
17+
.find(j.Identifier, { name: 'arguments' })
18+
.size() > 0;
19+
20+
if (hasArguments) {
21+
var warnStr = '';
22+
23+
if (filepath) {
24+
warnStr += filepath + ': ';
25+
}
26+
27+
warnStr += '`' + ReactUtils.directlyGetComponentName(path) + '` ' +
28+
'was skipped because `arguments` was found in your functions. ' +
29+
'Arrow functions do not expose an `arguments` object; ' +
30+
'consider changing to use ES6 spread operator and re-run this script.';
31+
32+
console.warn(warnStr);
33+
34+
return false;
35+
}
36+
return true;
37+
};
38+
39+
return doesNotUseArguments;
40+
};

0 commit comments

Comments
 (0)