Skip to content
This repository was archived by the owner on Dec 11, 2019. It is now read-only.

Commit 27e24d7

Browse files
committed
Merge pull request #10165 from brave/10133
do not rely on classList for event target checks
1 parent 7e6af22 commit 27e24d7

File tree

10 files changed

+83
-14
lines changed

10 files changed

+83
-14
lines changed

app/renderer/components/bookmarks/addEditBookmarkHanger.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class AddEditBookmarkHanger extends React.Component {
193193
}
194194

195195
render () {
196-
return <Dialog className={cx({
196+
return <Dialog bookmarkHanger className={cx({
197197
bookmarkDialog: this.props.isModal,
198198
bookmarkHanger: !this.props.isModal,
199199
[css(styles.bookmarkHanger)]: !this.props.isModal

app/renderer/components/common/browserButton.js

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class BrowserButton extends ImmutableComponent {
5959
render () {
6060
return <button
6161
disabled={this.props.disabled}
62+
data-extension-button={this.props.extensionButton}
6263
data-l10n-id={this.props.l10nId}
6364
data-test-id={this.props.testId}
6465
data-test2-id={this.props.test2Id}

app/renderer/components/common/contextMenu.js

+1
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ class ContextMenu extends ImmutableComponent {
474474
styles.maxHeight = this.props.contextMenuDetail.get('maxHeight')
475475
}
476476
return <div
477+
data-context-menu
477478
ref={(node) => { this.node = node }}
478479
className={cx({
479480
contextMenu: true,

app/renderer/components/common/dialog.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ class Dialog extends ImmutableComponent {
4141
}
4242

4343
render () {
44-
return <div className={cx({
45-
[css(styles.dialog)]: true,
46-
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
47-
[this.props.className]: !!this.props.className
48-
})}
44+
return <div
45+
data-bookmark-hanger={this.props.bookmarkHanger}
46+
className={cx({
47+
[css(styles.dialog)]: true,
48+
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
49+
[this.props.className]: !!this.props.className
50+
})}
4951
data-test-id={this.props.testId}
5052
data-test2-id={this.props.test2Id}
5153
tabIndex='-1'

app/renderer/components/main/main.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -572,18 +572,19 @@ class Main extends ImmutableComponent {
572572
}
573573

574574
onMouseDown (e) {
575-
// TODO(bsclifton): update this to use eventUtil.eventElHasAncestorWithClasses
576575
let node = e.target
576+
const datasets = [
577+
'popupWindow',
578+
'contextMenu',
579+
'extensionButton',
580+
'menubarItem',
581+
'bookmarkHanger'
582+
]
577583
while (node) {
578-
if (node.classList &&
579-
(node.matches('[class^="popupWindow"]') ||
580-
node.classList.contains('contextMenu') ||
581-
node.matches('[class*="extensionButton_"]') ||
582-
node.classList.contains('menubarItem') ||
583-
node.classList.contains('bookmarkHanger'))) {
584+
if (eventUtil.elementHasDataset(node, datasets)) {
584585
// Middle click (on context menu) needs to fire the click event.
585586
// We need to prevent the default "Auto-Scrolling" behavior.
586-
if (node.classList.contains('contextMenu') && e.button === 1) {
587+
if (eventUtil.elementHasDataset(node, 'contextMenu') && e.button === 1) {
587588
e.preventDefault()
588589
}
589590
// Click event is handled downstream

app/renderer/components/main/popupWindow.js

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class PopupWindow extends ImmutableComponent {
106106
}
107107

108108
return <div
109+
data-popup-window
109110
className={css(
110111
styles.popupWindow,
111112
style.right !== undefined && styles.reverseExpand

app/renderer/components/navigation/browserAction.js

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class BrowserAction extends React.Component {
8080
// TODO(bridiver) should have some visual notification of hover/press
8181
return <div className={css(styles.browserActionButton)}>
8282
<BrowserButton
83+
extensionButton
8384
extensionItem
8485
l10nId='browserActionButton'
8586
testId='extensionBrowserAction'

app/renderer/components/navigation/menuBarItem.js

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class MenuBarItem extends React.Component {
6565

6666
render () {
6767
return <span
68+
data-menubar-item
6869
className={'menubarItem' + (this.props.selected ? ' selected' : '')}
6970
onClick={this.onClick}
7071
onMouseOver={this.onMouseOver}

js/lib/eventUtil.js

+23
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ module.exports.isForSecondaryAction = (e) =>
1010
e.button === 1
1111

1212
module.exports.eventElHasAncestorWithClasses = (e, classesToCheck) => {
13+
// DO NOT ADD NEW CHECKS USING THIS METHOD
14+
// classNames are changed from dev to prod by Aphrodite est. v1.2.3
15+
// and new code will not work. Consider using dataset attribute instead.
16+
// See issue #10029 for a breaking example.
17+
// ....
18+
// TODO deprecate this method.
1319
let node = e.target
1420

1521
while (node) {
@@ -28,3 +34,20 @@ module.exports.eventElHasAncestorWithClasses = (e, classesToCheck) => {
2834

2935
return false
3036
}
37+
38+
/**
39+
* Checks if a given node dataset matches a given dataset or array of datasets
40+
* @param {Object} The node to check if dataset is included
41+
* @param {Array|String} the dataset value to check against
42+
* @returns {Boolean} Whether or not the given dataset is included in the check
43+
*/
44+
module.exports.elementHasDataset = (node, datasetArray) => {
45+
if (!node.dataset) {
46+
return false
47+
}
48+
49+
const datasetToMatch = Array.isArray(datasetArray) ? datasetArray : [datasetArray]
50+
const elementDataset = Object.keys(node.dataset)
51+
52+
return elementDataset.some(dataset => datasetToMatch.includes(dataset))
53+
}

test/unit/js/lib/eventUtilTest.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
/* global describe, it */
5+
6+
const eventUtil = require('../../../../js/lib/eventUtil')
7+
const assert = require('assert')
8+
9+
require('../../braveUnit')
10+
11+
describe('eventUtil', function () {
12+
describe('elementHasDataset', function () {
13+
let datasetToTest
14+
let node = { dataset: { nespresso: true } }
15+
16+
it('returns false if node dataset do not match', function () {
17+
datasetToTest = ['starbucks', 'keurig']
18+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
19+
})
20+
it('returns true if node dataset match the provided dataset array', function () {
21+
datasetToTest = ['wow', 'such', 'nespresso', 'very', 'amazing']
22+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
23+
})
24+
it('can accept strings for the dataset to match against', function () {
25+
datasetToTest = 'nespresso'
26+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
27+
})
28+
it('can not accept partial string match', function () {
29+
datasetToTest = ['nespressomnibox']
30+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
31+
})
32+
it('returns false if node do not provide a dataset', function () {
33+
node = delete node.dataset
34+
datasetToTest = ['nespresso']
35+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
36+
})
37+
})
38+
})

0 commit comments

Comments
 (0)