Skip to content

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

Merged
jankapunkt merged 1 commit into
meteor:release-3.1.0from
dupontbertrand:fix/native-event-scope-view-identity
Sep 14, 2026
Merged

jankapunkt merged 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
nachocodoner added a commit to meteor/meteor that referenced this pull request Sep 14, 2026
Exercise the two delegated-click cases from meteor/blaze#512 with native and jQuery backends in development and production using the existing Blaze fixture.

Verify and log the submodule SHA, resolved Blaze version, compiler-recorded dombackend.js input hash, and active backend across all three Blaze E2E apps.

The pinned alpha reproduces four failures (two cases in two modes). A temporary application of only meteor/blaze#513 dombackend.js makes all 36 Blaze group tests pass; the upstream source change is not included.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants