UNPKG

@locker/eslint-plugin-unsafe-types

Version:
257 lines (226 loc) 9.35 kB
/** * @fileoverview Tests for no-implied-eval rule. * Original source code https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-implied-eval.js * @author Lightning Web Security Team */ 'use strict'; //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/unsafe-implied-eval'); const env = { browser: true, commonjs: true, es2024: true, jquery: true }; //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ const ruleTester = new RuleTester(); ruleTester.run('no-implied-eval', rule, { valid: [ 'setTimeout();', 'setTimeout;', 'setTimeout = foo;', 'window.setTimeout;', 'window.setTimeout = foo;', "window['setTimeout'];", "window['setTimeout'] = foo;", 'global.setTimeout;', 'global.setTimeout = foo;', "global['setTimeout'];", "global['setTimeout'] = foo;", "globalThis['setTimeout'] = foo;", "window.setTimeout($A.lockerService.restricted.createScript('foo'))", "window.setInterval($A.lockerService.restricted.createScript('foo'))", "window['setTimeout']($A.lockerService.restricted.createScript('foo'))", "window['setInterval']($A.lockerService.restricted.createScript('foo'))", "window.setTimeout($A.lockerService.restricted.createScript('foo'))", "window.setInterval($A.lockerService.restricted.createScript('foo'))", "window['setTimeout']($A.lockerService.restricted.createScript('foo'))", "window['setInterval']($A.lockerService.restricted.createScript('foo'))", "global.setTimeout($A.lockerService.restricted.createScript('foo'))", "global.setInterval($A.lockerService.restricted.createScript('foo'))", "global['setTimeout']($A.lockerService.restricted.createScript('foo'))", "global['setInterval']($A.lockerService.restricted.createScript('foo'))", "globalThis.setTimeout($A.lockerService.restricted.createScript('foo'))", "globalThis['setInterval']($A.lockerService.restricted.createScript('foo'))", "window[`SetTimeOut`]('foo', 100);", "global[`SetTimeOut`]('foo', 100);", // eslint-disable-next-line no-template-curly-in-string "global[`setTimeout${foo}`]('foo', 100);", // eslint-disable-next-line no-template-curly-in-string "global[`setTimeout${foo}`]('foo', 100);", // eslint-disable-next-line no-template-curly-in-string "globalThis[`setTimeout${foo}`]('foo', 100);", // normal usage 'setTimeout(function() { x = 1; }, 100);', 'setInterval(function() { x = 1; }, 100)', 'execScript(function() { x = 1; }, 100)', 'window.setTimeout(function() { x = 1; }, 100);', 'window.setInterval(function() { x = 1; }, 100);', 'window.execScript(function() { x = 1; }, 100);', 'window.setTimeout(foo, 100);', 'window.setInterval(foo, 100);', 'window.execScript(foo, 100);', 'global.setTimeout(function() { x = 1; }, 100);', 'global.setInterval(function() { x = 1; }, 100);', 'global.execScript(function() { x = 1; }, 100);', 'global.setTimeout(foo, 100);', 'global.setInterval(foo, 100);', 'global.execScript(foo, 100);', 'globalThis.setTimeout(foo, 100);', // only checks on top-level statements or window.* "foo.setTimeout('hi')", // identifiers are fine 'setTimeout(foo, 10)', 'setInterval(1, 10)', 'execScript(2)', // as are function expressions 'setTimeout(function() {}, 10)', // setInterval "foo.setInterval('hi')", 'setInterval(foo, 10)', 'setInterval(function() {}, 10)', // execScript "foo.execScript('hi')", 'execScript(foo)', 'execScript(function() {})', // a binary plus on non-strings doesn't guarantee a string 'setTimeout(foo + bar, 10)', // doesn't check anything but the first argument "setTimeout(foobar, 'buzz')", "setTimeout(foobar, foo + 'bar')", // only checks immediate subtrees of the argument "setTimeout(function() { return 'foobar'; }, 10)", // https://github.com/eslint/eslint/issues/7821 "setTimeoutFooBar('Foo Bar')", "foo.window.setTimeout('foo', 100);", "foo.global.setTimeout('foo', 100);", "var window; window.setTimeout('foo', 100);", "var global; global.setTimeout('foo', 100);", "function foo(window) { window.setTimeout('foo', 100); }", "function foo(global) { global.setTimeout('foo', 100); }", "foo('', window.setTimeout);", "foo('', global.setTimeout);", ].map((code) => ({ code, env })), invalid: [ "globalThis['setInterval']('foo')", 'setTimeout("x = 1;");', 'setTimeout("x = 1;", 100);', 'setInterval("x = 1;");', 'execScript("x = 1;");', "const s = 'x=1'; setTimeout(s, 100);", "setTimeout(String('x=1'), 100);", // member expressions "window.setTimeout('foo')", "window.setInterval('foo')", "window['setTimeout']('foo')", "window['setInterval']('foo')", "window[`setInterval`]('foo')", "window.window['setInterval']('foo')", "global.setTimeout('foo')", "global.setInterval('foo')", "global['setTimeout']('foo')", "global['setInterval']('foo')", "global[`setInterval`]('foo')", "global.global['setInterval']('foo')", "globalThis.setTimeout('foo')", "globalThis.setInterval('foo')", // template literals // eslint-disable-next-line no-template-curly-in-string 'setTimeout(`foo${bar}`)', // eslint-disable-next-line no-template-curly-in-string 'window.setTimeout(`foo${bar}`)', // eslint-disable-next-line no-template-curly-in-string 'window.window.setTimeout(`foo${bar}`)', // eslint-disable-next-line no-template-curly-in-string 'global.global.setTimeout(`foo${bar}`)', // string concatenation "setTimeout('foo' + bar)", "setTimeout(foo + 'bar')", 'setTimeout(`foo` + bar)', "setTimeout(1 + ';' + 1)", "window.setTimeout('foo' + bar)", "window.setTimeout(foo + 'bar')", 'window.setTimeout(`foo` + bar)', "window.setTimeout(1 + ';' + 1)", "global.setTimeout('foo' + bar)", "global.setTimeout(foo + 'bar')", 'global.setTimeout(`foo` + bar)', "global.setTimeout(1 + ';' + 1)", "global.global.setTimeout(1 + ';' + 1)", "globalThis.setTimeout('foo' + bar)", // gives the correct node when dealing with nesting { code: "setTimeout('foo' + (function() {\n" + ' setTimeout(helper);\n' + " execScript('str');\n" + " return 'bar';\n" + '})())', errors: [ { messageId: 'impliedEval', type: 'CallExpression', line: 1, }, // no error on line 2 { messageId: 'impliedEval', type: 'CallExpression', line: 3, }, ], }, { code: "window.setTimeout('foo' + (function() {\n" + ' setTimeout(helper);\n' + " window.execScript('str');\n" + " return 'bar';\n" + '})())', errors: [ { messageId: 'impliedEval', type: 'CallExpression', line: 1, }, // no error on line 2 { messageId: 'impliedEval', type: 'CallExpression', line: 3, }, ], }, { code: "global.setTimeout('foo' + (function() {\n" + ' setTimeout(helper);\n' + " global.execScript('str');\n" + " return 'bar';\n" + '})())', errors: [ { messageId: 'impliedEval', type: 'CallExpression', line: 1, }, // no error on line 2 { messageId: 'impliedEval', type: 'CallExpression', line: 3, }, ], }, // Optional chaining "window?.setTimeout('code', 0)", "(window?.setTimeout)('code', 0)", ].map((code) => { if (typeof code === 'object') { code.env = env; } else { code = { code, env, errors: [{ messageId: 'impliedEval' }] }; } return code; }), });