Skip to content

fix(blaze): match delegated event selectors within delegation root - #513

Open
dupontbertrand wants to merge 1 commit into
meteor:release-3.1.0from
dupontbertrand:fix/native-event-scope-view-identity
Open

fix(blaze): match delegated event selectors within delegation root#513
dupontbertrand wants to merge 1 commit into
meteor:release-3.1.0from
dupontbertrand:fix/native-event-scope-view-identity

Conversation

@dupontbertrand

Copy link
Copy Markdown

Fixes #512.

The native (no-jQuery) backend decided delegation scope by comparing $blaze_range.view.name strings between the delegation root and the node where the selector stopped matching. Block helper views share generic names ('if', 'unless', …), so a wrapper element inside a parent's {{#if}} collided with the child template's own {{#if}} and the event was silently dropped (#512 has the verified 8-case matrix; when the clicked element is a direct child of the delegation root, both names are even read off the same element, dropping the event for any tagged wrapper regardless of names).

The heuristic was approximating jQuery's context-rooted selector matching (the "event map selector scope" tests: for 'div p', both elements must live inside the delegation root — $(elem).find(selector) semantics). This PR implements that semantics directly instead: prefix the selector with :scope, query from the delegation element, and pick the closest matching ancestor-or-self of the event target (root excluded, as jQuery does). The name comparison is gone.

Notes:

  • Two regression tests added (watched fail before the fix: expected "hit", actual ""); existing tests untouched — in particular the "event map selector scope" tests now pass for the right reason.
  • Full suite green on both backends via the CI method (test-in-console + puppeteerRunner): native 416/416, jQuery 420/420.
  • Per-event querySelectorAll cost is equivalent to what jQuery's Sizzle did per delegated event on this same path; it only runs when jQuery is absent, and only for delegated (selector) handlers.
  • :scope is supported by every browser Meteor 3 targets, and the test suite itself already relies on it (querySelectorAll(':scope > *')).

The native (no-jQuery) backend decided delegation scope by comparing
$blaze_range.view.name strings between the delegation root and the node
where the selector stopped matching. Block helper views all share generic
names ('if', 'unless', 'each', ...), so a wrapper element placed inside a
parent's {{#if}} collided with the child template's own {{#if}} and the
event was silently dropped. When the clicked element was a direct child
of the delegation root, both names were even read off the same element,
dropping the event for any tagged wrapper.

Replace the name heuristic with the semantics jQuery actually applies:
evaluate the selector rooted at the delegation element (:scope prefix,
as $(elem).find(selector) does), then pick the closest matching
ancestor-or-self of the event target. This keeps the 'event map selector
scope' tests passing for the right reason and delivers events that the
heuristic wrongly discarded.

Fixes meteor#512
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant