Skip to content

Commit

Permalink
Rename & refactor invoker commands to reflect new spec decisions.
Browse files Browse the repository at this point in the history
Invoker commands now live solely on HTMLButtonElement, and have been
dropped from HTMLInputElement. This was discussed and resolved + minuted
in Jul 18 WHATNOT meeting:
whatwg/html#10471 (comment))

Words must be separated with dashes. This was discussed and resolved +
minuted in Jul 18 WHATNOT meeting:
whatwg/html#10471 (comment))

"Custom" commands now require a double dash (`--`) prefix. This was
discussed & resolved + minuted in the Jul 25 OpenUI meeting:
openui/open-ui#969 (comment)

In addition, CommandEvent#invoker is now renamed to CommandEvent#source
as discussed and resolved + minuted in Jul 18 WHATNOT meeting:
whatwg/html#10471 (comment))

This CL updates the tests & implementation to follow these changes. The
changes can also be found in the spec PR which reflects this updated
status:

whatwg/html#9841

Bug: 40284894
Change-Id: Iefa91a1736867239a21f8717aee1fcaaa54fdfd0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839601
Reviewed-by: Mason Freed <masonf@chromium.org>
Reviewed-by: Luke <lwarlow@igalia.com>
Commit-Queue: Keith Cirkel <chromium@keithcirkel.co.uk>
Cr-Commit-Position: refs/heads/main@{#1367705}
  • Loading branch information
keithamus authored and chromium-wpt-export-bot committed Oct 11, 2024
1 parent 39246a8 commit 89a5856
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
promise_test(async function (t) {
t.add_cleanup(reset);
assert_false(interestee.matches(":popover-open"));
interestbutton.setAttribute("interestaction", "togglepopover");
interestbutton.setAttribute("interestaction", "toggle-popover");
await hoverOver(interestbutton);
assert_true(interestee.matches(":popover-open"));
}, "hover interest invoking (as togglepopover) closed popover opens");
Expand All @@ -80,15 +80,15 @@
t.add_cleanup(reset);
interestee.showPopover();
assert_true(interestee.matches(":popover-open"));
interestbutton.setAttribute("interestaction", "togglepopover");
interestbutton.setAttribute("interestaction", "toggle-popover");
await hoverOver(interestbutton);
assert_false(interestee.matches(":popover-open"));
}, "hover interest invoking (as togglepopover) open popover closes");

promise_test(async function (t) {
t.add_cleanup(reset);
assert_false(interestee.matches(":popover-open"));
interestbutton.setAttribute("interestaction", "togglepopover");
interestbutton.setAttribute("interestaction", "toggle-popover");
interestbutton.focus();
assert_true(interestee.matches(":popover-open"));
}, "focus interest invoking (as togglepopover) closed popover opens");
Expand All @@ -97,15 +97,15 @@
t.add_cleanup(reset);
interestee.showPopover();
assert_true(interestee.matches(":popover-open"));
interestbutton.setAttribute("interestaction", "togglepopover");
interestbutton.setAttribute("interestaction", "toggle-popover");
interestbutton.focus();
assert_false(interestee.matches(":popover-open"));
}, "focus interest invoking (as togglepopover) open popover closes");

promise_test(async function (t) {
t.add_cleanup(reset);
assert_false(interestee.matches(":popover-open"));
interestbutton.setAttribute("interestaction", "tOgGlEpOpOvEr");
interestbutton.setAttribute("interestaction", "tOgGlE-pOpOvEr");
interestbutton.focus();
assert_true(interestee.matches(":popover-open"));
}, "interest invoking (as togglepopover - case insensitive) closed popover opens");
Expand Down
30 changes: 15 additions & 15 deletions html/semantics/invokers/invokeevent-dispatch-shadow.tentative.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
const slot = shadow.appendChild(document.createElement("slot"));
let childEvent = null;
let childEventTarget = null;
let childEventInvoker = null;
let childEventSource = null;
let hostEvent = null;
let hostEventTarget = null;
let hostEventInvoker = null;
let hostEventSource = null;
slot.addEventListener(
"command",
(e) => {
childEvent = e;
childEventTarget = e.target;
childEventInvoker = e.invoker;
childEventSource = e.source;
},
{ once: true },
);
Expand All @@ -38,13 +38,13 @@
(e) => {
hostEvent = e;
hostEventTarget = e.target;
hostEventInvoker = e.invoker;
hostEventSource = e.source;
},
{ once: true },
);
const event = new CommandEvent("command", {
bubbles: true,
invoker: slot,
source: slot,
composed: true,
});
slot.dispatchEvent(event);
Expand All @@ -55,9 +55,9 @@
"target is child inside shadow boundary",
);
assert_equals(
childEventInvoker,
childEventSource,
slot,
"invoker is child inside shadow boundary",
"source is child inside shadow boundary",
);
assert_equals(
hostEvent,
Expand All @@ -70,11 +70,11 @@
"target is retargeted to shadowroot host",
);
assert_equals(
hostEventInvoker,
hostEventSource,
host,
"invoker is retargeted to shadowroot host",
"source is retargeted to shadowroot host",
);
}, "CommandEvent propagates across shadow boundaries retargeting invoker");
}, "CommandEvent propagates across shadow boundaries retargeting source");

test(function (t) {
const host = document.createElement("div");
Expand All @@ -84,22 +84,22 @@
const button = shadow.appendChild(document.createElement("button"));
const invokee = host.appendChild(document.createElement("div"));
button.commandForElement = invokee;
button.command = 'test-command';
button.command = '--test-command';
let event = null;
let eventTarget = null;
let eventInvoker = null;
let eventSource = null;
invokee.addEventListener(
"command",
(e) => {
event = e;
eventTarget = e.target;
eventInvoker = e.invoker;
eventSource = e.source;
},
{ once: true },
);
button.click();
assert_true(event instanceof CommandEvent);
assert_equals(eventTarget, invokee, "target is invokee");
assert_equals(eventInvoker, host, "invoker is host");
}, "cross shadow CommandEvent retargets invoker to host element");
assert_equals(eventSource, host, "source is host");
}, "cross shadow CommandEvent retargets source to host element");
</script>
54 changes: 27 additions & 27 deletions html/semantics/invokers/invokeevent-interface.tentative.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@

test(function () {
const event = new CommandEvent("test");
assert_equals(event.invoker, null);
assert_readonly(event, "invoker", "readonly attribute value");
}, "invoker is readonly defaulting to null");
assert_equals(event.source, null);
assert_readonly(event, "source", "readonly attribute value");
}, "source is readonly defaulting to null");

test(function () {
const event = new CommandEvent("test", { command: "sAmPle" });
Expand Down Expand Up @@ -87,80 +87,80 @@
}, "command set to an object with a toString function");

test(function () {
const eventInit = { command: "sample", invoker: document.body };
const eventInit = { command: "sample", source: document.body };
const event = new CommandEvent("test", eventInit);
assert_equals(event.command, "sample");
assert_equals(event.invoker, document.body);
assert_equals(event.source, document.body);
}, "CommandEventInit properties set value");

test(function () {
const eventInit = {
command: "open",
invoker: document.getElementById("div"),
source: document.getElementById("div"),
};
const event = new CommandEvent("beforetoggle", eventInit);
assert_equals(event.command, "open");
assert_equals(event.invoker, document.getElementById("div"));
assert_equals(event.source, document.getElementById("div"));
}, "CommandEventInit properties set value 2");

test(function () {
const eventInit = {
command: "closed",
invoker: document.getElementById("button"),
source: document.getElementById("button"),
};
const event = new CommandEvent("toggle", eventInit);
assert_equals(event.command, "closed");
assert_equals(event.invoker, document.getElementById("button"));
assert_equals(event.source, document.getElementById("button"));
}, "CommandEventInit properties set value 3");

test(function () {
const event = new CommandEvent("test", { invoker: undefined });
assert_equals(event.invoker, null);
}, "invoker set to undefined");
const event = new CommandEvent("test", { source: undefined });
assert_equals(event.source, null);
}, "source set to undefined");

test(function () {
const event = new CommandEvent("test", { invoker: null });
assert_equals(event.invoker, null);
}, "invoker set to null");
const event = new CommandEvent("test", { source: null });
assert_equals(event.source, null);
}, "source set to null");

test(function () {
assert_throws_js(
TypeError,
function () {
new CommandEvent("test", { invoker: false });
new CommandEvent("test", { source: false });
},
"invoker is not an object",
"source is not an object",
);
}, "invoker set to false");
}, "source set to false");

test(function () {
assert_throws_js(
TypeError,
function () {
const event = new CommandEvent("test", { invoker: true });
const event = new CommandEvent("test", { source: true });
},
"invoker is not an object",
"source is not an object",
);
}, "invoker set to true");
}, "source set to true");

test(function () {
assert_throws_js(
TypeError,
function () {
const event = new CommandEvent("test", { invoker: {} });
const event = new CommandEvent("test", { source: {} });
},
"invoker is not an object",
"source is not an object",
);
}, "invoker set to {}");
}, "source set to {}");

test(function () {
assert_throws_js(
TypeError,
function () {
const eventInit = { command: "closed", invoker: new XMLHttpRequest() };
const eventInit = { command: "closed", source: new XMLHttpRequest() };
const event = new CommandEvent("toggle", eventInit);
},
"invoker is not an Element",
"source is not an Element",
);
}, "invoker set to non-Element EventTarget");
}, "source set to non-Element EventTarget");
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@
<script src="resources/invoker-utils.js"></script>

<div id="invokee"></div>
<button id="invokerbutton" commandfor="invokee" command="custom-command"></button>
<button id="invokerbutton" commandfor="invokee" command="--custom-command"></button>
<input type="button" id="invalidbutton" commandfor="invokee" command="--custom-command">
<form id="aform"></form>

<script>
aform.addEventListener('submit', (e) => (e.preventDefault()));

function resetState() {
invokerbutton.setAttribute("commandfor", "invokee");
invokerbutton.setAttribute("command", "custom-command");
invokerbutton.setAttribute("command", "--custom-command");
invokerbutton.removeAttribute("disabled");
invokerbutton.removeAttribute("form");
invokerbutton.removeAttribute("type");
Expand All @@ -34,13 +35,13 @@
assert_equals(event.bubbles, false, "bubbles");
assert_equals(event.composed, true, "composed");
assert_equals(event.isTrusted, true, "isTrusted");
assert_equals(event.command, "custom-command", "command");
assert_equals(event.command, "--custom-command", "command");
assert_equals(event.target, invokee, "target");
assert_equals(event.invoker, invokerbutton, "invoker");
assert_equals(event.source, invokerbutton, "invoker");
}, "event dispatches on click");

// valid custom invokeactions
["-foo", "foo-", "cAsE-cArRiEs", "-", "-a-", "a-b", "---", "show-picker"].forEach(
["--foo", "--foo-", "--cAsE-cArRiEs", "--", "--a-", "--a-b", "---", "--show-picker"].forEach(
(command) => {
promise_test(async function (t) {
t.add_cleanup(resetState);
Expand All @@ -55,7 +56,7 @@
assert_equals(event.isTrusted, true, "isTrusted");
assert_equals(event.command, command, "command");
assert_equals(event.target, invokee, "target");
assert_equals(event.invoker, invokerbutton, "invoker");
assert_equals(event.source, invokerbutton, "invoker");
}, `setting custom command property to ${command} (must include dash) sets event command`);

promise_test(async function (t) {
Expand All @@ -71,13 +72,13 @@
assert_equals(event.isTrusted, true, "isTrusted");
assert_equals(event.command, command, "command");
assert_equals(event.target, invokee, "target");
assert_equals(event.invoker, invokerbutton, "invoker");
assert_equals(event.source, invokerbutton, "invoker");
}, `setting custom command attribute to ${command} (must include dash) sets event command`);
},
);

// invalid custom invokeactions
["foo", "foobar", "foo bar", "em—dash", "hidedocument"].forEach((command) => {
["-foo", "-foo-", "foo-bar", "-foo bar", "—-emdash", "hidedocument"].forEach((command) => {
promise_test(async function (t) {
t.add_cleanup(resetState);
let event = null;
Expand Down Expand Up @@ -117,6 +118,13 @@
assert_false(called, "event was not called");
}, "event does not dispatch if click:preventDefault is called");

promise_test(async function (t) {
let event = null;
invokee.addEventListener("command", (e) => (event = e), { once: true });
await clickOn(invalidbutton);
assert_equals(event, null, "command should not have fired");
}, "event does not dispatch on input[type=button]");

promise_test(async function (t) {
t.add_cleanup(resetState);
let called = false;
Expand Down Expand Up @@ -155,12 +163,12 @@
let event = null;
svgInvokee.addEventListener("command", (e) => (event = e), { once: true });
invokerbutton.setAttribute("commandfor", "svg-invokee");
invokerbutton.setAttribute("command", "custom-command");
invokerbutton.setAttribute("command", "--custom-command");
assert_equals(invokerbutton.commandForElement, svgInvokee);
await clickOn(invokerbutton);
assert_not_equals(event, null, "event was called");
assert_true(event instanceof CommandEvent, "event is CommandEvent");
assert_equals(event.invoker, invokerbutton, "event.invoker is set to right element");
assert_equals(event.source, invokerbutton, "event.invoker is set to right element");
assert_equals(event.target, svgInvokee, "event.target is set to right element");
}, "event dispatches if invokee is non-HTML Element");
</script>
Loading

0 comments on commit 89a5856

Please sign in to comment.