Skip to content

add source to the dispatched events#7

Open
UweOhse wants to merge 1 commit intomfreed7:mainfrom
UweOhse:main
Open

add source to the dispatched events#7
UweOhse wants to merge 1 commit intomfreed7:mainfrom
UweOhse:main

Conversation

@UweOhse
Copy link
Copy Markdown

@UweOhse UweOhse commented Jan 13, 2026

This adds the source to the interest and loseinterest events.

Comment thread src/interestfor.js
Comment on lines +211 to +213
let evt = new Event(interestEventName);
evt.source = invoker
target.dispatchEvent(evt);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to crate an InterestEvent which subclasses Event, and both of these events should use that.

.source is also readonly, so you need to make it a getter and not a setter. You'll also want to retarget source so you don't expose ShadowDOMs.

All together this will look something like:

function getRootNode(node) {
  if (node && typeof node.getRootNode === "function") {
    return node.getRootNode();
  }
  if (node && node.parentNode) return getRootNode(node.parentNode);
  return node;
}
const eventSourceElements = new WeakMap();
class InterestEvent extends Event {
  constructor(type, eventInit = {}) {
    super(type, eventInit);
    const { source } = eventInit;
    if (source != null && !(source instanceof Element)) {
      throw new TypeError(`source must be an element`);
    }
    eventSourceElements.set(this, source || null);
  }

  get [Symbol.toStringTag]() {
    return "InterestEvent";
  }

  get source() {
    if (!eventSourceElements.has(this)) {
      throw new TypeError("illegal invocation");
    }
    const source = eventSourceElements.get(this);
    if (!(source instanceof Element)) return null;
    // Retarget `source` to the current event's root:
    const sourceRoot = getRootNode(source);
    if (sourceRoot !== getRootNode(this.target || document)) {
      return sourceRoot.host;
    }
    return source;
  }
}

In addition, the event is cancelable, and so we need to return early if it's preventdefaulted. We can check dispatchEvent's return value for this.

So each of the dispatch callsites become:

Suggested change
let evt = new Event(interestEventName);
evt.source = invoker
target.dispatchEvent(evt);
const shouldContinue = target.dispatchEvent(new InterestEvent(interestEventName, { source: invoker }));
if (!shouldContinue) return;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing this Keith!

@aliu-vmware
Copy link
Copy Markdown
Contributor

Pretty interested in getting this in. One thing I'm curious about, is the WeakMap really necessary for some reason, or can it be replaced by a private element?

@mfreed7
Copy link
Copy Markdown
Owner

mfreed7 commented Feb 21, 2026

Pretty interested in getting this in.

I think it's just waiting on a response from Keith's review comments.

@aliu-vmware
Copy link
Copy Markdown
Contributor

Pretty interested in getting this in.

I think it's just waiting on a response from Keith's review comments.

I'd like to be respectful, but it's been over a month with no response. What's a reasonable time to wait before I submit a PR with the changes included?

@mfreed7
Copy link
Copy Markdown
Owner

mfreed7 commented Feb 24, 2026

Pretty interested in getting this in.

I think it's just waiting on a response from Keith's review comments.

I'd like to be respectful, but it's been over a month with no response. What's a reasonable time to wait before I submit a PR with the changes included?

I think a month is reasonable. If you'd like to put up a PR with the comments incorporated, we could definitely take a look.

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.

4 participants