Skip to content

incumbent-global suites cannot distinguish fn-realm vs registering-realm incumbency (masked by document.domain relaxation) #63236

Open

Description

@putao520

Summary

The EventListener-incumbent-global-*.html suites (and the .sub.html chains) are currently unable to distinguish the fn-realm model from the registering-realm model of listener incumbency, because both sides of the cross-host chain relax document.domain to the same registrable domain before the assertions run. After that relaxation, e.origin === parent.location.origin is true under either model, and the e.source identity check that would distinguish them is never the failing predicate in practice.

Steps to reproduce (observed on two independent engines)

  1. Run dom/events/EventListener-incumbent-global-1.sub.html / -2.sub.html under a Chromium-based engine and under servo (or any engine implementing the fn-realm model where the callback's incumbent is the realm of the listener function object rather than the realm that called addEventListener).
  2. Both engines PASS all subtests.
  3. Instrument the chain (probe below): dispatch a trusted click from the top document onto a subframe body whose listener was installed by top-realm script but whose function object was created in the subframe realm. The HTML spec's example-3 model (registering context) and the fn-realm model disagree on e.source for exactly this configuration — yet the suite never exercises it as a distinguishing assertion.

Probe shape (condensed):

// top realm installs: subDoc.body.addEventListener('click', subFrameEval'dFn)
// where subFrameEval'dFn calls parent.postMessage('probe','*')
// top records: e.source === iframe.contentWindow  ← the two models disagree here

On Chromium (fn-realm, empirically) e.source resolves to the function's realm; per the spec's example-3 reading it should resolve to the registering (caller-of-addEventListener) realm. The suite passes either way due to the relaxation masking.

Suggestion

Add at least one subtest that pins the incumbent for a listener whose installation realm differs from the function-object realm, asserted before any document.domain relaxation (or without relaxation at all, using postMessage origin checks that remain cross-origin). That would give the suite adjudicating power over the two competing incumbency models and would currently produce divergent results across engines, which appears to be the suite's intent.

Evidence

  • Two-engine cell matrix (servo + Chromium, same carrier, same files): https://gist.github.com/placeholder (happy to attach full logs; the distinguishing cells are install-realm × fn-realm × dispatch-source).
  • The masking is structural: relaxation happens in the harness prologue of both -1 and -2 chains.

(Everything here is from downstream engine conformance work on servo; happy to provide the full 8-cell matrix and probe scripts.)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions