polyfills icon indicating copy to clipboard operation
polyfills copied to clipboard

[Custom Elements] Incorrect `observedAttributes` behavior when using mixed-case attributes

Open wessberg opened this issue 5 years ago • 6 comments

Description

Another issue that is somewhat related, and may be relevant to also see for context: https://github.com/webcomponents/polyfills/issues/111

With native Custom Elements, the attributes declared in the static observedAttributes getter must be lower-case in order for the attributeChangedCallback to be triggered when they change. This is how the implementation in Chrome, Firefox, and Safari works.

In the following example, the attributeChangedCallback will never be called in browsers that natively support Custom Elements:

class A extends HTMLElement {
	static get observedAttributes () {
		return ["fooBarBaz"];
	}

	attributeChangedCallback (name, oldValue, newValue) {
		console.log("changed!:", {
			name, oldValue, newValue
		});
	}
}
customElements.define("a-el", A);

const a = new A();
// Won't trigger attributeChangedCallback
console.log("setting attribute with name: 'foobarbaz'");
a.setAttribute("foobarbaz", "");

// Wait a bit since MutationObserver operates on the microtask queue
setTimeout(() => {
	// *Will* trigger attributeChangedCallback but **only when using the Custom Elements polyfill**
	console.log("setting attribute with name: 'fooBarBaz'");
	a.setAttribute("fooBarBaz", "");
}, 1000);

However, using the Custom Elements polyfill, the attributeChangedCallback will be called when there is a direct case-sensitive match between the observed attribute name and the attribute named passed on to setAttribute. In the example above, the second call (a.setAttribute("fooBarBaz", "")) will trigger the attributeChangedCallback.

While - according to the HTML spec - attribute names can mix lower- with uppercase letters that are an ASCII case-insensitive match for the attribute's name, the actual behavior of observedAttributes does require, at least as evidenced by its implementation in Chromium/WebKit/Firefox, that these names are all lowercased when returned from that getter.

For lit-html/LitElement users and users of other tools and libraries that leverages Custom Elements, this can cause problems when binding to attributes or boolean attributes with mixed-case property names as is very common to do (camelCased property names that reflect to/from attributes) when leveraging the Custom Elements polyfill.

Example

Here's a repro. Open the page, and check out the console. What is printed there depends on whether or not the polyfill is being used.

https://ce-bug-demo.surge.sh/

Steps to reproduce

A repro example is provided in the code example above

Expected behavior

The behavior of observedAttributes aligns with native behavior.

Actual behavior

The behavior of observedAttributes does not align with native behavior.

Version

@webcomponents/[email protected]

Browsers affected

  • [x] Chrome
  • [x] Firefox
  • [x] Edge
  • [x] Safari
  • [x] IE 11

wessberg avatar Sep 04 '20 08:09 wessberg

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Sep 04 '21 14:09 stale[bot]

This issue is very much still relevant, and it should not be marked as stale.

wessberg avatar Sep 07 '21 06:09 wessberg

Agreed, I just had this absurd behavior effect me as well.

oldmansutton avatar Oct 07 '21 17:10 oldmansutton

this affected me well - is this getting prioritized?

colelloa avatar Feb 19 '22 18:02 colelloa

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Mar 18 '23 15:03 stale[bot]

Affecting me too. It doesn't seem to be documented anywhere, but observedAttributes only works for attributes which are specified in lower case.

noseratio avatar Nov 13 '23 20:11 noseratio