Merge pull request #208 from muffinresearch/add-widget-js-rule
Detect require() of deprecated widget module
This commit is contained in:
Коммит
bc57807cd7
|
@ -19,9 +19,10 @@ To update it edit `docs/rules.md` in the
|
|||
| :x: | warning | called_dangerous_global | | `%s` called in potentially dangerous manner' | | | | |
|
||||
| :white_check_mark: | error? | eval | | In order to prevent vulnerabilities, the `setTimeout` 'and `setInterval` functions should be called only with function expressions as their first argument. | | [testcases/javascript/actions.py](https://github.com/mozilla/amo-validator/blob/7a8011aba8bf8c665aef2b51eb26d0697b3e19c3/validator/testcases/javascript/actions.py#L488) | | EVAL_STRING_ARG |
|
||||
| :x: | warning | low_level_module (not from src) | | Usage of low-level or non-SDK interface | | | | |
|
||||
| :x: | warning | widget | | Use of deprecated SDK module | | | | |
|
||||
| :white_check_mark: | warning | widget | | Use of deprecated SDK module | | | null | DEPREC_SDK_MOD_WIDGET |
|
||||
| :negative_squared_cross_mark: | notice | \_readonly_top | | window.top is a reserved variable | | | ('testcases_javascript_actions', '_readonly_top' | **Removed** |
|
||||
| :x: | warning | global_overwrite | | Global variable overwrite | | | | |
|
||||
| :white_check_mark: | warning | unexpected_global_arg [NEW] | | Unexpected global passed as an argument | | | null | UNEXPECTED_GLOGAL_ARG |
|
||||
|
||||
### Call definitions
|
||||
| Done? | MsgType | Rule name | Addon type | Description | File Type | Source ref | Old Code | New Code |
|
||||
|
|
|
@ -107,3 +107,23 @@ export const EVAL_STRING_ARG = {
|
|||
called only with function expressions as their first argument`),
|
||||
legacyCode: ['javascript', 'dangerous_global', 'eval'],
|
||||
};
|
||||
|
||||
export const DEPREC_SDK_MOD_WIDGET = {
|
||||
code: 'DEPREC_SDK_MOD_WIDGET',
|
||||
message: _('Use of deprecated SDK module'),
|
||||
description: _(singleLineString`The 'widget' module has been deprecated
|
||||
due to a number of performance and usability issues, and has been
|
||||
removed from the SDK as of Firefox 40. Please use the
|
||||
'sdk/ui/button/action' or 'sdk/ui/button/toggle' module instead.
|
||||
See https://developer.mozilla.org/Add-ons/SDK/High-Level_APIs/ui
|
||||
for more information.`),
|
||||
legacyCode: null,
|
||||
};
|
||||
|
||||
export const UNEXPECTED_GLOGAL_ARG = {
|
||||
code: 'UNEXPECTED_GLOGAL_ARG',
|
||||
message: _('Unexpected global passed as an argument'),
|
||||
description: _(singleLineString`Passing a global as an argument
|
||||
is not recommended. Please make this a var instead.`),
|
||||
legacyCode: null,
|
||||
};
|
||||
|
|
|
@ -2,10 +2,11 @@ import { ESLINT_ERROR, ESLINT_WARNING } from 'const';
|
|||
|
||||
export default {
|
||||
banned_identifiers: ESLINT_WARNING,
|
||||
eval_string_arg: ESLINT_ERROR,
|
||||
mozindexeddb: ESLINT_ERROR,
|
||||
mozindexeddb_property: ESLINT_WARNING,
|
||||
opendialog_remote_uri: ESLINT_WARNING,
|
||||
opendialog_nonlit_uri: ESLINT_WARNING,
|
||||
opendialog_remote_uri: ESLINT_WARNING,
|
||||
shallow_wrapper: ESLINT_WARNING,
|
||||
eval_string_arg: ESLINT_ERROR,
|
||||
widget_module: ESLINT_WARNING,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import { DEPREC_SDK_MOD_WIDGET, UNEXPECTED_GLOGAL_ARG } from 'messages';
|
||||
import { getVariable } from 'utils';
|
||||
|
||||
const WIDGET_PATH = 'sdk/widget';
|
||||
|
||||
/*
|
||||
* This rule will detect use of `require()` with the first arg being either
|
||||
* a literal that matches the widget module or var pointing at a literal.
|
||||
*
|
||||
* TODO: This rule looks to be related to compat - based on the old tests.
|
||||
* TODO: This rule should only be run for jetpack.
|
||||
*
|
||||
*/
|
||||
export default function(context) {
|
||||
return {
|
||||
CallExpression: function(node) {
|
||||
var requiresWidgetMod = false;
|
||||
if (node.callee.name === 'require' &&
|
||||
node.arguments &&
|
||||
node.arguments.length) {
|
||||
|
||||
var firstArg = node.arguments[0];
|
||||
|
||||
// Find a literal string value passed to the
|
||||
// the require function.
|
||||
if (firstArg.type === 'Literal' &&
|
||||
firstArg.value === WIDGET_PATH) {
|
||||
requiresWidgetMod = true;
|
||||
}
|
||||
|
||||
// Detect a var matching the widget module
|
||||
// being passed as the first arg of require().
|
||||
if (firstArg.type === 'Identifier') {
|
||||
var pathVar = getVariable(context, firstArg.name);
|
||||
if (pathVar && pathVar.type === 'Literal' &&
|
||||
pathVar.value === WIDGET_PATH) {
|
||||
requiresWidgetMod = true;
|
||||
}
|
||||
|
||||
if (typeof pathVar === 'undefined') {
|
||||
// We infer this is probably a global.
|
||||
return context.report(node, UNEXPECTED_GLOGAL_ARG.code);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresWidgetMod) {
|
||||
return context.report(node, DEPREC_SDK_MOD_WIDGET.code);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import { VALIDATION_WARNING } from 'const';
|
||||
import JavaScriptScanner from 'scanners/javascript';
|
||||
import * as messages from 'messages';
|
||||
|
||||
|
||||
describe('widget_module', () => {
|
||||
|
||||
it('should catch require of sdk/widget as literal', () => {
|
||||
var code = `require("sdk/widget").Widget({
|
||||
id: "mozilla-icon",
|
||||
label: "My Mozilla Widget",
|
||||
contentURL: "http://www.mozilla.org/favicon.ico"
|
||||
});`;
|
||||
var jsScanner = new JavaScriptScanner(code, 'badcode.js');
|
||||
|
||||
return jsScanner.scan()
|
||||
.then((validationMessages) => {
|
||||
assert.equal(validationMessages.length, 1);
|
||||
assert.equal(validationMessages[0].code,
|
||||
messages.DEPREC_SDK_MOD_WIDGET.code);
|
||||
assert.equal(validationMessages[0].type, VALIDATION_WARNING);
|
||||
});
|
||||
});
|
||||
|
||||
it('should catch require of sdk/widget as var', () => {
|
||||
var code = `var path = 'sdk/widget';
|
||||
require(path).Widget({
|
||||
id: "mozilla-icon",
|
||||
label: "My Mozilla Widget",
|
||||
contentURL: "http://www.mozilla.org/favicon.ico"
|
||||
});`;
|
||||
var jsScanner = new JavaScriptScanner(code, 'badcode.js');
|
||||
|
||||
return jsScanner.scan()
|
||||
.then((validationMessages) => {
|
||||
assert.equal(validationMessages.length, 1);
|
||||
assert.equal(validationMessages[0].code,
|
||||
messages.DEPREC_SDK_MOD_WIDGET.code);
|
||||
assert.equal(validationMessages[0].type, VALIDATION_WARNING);
|
||||
});
|
||||
});
|
||||
|
||||
it('should catch require() first arg being a global', () => {
|
||||
var code = `widgetPath = 'sdk/widget';
|
||||
require(widgetPath).Widget({
|
||||
id: "mozilla-icon",
|
||||
label: "My Mozilla Widget",
|
||||
contentURL: "http://www.mozilla.org/favicon.ico"
|
||||
});`;
|
||||
var jsScanner = new JavaScriptScanner(code, 'badcode.js');
|
||||
|
||||
return jsScanner.scan()
|
||||
.then((validationMessages) => {
|
||||
assert.equal(validationMessages.length, 1);
|
||||
assert.equal(validationMessages[0].code,
|
||||
messages.UNEXPECTED_GLOGAL_ARG.code);
|
||||
assert.equal(validationMessages[0].type, VALIDATION_WARNING);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Загрузка…
Ссылка в новой задаче