From 64e13162faa692aa2d12071ad9a14a3ac1b08a6f Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Thu, 7 Oct 2021 17:48:36 +0300 Subject: Sanitizer: fix logic and add a test. (#35133) This was broken in 2596c97 inadvertently. Added a test so that we don't hit this in the future. --- js/src/util/sanitizer.js | 2 +- js/tests/unit/util/sanitizer.spec.js | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'js') diff --git a/js/src/util/sanitizer.js b/js/src/util/sanitizer.js index f5a8287cd..232416f3a 100644 --- a/js/src/util/sanitizer.js +++ b/js/src/util/sanitizer.js @@ -45,7 +45,7 @@ const allowedAttribute = (attribute, allowedAttributeList) => { // Check if a regular expression validates the attribute. return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp) - .every(regex => regex.test(attributeName)) + .some(regex => regex.test(attributeName)) } export const DefaultAllowlist = { diff --git a/js/tests/unit/util/sanitizer.spec.js b/js/tests/unit/util/sanitizer.spec.js index 7379d221f..28d624c87 100644 --- a/js/tests/unit/util/sanitizer.spec.js +++ b/js/tests/unit/util/sanitizer.spec.js @@ -23,6 +23,31 @@ describe('Sanitizer', () => { expect(result).not.toContain('href="javascript:alert(7)') }) + it('should sanitize template and work with multiple regex', () => { + const template = [ + '
', + ' Click me', + ' Some content', + '
' + ].join('') + + const myDefaultAllowList = DefaultAllowlist + // With the default allow list + let result = sanitizeHtml(template, myDefaultAllowList, null) + + // `data-foo` won't be present + expect(result).not.toContain('data-foo="bar"') + + // Add the following regex too + myDefaultAllowList['*'].push(/^data-foo/) + + result = sanitizeHtml(template, myDefaultAllowList, null) + + expect(result).not.toContain('href="javascript:alert(7)') // This is in the default list + expect(result).toContain('aria-label="This is a link"') // This is in the default list + expect(result).toContain('data-foo="bar"') // We explicitly allow this + }) + it('should allow aria attributes and safe attributes', () => { const template = [ '
', -- cgit v1.2.3 From eb0f705621a044d25d6de0e5d1b4dde306b5004d Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Fri, 8 Oct 2021 12:28:05 +0300 Subject: scrollspy.js: chain functions (#35139) --- js/src/scrollspy.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'js') diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js index df9a14e22..e0e2e9bf9 100644 --- a/js/src/scrollspy.js +++ b/js/src/scrollspy.js @@ -110,25 +110,26 @@ class ScrollSpy extends BaseComponent { this._scrollHeight = this._getScrollHeight() const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target) - - for (const item of targets.map(element => { - const targetSelector = getSelectorFromElement(element) - const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null - - if (target) { - const targetBCR = target.getBoundingClientRect() - if (targetBCR.width || targetBCR.height) { - return [ - Manipulator[offsetMethod](target).top + offsetBase, - targetSelector - ] + .map(element => { + const targetSelector = getSelectorFromElement(element) + const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null + + if (target) { + const targetBCR = target.getBoundingClientRect() + if (targetBCR.width || targetBCR.height) { + return [ + Manipulator[offsetMethod](target).top + offsetBase, + targetSelector + ] + } } - } - return null - }) - .filter(item => item) - .sort((a, b) => a[0] - b[0])) { + return null + }) + .filter(item => item) + .sort((a, b) => a[0] - b[0]) + + for (const item of targets) { this._offsets.push(item[0]) this._targets.push(item[1]) } -- cgit v1.2.3 From a260967a55806a26bee15a5c1eb890c9e6a3ba02 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Fri, 8 Oct 2021 12:32:11 +0300 Subject: tests: minor cleanup (#35138) * tests: minor cleanup * tests: use the util noop function --- js/tests/unit/alert.spec.js | 2 -- js/tests/unit/button.spec.js | 8 +------- js/tests/unit/carousel.spec.js | 24 +++++++++++------------- js/tests/unit/collapse.spec.js | 2 -- js/tests/unit/dom/data.spec.js | 5 ++--- js/tests/unit/dom/event-handler.spec.js | 2 -- js/tests/unit/dom/manipulator.spec.js | 2 -- js/tests/unit/dom/selector-engine.spec.js | 2 -- js/tests/unit/dropdown.spec.js | 8 +++----- js/tests/unit/jquery.spec.js | 3 +-- js/tests/unit/modal.spec.js | 2 -- js/tests/unit/offcanvas.spec.js | 4 +--- js/tests/unit/popover.spec.js | 2 -- js/tests/unit/scrollspy.spec.js | 2 -- js/tests/unit/tab.spec.js | 2 -- js/tests/unit/toast.spec.js | 2 -- js/tests/unit/tooltip.spec.js | 2 -- js/tests/unit/util/index.spec.js | 2 -- 18 files changed, 19 insertions(+), 57 deletions(-) (limited to 'js') diff --git a/js/tests/unit/alert.spec.js b/js/tests/unit/alert.spec.js index 72cd23d89..cdda997c9 100644 --- a/js/tests/unit/alert.spec.js +++ b/js/tests/unit/alert.spec.js @@ -1,7 +1,5 @@ import Alert from '../../src/alert' import { getTransitionDurationFromElement } from '../../src/util/index' - -/** Test helpers */ import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture' describe('Alert', () => { diff --git a/js/tests/unit/button.spec.js b/js/tests/unit/button.spec.js index be99177e8..e24ff5cb0 100644 --- a/js/tests/unit/button.spec.js +++ b/js/tests/unit/button.spec.js @@ -1,11 +1,5 @@ import Button from '../../src/button' - -/** Test helpers */ -import { - getFixture, - clearFixture, - jQueryMock -} from '../helpers/fixture' +import { getFixture, clearFixture, jQueryMock } from '../helpers/fixture' describe('Button', () => { let fixtureEl diff --git a/js/tests/unit/carousel.spec.js b/js/tests/unit/carousel.spec.js index 9e5cfea86..70b9b8f0f 100644 --- a/js/tests/unit/carousel.spec.js +++ b/js/tests/unit/carousel.spec.js @@ -1,9 +1,7 @@ import Carousel from '../../src/carousel' import EventHandler from '../../src/dom/event-handler' - -/** Test helpers */ import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture' -import * as util from '../../src/util' +import { isRTL, noop } from '../../src/util/index' describe('Carousel', () => { const { Simulator, PointerEvent } = window @@ -331,7 +329,7 @@ describe('Carousel', () => { // Headless browser does not support touch events, so need to fake it // to test that touch events are add properly. - document.documentElement.ontouchstart = () => {} + document.documentElement.ontouchstart = noop const carousel = new Carousel(carouselEl) expect(carousel._addTouchEventListeners).toHaveBeenCalled() @@ -344,7 +342,7 @@ describe('Carousel', () => { return } - document.documentElement.ontouchstart = () => {} + document.documentElement.ontouchstart = noop document.head.append(stylesCarousel) Simulator.setType('pointer') @@ -389,7 +387,7 @@ describe('Carousel', () => { return } - document.documentElement.ontouchstart = () => {} + document.documentElement.ontouchstart = noop document.head.append(stylesCarousel) Simulator.setType('pointer') @@ -431,7 +429,7 @@ describe('Carousel', () => { it('should allow swiperight and call _slide (prev) with touch events', done => { Simulator.setType('touch') clearPointerEvents() - document.documentElement.ontouchstart = () => {} + document.documentElement.ontouchstart = noop fixtureEl.innerHTML = [ '