From b551117552aad883e8980ddb2a2e9fc9e8a6bda9 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Wed, 22 May 2024 17:38:10 +0200 Subject: [PATCH] Prebid 9: Removing innerText & adding eslint rule (#11531) * 11233 Removing innerText & adding eslint rule * tests fix --------- Co-authored-by: Marcin Komorski --- .eslintrc.js | 1 + modules/adhashBidAdapter.js | 2 +- modules/idImportLibrary.js | 2 +- plugins/eslint/index.js | 54 ++++++++++++++++++++++ plugins/eslint/package.json | 2 +- plugins/eslint/validateImports.js | 30 +----------- test/spec/modules/adhashBidAdapter_spec.js | 30 ++++++------ 7 files changed, 75 insertions(+), 46 deletions(-) create mode 100644 plugins/eslint/index.js diff --git a/.eslintrc.js b/.eslintrc.js index f17c7a0063d..b0cd6eb26ca 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -83,6 +83,7 @@ module.exports = { files: key + '/**/*.js', rules: { 'prebid/validate-imports': ['error', allowedModules[key]], + 'prebid/no-innerText': ['error', allowedModules[key]], 'no-restricted-globals': [ 'error', { diff --git a/modules/adhashBidAdapter.js b/modules/adhashBidAdapter.js index 96e93883de6..c88b243d1d8 100644 --- a/modules/adhashBidAdapter.js +++ b/modules/adhashBidAdapter.js @@ -120,7 +120,7 @@ function brandSafety(badWords, maxScore) { .replaceAll(/\s\s+/g, ' ') .toLowerCase() .trim(); - const content = window.top.document.body.innerText.toLowerCase(); + const content = window.top.document.body.textContent.toLowerCase(); // \p{L} matches a single unicode code point in the category 'letter'. Matches any kind of letter from any language. const regexp = new RegExp('[\\p{L}]+', 'gu'); const wordsMatched = content.match(regexp); diff --git a/modules/idImportLibrary.js b/modules/idImportLibrary.js index e1847edfce4..f6819a485e0 100644 --- a/modules/idImportLibrary.js +++ b/modules/idImportLibrary.js @@ -155,7 +155,7 @@ function handleTargetElement() { const targetElement = document.getElementById(conf.target); if (targetElement) { - email = targetElement.innerText; + email = targetElement.textContent; if (!email) { _logInfo('Finding the email with observer'); diff --git a/plugins/eslint/index.js b/plugins/eslint/index.js new file mode 100644 index 00000000000..71af5a4098b --- /dev/null +++ b/plugins/eslint/index.js @@ -0,0 +1,54 @@ +const _ = require('lodash'); +const { flagErrors } = require('./validateImports.js'); + +module.exports = { + rules: { + 'no-innerText': { + meta: { + docs: { + description: '.innerText property on DOM elements should not be used due to performance issues' + }, + messages: { + noInnerText: 'Use of `.innerText` is not allowed. Use `.textContent` instead.', + } + }, + create: function(context) { + return { + MemberExpression(node) { + if (node.property && node.property.name === 'innerText') { + context.report({ + node: node.property, + messageId: 'noInnerText', + }); + } + } + } + } + }, + 'validate-imports': { + meta: { + docs: { + description: 'validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points' + } + }, + create: function(context) { + return { + "CallExpression[callee.name='require']"(node) { + let importPath = _.get(node, ['arguments', 0, 'value']); + if (importPath) { + flagErrors(context, node, importPath); + } + }, + ImportDeclaration(node) { + let importPath = node.source.value.trim(); + flagErrors(context, node, importPath); + }, + 'ExportNamedDeclaration[source]'(node) { + let importPath = node.source.value.trim(); + flagErrors(context, node, importPath); + } + } + } + } + } +}; diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json index fa18ad83718..446f63945fa 100644 --- a/plugins/eslint/package.json +++ b/plugins/eslint/package.json @@ -2,7 +2,7 @@ "name": "eslint-plugin-prebid", "version": "1.0.0", "description": "validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points", - "main": "validateImports.js", + "main": "index.js", "author": "the prebid.js contributors", "license": "Apache-2.0" } diff --git a/plugins/eslint/validateImports.js b/plugins/eslint/validateImports.js index b936f44aee7..e38f0532238 100644 --- a/plugins/eslint/validateImports.js +++ b/plugins/eslint/validateImports.js @@ -53,31 +53,5 @@ function flagErrors(context, node, importPath) { } module.exports = { - rules: { - 'validate-imports': { - meta: { - docs: { - description: 'validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points' - } - }, - create: function(context) { - return { - "CallExpression[callee.name='require']"(node) { - let importPath = _.get(node, ['arguments', 0, 'value']); - if (importPath) { - flagErrors(context, node, importPath); - } - }, - ImportDeclaration(node) { - let importPath = node.source.value.trim(); - flagErrors(context, node, importPath); - }, - 'ExportNamedDeclaration[source]'(node) { - let importPath = node.source.value.trim(); - flagErrors(context, node, importPath); - } - } - } - } - } -}; + flagErrors +} diff --git a/test/spec/modules/adhashBidAdapter_spec.js b/test/spec/modules/adhashBidAdapter_spec.js index cc643d6d2ab..f3b63a2359b 100644 --- a/test/spec/modules/adhashBidAdapter_spec.js +++ b/test/spec/modules/adhashBidAdapter_spec.js @@ -178,105 +178,105 @@ describe('adhashBidAdapter', function () { }); it('should return empty array when there are bad words (full)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text badword badword example badword text' + ' word'.repeat(993); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (full cyrillic)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text дума дума example дума text' + ' текст'.repeat(993); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (partial)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text partialbadwordb badwordb example badwordbtext' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (partial, compound phrase)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text partialbad wordb bad wordb example bad wordbtext' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (starts)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text startsWith starts text startsAgain' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (starts cyrillic)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text стартТекст старт text стартТекст' + ' дума'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (ends)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text wordEnds ends text anotherends' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (ends cyrillic)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text ДругКрай край text ощеединкрай' + ' дума'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (combo)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'queen of england dies, the queen dies' + ' word'.repeat(993); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return empty array when there are bad words (regexp)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text xxxayyy zzxxxAyyyzz text xxxbyyy' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(0); }); it('should return non-empty array when there are not enough bad words (full)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text badword badword example text' + ' word'.repeat(994); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); }); it('should return non-empty array when there are not enough bad words (partial)', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text partialbadwordb example' + ' word'.repeat(996); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); }); it('should return non-empty array when there are no-bad word matches', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text partialbadword example text' + ' word'.repeat(995); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); }); it('should return non-empty array when there are bad words and good words', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return 'example text badword badword example badword goodWord goodWord ' + ' word'.repeat(992); }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(1); }); it('should return non-empty array when there is a problem with the brand-safety', function () { - bodyStub = sinon.stub(window.top.document.body, 'innerText').get(function() { + bodyStub = sinon.stub(window.top.document.body, 'textContent').get(function() { return null; }); expect(spec.interpretResponse(serverResponse, request).length).to.equal(1);