Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cjs/interface/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const {DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_TYPE_NODE, ELEMENT_NODE, SVG_NAMESPACE} = require('../shared/constants.js');

const {
CUSTOM_ELEMENTS, DOM_PARSER, GLOBALS, IMAGE, MUTATION_OBSERVER, DOCTYPE, END, NEXT, MIME, EVENT_TARGET, UPGRADE
CUSTOM_ELEMENTS, DISPATCH_TARGET, DOM_PARSER, GLOBALS, IMAGE, MUTATION_OBSERVER, DOCTYPE, END, NEXT, MIME, EVENT_TARGET, UPGRADE
} = require('../shared/symbols.js');

const {Facades, illegalConstructor} = require('../shared/facades.js');
Expand Down Expand Up @@ -98,6 +98,7 @@ class Document extends NonElementParentNode {
case 'dispatchEvent':
if (!this[EVENT_TARGET]) {
const et = this[EVENT_TARGET] = new EventTarget;
et[DISPATCH_TARGET] = window.get(this);
et.dispatchEvent = et.dispatchEvent.bind(et);
et.addEventListener = et.addEventListener.bind(et);
et.removeEventListener = et.removeEventListener.bind(et);
Expand Down
5 changes: 4 additions & 1 deletion cjs/interface/event-target.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';
// https://dom.spec.whatwg.org/#interface-eventtarget

const {DISPATCH_TARGET} = require('../shared/symbols.js');

const wm = new WeakMap();

function dispatch(event, listener) {
Expand Down Expand Up @@ -70,12 +72,13 @@ class DOMEventTarget {

dispatchEvent(event) {
let node = this;
const target = this[DISPATCH_TARGET] || this;
event.eventPhase = event.CAPTURING_PHASE;

// intentionally simplified, specs imply way more code: https://dom.spec.whatwg.org/#event-path
while (node) {
if (node.dispatchEvent)
event._path.push({currentTarget: node, target: this});
event._path.push({currentTarget: node, target});
node = event.bubbles && node._getParent && node._getParent();
}
event._path.some(invokeListeners, event);
Expand Down
4 changes: 4 additions & 0 deletions cjs/shared/symbols.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ exports.END = END;
const EVENT_TARGET = Symbol('EventTarget');
exports.EVENT_TARGET = EVENT_TARGET;

// used in EventTarget to report a different target (e.g. defaultView)
const DISPATCH_TARGET = Symbol('dispatchTarget');
exports.DISPATCH_TARGET = DISPATCH_TARGET;

// used to augment a created document defaultView
const GLOBALS = Symbol('globals');
exports.GLOBALS = GLOBALS;
Expand Down
5 changes: 3 additions & 2 deletions esm/interface/document.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_TYPE_NODE, ELEMENT_NODE, SVG_NAMESPACE} from '../shared/constants.js';

import {
CUSTOM_ELEMENTS, DOM_PARSER, GLOBALS, IMAGE, MUTATION_OBSERVER,
DOCTYPE, END, NEXT, MIME, EVENT_TARGET, UPGRADE
CUSTOM_ELEMENTS, DISPATCH_TARGET, DOM_PARSER, GLOBALS, IMAGE,
MUTATION_OBSERVER, DOCTYPE, END, NEXT, MIME, EVENT_TARGET, UPGRADE
} from '../shared/symbols.js';

import {Facades, illegalConstructor} from '../shared/facades.js';
Expand Down Expand Up @@ -98,6 +98,7 @@ export class Document extends NonElementParentNode {
case 'dispatchEvent':
if (!this[EVENT_TARGET]) {
const et = this[EVENT_TARGET] = new EventTarget;
et[DISPATCH_TARGET] = window.get(this);
et.dispatchEvent = et.dispatchEvent.bind(et);
et.addEventListener = et.addEventListener.bind(et);
et.removeEventListener = et.removeEventListener.bind(et);
Expand Down
5 changes: 4 additions & 1 deletion esm/interface/event-target.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// https://dom.spec.whatwg.org/#interface-eventtarget

import {DISPATCH_TARGET} from '../shared/symbols.js';

const wm = new WeakMap();

function dispatch(event, listener) {
Expand Down Expand Up @@ -69,12 +71,13 @@ class DOMEventTarget {

dispatchEvent(event) {
let node = this;
const target = this[DISPATCH_TARGET] || this;
event.eventPhase = event.CAPTURING_PHASE;

// intentionally simplified, specs imply way more code: https://dom.spec.whatwg.org/#event-path
while (node) {
if (node.dispatchEvent)
event._path.push({currentTarget: node, target: this});
event._path.push({currentTarget: node, target});
node = event.bubbles && node._getParent && node._getParent();
}
event._path.some(invokeListeners, event);
Expand Down
3 changes: 3 additions & 0 deletions esm/shared/symbols.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export const END = Symbol('end');
// used in Document to make the globalThis an event target
export const EVENT_TARGET = Symbol('EventTarget');

// used in EventTarget to report a different target (e.g. defaultView)
export const DISPATCH_TARGET = Symbol('dispatchTarget');

// used to augment a created document defaultView
export const GLOBALS = Symbol('globals');

Expand Down
14 changes: 13 additions & 1 deletion test/interface/event-target.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,16 @@ containerTarget.addEventListener('click', basicHandler, { once: true });
callCount = 0;
buttonTarget.click();
assert(callCount, 4, '4 (2 are set before previous tests) and 2 here listeners should be called');
assert(evBtn, 0, 'default click event button should be 0 (left click)')
assert(evBtn, 0, 'default click event button should be 0 (left click)')

// defaultView events must report the actual view as their target (#298)
let viewCalls = 0;
for (const name of ['document', 'window']) {
const view = window[name];
view.addEventListener('direct', event => {
assert(event.target === view, true, `${name} is the event target`);
viewCalls++;
}, { once: true });
view.dispatchEvent(new Event('direct'));
}
assert(viewCalls, 2, 'defaultView direct dispatch should invoke its listeners')