Closed Bug 1709832 Opened 5 years ago Closed 5 years ago

dragenter event incorrectly fires on Text nodes (should be Element nodes only)

Categories

(Core :: DOM: Copy & Paste and Drag & Drop, defect, P2)

Firefox 88
defect

Tracking

()

RESOLVED FIXED
92 Branch
Tracking Status
firefox92 --- fixed

People

(Reporter: u587334, Assigned: saschanaz)

References

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36

Steps to reproduce:

I was writing a drag event handler on a <table>.

I needed to obtain the parent <tr> element while dragging over various nested elements, such as a <div> containing text inside <td>.

I was having trouble getting consistent results between browsers with Node.nodeName. So I decided to use Element.closest().

Here's a quick HTML example of my markup nesting (it's not all that complicated):

<tr>
    <td>
      Test 123<div>Test 123</div>
    </td>
</tr>

Actual results:

It seemed to work, but I sometimes got this error: Uncaught TypeError: event.target.closest is not a function

Upon investigation, it only happens if event.target has a nodeType of TEXT_NODE. This appears to be a "Text Interface" according to MDN: https://developer.mozilla.org/en-US/docs/Web/API/Text.

It would seem that Element.closest() can only handle type ELEMENT_NODE.

Expected results:

The text node itself has a parentElement property that Element.closest() should be able to use. This bug does not occur in Chrome.

The Bugbug bot thinks this bug should belong to the 'Core::DOM: Core & HTML' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core

This appears to be a workaround that makes my code work as it should (adapted from whatwg issue):

if (!Text.prototype.closest) Text.prototype.closest = function(s) {return this.parentNode.closest(s); }

Existing polyfills don't seem to solve this particular issue because they still only work with Element.

This bug does not occur in Chrome.

Chrome also limits closest() to Element so it should be same. Could you share the full page for us to debug the issue? Possibly https://codepen.io or such?

The text node itself has a parentElement property that Element.closest() should be able to use.

Sounds like a valid argument to me. Anne, do you recall why closest() is limited to Elements?

Flags: needinfo?(annevk)

Here's a test case: https://codepen.io/bryc/pen/MWpWzYv

To reproduce the issue:

  1. Click and hold on "Test" text.
  2. Drag to the right towards "123" text, careful not to cross over the dotted red line.

(Don't let go just yet)

Result: Firefox should give the error, Chrome will log "a1" to the console.

  1. Continue dragging from the black "123" text, over the dotted red line, down to the red "123" text below it.

Result: Firefox will log "a1", and then give a second error. Chrome will log a second "a1".


Hope that helps highlight the issue.

https://developer.mozilla.org/en-US/docs/Web/API/Node/contains

This method works somewhat similarly, it checks if a node is contained in another node. Might be something to contrast against, because it could often be used together and be assumed to work similarly. Firefox doesn't have this issue here.

Hmm, it seems Firefox emits dragenter with text nodes while Chrome emits with the parent element. The spec says the target must be "Immediate user selection or the body element" where the former is also an element, so the target should always be an element.

Anne, could you double check also for this one?

Agreed that the specification says that dragenter events must only fire on elements.

Status: UNCONFIRMED → NEW
Component: DOM: Core & HTML → DOM: Copy & Paste and Drag & Drop
Ever confirmed: true
Flags: needinfo?(annevk)
Priority: -- → P2
Summary: Element.closest() fails to access parent elements of TEXT_NODE → dragenter event incorrectly fires on Text nodes (should be Element nodes only)
Assignee: nobody → krosylight
Attachment #9233379 - Attachment description: Bug 1709832 - Do not fire dragenter/leave at text nodes → Bug 1709832 - Part 1: Do not fire dragenter/leave at text nodes r=edgar

Because EventDispatcher::Dispatch can run script (but not marked as such, which is bug 1539884).

Depends on D121006

OS: Unspecified → All
Hardware: Unspecified → All
Pushed by krosylight@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/763aa9ea82f0 Part 1: Do not fire dragenter/leave at text nodes r=edgar https://hg.mozilla.org/integration/autoland/rev/1db9d4f36b1e Part 2: Mark drag event dispatchers as MOZ_CAN_RUN_SCRIPT r=edgar
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → 92 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: