Skip to content

Commit

Permalink
MouseEvent: fix pageX/Y during dispatch
Browse files Browse the repository at this point in the history
Ensure that they correctly reflect the coordinate relative to the origin of
the window at the time of init (i.e. `clientX/Y` plus `scrollX/Y`). We record
it during init, since during scrollX/Y may have change and result in the wrong
`pageX/Y` values; see added tuWPT.

Also track the target-relative coordinate during init (still just `(0, 0)` in
the absence of layout support). This doesn't fundamentally change any
behavior, but makes the implementation more future proof, making it safer to
start handling Image Button submitters when constructing the form data set;
see jsdom#3496 where this code was extracted from.
  • Loading branch information
jenseng committed Mar 2, 2023
1 parent 65ef06f commit ca930f6
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
20 changes: 16 additions & 4 deletions lib/jsdom/living/events/MouseEvent-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,43 @@ class MouseEventImpl extends UIEventImpl {
}
get pageX() {
if (this._dispatchFlag) {
return 0;
return this._initialContainingBlockRelativeX;
}
const offset = wrapperForImpl(this.view)?.scrollX || 0;
return offset + this.clientX;
}
get pageY() {
if (this._dispatchFlag) {
return 0;
return this._initialContainingBlockRelativeY;
}
const offset = wrapperForImpl(this.view)?.scrollY || 0;
return offset + this.clientY;
}
get offsetX() {
if (this._dispatchFlag) {
return 0;
return this._paddingEdgeRelativeX;
}
return this.pageX;
}
get offsetY() {
if (this._dispatchFlag) {
return 0;
return this._paddingEdgeRelativeY;
}
return this.pageY;
}

constructor(globalObject, args, privateData) {
super(globalObject, args, privateData);

// We cache this during init so that we have a stable value during dispatch
const { scrollX = 0, scrollY = 0 } = wrapperForImpl(this.view) ?? {};
this._initialContainingBlockRelativeX = this.clientX + scrollX;
this._initialContainingBlockRelativeY = this.clientY + scrollY;
// TODO: support non-zero values somehow if/when jsdom adds layout support
this._paddingEdgeRelativeX = 0;
this._paddingEdgeRelativeY = 0;
}

initMouseEvent(
type,
bubbles,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@
assert_equals(e.offsetY, 22);
}, "MouseEvent should provide the correct computed values when the dispatch flag is not set");

async_test(t => {
const element = document.querySelector("button");
element.addEventListener("click", t.step_func_done(e => {
// changing these during dispatch should not mess up pageX/Y
window.scrollX = 0;
window.scrollY = 0;
assert_equals(e.pageX, 110);
assert_equals(e.pageY, 220);
assert_equals(e.offsetX, 0);
assert_equals(e.offsetY, 0);
}));
window.scrollX = 10;
window.scrollY = 20;
element.dispatchEvent(new MouseEvent("click", {
clientX: 100, clientY: 200, view: window
}));
}, "MouseEvent should provide the correct computed values when the dispatch flag is set");

test(() => {
const e = new MouseEvent("click", {
screenX: 1.5, screenY: 2.5, clientX: 3.5, clientY: 4.5
Expand Down

0 comments on commit ca930f6

Please sign in to comment.