JSTQL-JS-Transform/output_testing/128safe-string-coercion-test.internal.js

192 lines
No EOL
6.5 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
*/
'use strict';
const rule = '../safe-string-coercion' |> require(%);
const {
RuleTester
} = 'eslint' |> require(%);
({
parser: 'babel-eslint' |> require.resolve(%),
parserOptions: {
ecmaVersion: 6,
sourceType: 'module'
}
}) |> RuleTester.setDefaultConfig(%);
const ruleTester = new RuleTester();
const missingDevCheckMessage = 'Missing DEV check before this string coercion.' + ' Check should be in this format:\n' + ' if (__DEV__) {\n' + ' checkXxxxxStringCoercion(value);\n' + ' }';
const prevStatementNotDevCheckMessage = 'The statement before this coercion must be a DEV check in this format:\n' + ' if (__DEV__) {\n' + ' checkXxxxxStringCoercion(value);\n' + ' }';
const message = "Using `'' + value` or `value + ''` is fast to coerce strings, but may throw." + ' For prod code, add a DEV check from shared/CheckStringCoercion immediately' + ' before this coercion.' + ' For non-prod code and prod error handling, use `String(value)` instead.';
ruleTester.run('eslint-rules/safe-string-coercion', rule, {
valid: [{
code: 'String(obj)',
options: [{
isProductionUserAppCode: false
}]
}, 'String(obj)', "'a' + obj", `
function getValueForAttribute(
node,
name,
expected
) {
if (__DEV__) {
var value = node.getAttribute(name);
if (__DEV__) {
checkAttributeStringCoercion(expected, name);
}
if (value === '' + expected) {
return expected;
}
return value;
}
}
`, `
if (__DEV__) { checkFormFieldValueStringCoercion (obj) }
'' + obj;
`, `
function f(a, index) {
if (typeof a === 'object' && a !== null && a.key != null) {
if (__DEV__) {
checkKeyStringCoercion(a.key);
}
return f('' + a.key);
}
return a;
}
`, "'' + i++", "'' + +i", "'' + +i", "+i + ''", "if (typeof obj === 'string') { '' + obj }", "if (typeof obj === 'string' || typeof obj === 'number') { '' + obj }", "if (typeof obj === 'string' && somethingElse) { '' + obj }", "if (typeof obj === 'number' && somethingElse) { '' + obj }", "if (typeof obj === 'bigint' && somethingElse) { '' + obj }", "if (typeof obj === 'undefined' && somethingElse) { '' + obj }", "if (typeof nextProp === 'number') { setTextContent(domElement, '' + nextProp); }",
// These twe below are sneaky. The inner `if` is unsafe, but the outer `if`
// ensures that the unsafe code will never be run. It's bad code, but
// doesn't violate this rule.
"if (typeof obj === 'string') { if (typeof obj === 'string' && obj.length) {} else {'' + obj} }", "if (typeof obj === 'string') if (typeof obj === 'string' && obj.length) {} else {'' + obj}", "'' + ''", "'' + '' + ''", "`test${foo}` + ''"],
invalid: [{
code: "'' + obj",
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: "obj + ''",
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: 'String(obj)',
options: [{
isProductionUserAppCode: true
}],
errors: [{
message: "For perf-sensitive coercion, avoid `String(value)`. Instead, use `'' + value`." + ' Precede it with a DEV check from shared/CheckStringCoercion' + ' unless Symbol and Temporal.* values are impossible.' + ' For non-prod code and prod error handling, use `String(value)` and disable this rule.'
}]
}, {
code: "if (typeof obj === 'object') { '' + obj }",
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: "if (typeof obj === 'string') { } else if (typeof obj === 'object') {'' + obj}",
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: "if (typeof obj === 'string' && obj.length) {} else {'' + obj}",
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__D__) { checkFormFieldValueStringCoercion (obj) }
'' + obj;
`,
errors: [{
message: prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__DEV__) { checkFormFieldValueStringCoercion (obj) }
'' + notobjj;
`,
errors: [{
message: 'Value passed to the check function before this coercion must match the value being coerced.' + '\n' + message
}]
}, {
code: `
if (__DEV__) { checkFormFieldValueStringCoercion (obj) }
// must be right before the check call
someOtherCode();
'' + objj;
`,
errors: [{
message: prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__DEV__) { chexxxxBadNameCoercion (obj) }
'' + objj;
`,
errors: [{
message: 'Missing or invalid check function call before this coercion.' + ' Expected: call of a function like checkXXXStringCoercion. ' + prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__DEV__) { }
'' + objj;
`,
errors: [{
message: prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__DEV__) { if (x) {} }
'' + objj;
`,
errors: [{
message: 'The DEV block before this coercion must only contain an expression. ' + prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (a) {
if (__DEV__) {
// can't have additional code before the check call
if (b) {
checkKeyStringCoercion(obj);
}
}
g = f( c, d + (b ? '' + obj : '') + e);
}
`,
errors: [{
message: 'The DEV block before this coercion must only contain an expression. ' + prevStatementNotDevCheckMessage + '\n' + message
}]
}, {
code: `
if (__DEV__) {
checkAttributeStringCoercion(expected, name);
}
// DEV check should be inside the if block
if (a && b) {
f('' + expected);
}
`,
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: `'' + obj + ''`,
errors: [{
message: missingDevCheckMessage + '\n' + message
}, {
message: missingDevCheckMessage + '\n' + message
}]
}, {
code: `foo\`text\` + ""`,
errors: [{
message: missingDevCheckMessage + '\n' + message
}]
}]
});