Do not use offsetX/Y in shadow DOM (#8082)

Do not use offsetX/Y in shadow DOM
This commit is contained in:
Jukka Kurkela 2020-11-20 22:59:48 +02:00 committed by GitHub
parent 5f099f3822
commit fa997f06e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 4 deletions

View File

@ -52,6 +52,8 @@ function getPositionedStyle(styles, style, suffix) {
return result;
}
const useOffsetPos = (x, y, target) => (x > 0 || y > 0) && (!target || !target.shadowRoot);
function getCanvasPosition(evt, canvas) {
const e = evt.originalEvent || evt;
const touches = e.touches;
@ -59,7 +61,7 @@ function getCanvasPosition(evt, canvas) {
const {offsetX, offsetY} = source;
let box = false;
let x, y;
if (offsetX > 0 || offsetY > 0) {
if (useOffsetPos(offsetX, offsetY, e.target)) {
x = offsetX;
y = offsetY;
} else {

View File

@ -345,5 +345,59 @@ describe('DOM helpers tests', function() {
expect(Math.abs(pos3.x - Math.round((event.clientX - rect3.x - 10) / 360 * 400))).toBeLessThanOrEqual(1);
expect(Math.abs(pos3.y - Math.round((event.clientY - rect3.y - 10) / 360 * 400))).toBeLessThanOrEqual(1);
});
it ('should get the correct relative position for a node in a ShadowRoot', function() {
const event = {
offsetX: 50,
offsetY: 100,
clientX: 50,
clientY: 100
};
const chart = window.acquireChart({}, {
canvas: {
height: 200,
width: 200,
},
useShadowDOM: true
});
event.target = chart.canvas.parentNode.host;
expect(event.target.shadowRoot).not.toEqual(null);
const rect = chart.canvas.getBoundingClientRect();
const pos = helpers.getRelativePosition(event, chart);
expect(Math.abs(pos.x - Math.round(event.clientX - rect.x))).toBeLessThanOrEqual(1);
expect(Math.abs(pos.y - Math.round(event.clientY - rect.y))).toBeLessThanOrEqual(1);
const chart2 = window.acquireChart({}, {
canvas: {
height: 200,
width: 200,
style: 'padding: 10px'
},
useShadowDOM: true
});
event.target = chart2.canvas.parentNode.host;
const rect2 = chart2.canvas.getBoundingClientRect();
const pos2 = helpers.getRelativePosition(event, chart2);
expect(Math.abs(pos2.x - Math.round((event.clientX - rect2.x - 10) / 180 * 200))).toBeLessThanOrEqual(1);
expect(Math.abs(pos2.y - Math.round((event.clientY - rect2.y - 10) / 180 * 200))).toBeLessThanOrEqual(1);
const chart3 = window.acquireChart({}, {
canvas: {
height: 200,
width: 200,
style: 'width: 400px, height: 400px; padding: 10px'
},
useShadowDOM: true
});
event.target = chart3.canvas.parentNode.host;
const rect3 = chart3.canvas.getBoundingClientRect();
const pos3 = helpers.getRelativePosition(event, chart3);
expect(Math.abs(pos3.x - Math.round((event.clientX - rect3.x - 10) / 360 * 400))).toBeLessThanOrEqual(1);
expect(Math.abs(pos3.y - Math.round((event.clientY - rect3.y - 10) / 360 * 400))).toBeLessThanOrEqual(1);
});
});
});

View File

@ -30,6 +30,7 @@ function readImageData(url, callback) {
* @param {object} options.canvas - Canvas attributes.
* @param {object} options.wrapper - Canvas wrapper attributes.
* @param {boolean} options.useOffscreenCanvas - use an OffscreenCanvas instead of the normal HTMLCanvasElement.
* @param {boolean} options.useShadowDOM - use shadowDom
* @param {boolean} options.persistent - If true, the chart will not be released after the spec.
*/
function acquireChart(config, options) {
@ -60,7 +61,15 @@ function acquireChart(config, options) {
config.options.responsive = config.options.responsive === undefined ? false : config.options.responsive;
config.options.locale = config.options.locale || 'en-US';
wrapper.appendChild(canvas);
if (options.useShadowDOM) {
if (!wrapper.attachShadow) {
// If shadowDOM is not supported by the browsers, mark test as 'pending'.
return pending();
}
wrapper.attachShadow({mode: 'open'}).appendChild(canvas);
} else {
wrapper.appendChild(canvas);
}
window.document.body.appendChild(wrapper);
try {
@ -71,8 +80,7 @@ function acquireChart(config, options) {
// test.
// TODO: switch to skip() once it's implemented (https://github.com/jasmine/jasmine/issues/1709), or
// remove if all browsers implement `transferControlToOffscreen`
pending();
return;
return pending();
}
var offscreenCanvas = canvas.transferControlToOffscreen();
ctx = offscreenCanvas.getContext('2d');