Repository navigation
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
7b18f61 to
2162b48
Compare
…orced-polyfill Chromium run - tests.yml: Node 24.5, actions v4, install Playwright browsers, drop the Saucelabs job - scoped-custom-element-registry: test:forced runs the tests in Chromium with the polyfill forced (FORCE_POLYFILL), and npm test depends on it - test/wtr.firefox.config.js: run the tests locally in a Firefox-engine browser without native support
A rewrite. Start with the "How it works" overview at the top of src/scoped-custom-element-registry.ts, then read the file rather than the line diff.
behavior.test.js and parsing.test.html(.js) are new; tests of polyfill-only behavior, and of spec behavior Chromium gets wrong, use itWithPolyfill so the suite also runs against native implementations.
2162b48 to
698b7c2
Compare
| 'registry' | ||
| ] = registry; | ||
| (shadowRoot as ShadowRootInitWithSettableCustomElements)[ | ||
| 'customElements' |
There was a problem hiding this comment.
should this not be customElementRegistry?
There was a problem hiding this comment.
registry and customElements are names from earlier versions of the proposal, set as plain properties so old code keeps working. Can drop them if we don't think back compat matters anymore.
There was a problem hiding this comment.
Right, but the new name of the property is customElementRegistry, which should be set on the shadowRoot, no?
| ? clonedShadowRootRegistries.get(host)! | ||
| : host.hasAttribute(DSD_HOST_ATTRIBUTE) | ||
| ? null | ||
| : getRegistry(host.ownerDocument); |
There was a problem hiding this comment.
Isnt this unnecessarily recusirve? This could just be getDefaultRegistry(node), right?
There was a problem hiding this comment.
It recurses one level because going through getRegistry(host.ownerDocument) picks up a registry initialized on a document specifically rather than its default.
|
|
||
| ## Usage notes | ||
|
|
||
| - **Load it first**, before any markup that uses custom elements is parsed. |
There was a problem hiding this comment.
Let's add instructions on how to load it.
| for the main document's parser, once inserted (before any script that follows | ||
| them runs). The "constructor call trick" is then used to upgrade them. | ||
|
|
||
| ## Supported |
There was a problem hiding this comment.
What's unsupported? Let's add a design doc.
| } | ||
| return instance; | ||
| } as unknown) as typeof HTMLElement; | ||
| window.HTMLElement.prototype = NativeHTMLElement.prototype; |
There was a problem hiding this comment.
Small suggestion: restore HTMLElement's static prototype chain.
window.HTMLElement.prototype = NativeHTMLElement.prototype;
+ Object.setPrototypeOf(window.HTMLElement, Object.getPrototypeOf(NativeHTMLElement)); // Element
Object.defineProperty(window.HTMLElement, 'name', {value: 'HTMLElement'});The patched HTMLElement's [[Prototype]] is Function.prototype, while natively it's Element, so it and every class extending it lose the statics inherited from Node/Element.
| Check | Before | After |
|---|---|---|
Object.getPrototypeOf(HTMLElement) === Element |
false |
true |
HTMLElement.ELEMENT_NODE |
undefined |
1 |
class X extends HTMLElement {}; X.ELEMENT_NODE |
undefined |
1 |
Construction and instanceof are unaffected.
Supersedes #604. Redesigns the polyfill to follow the current spec, including the
customElementRegistryproperty on node,initialize, null registries, thecustomelementregistryattribute, declarative shadow root'sshadowrootcustomelementregistrytemplate attribute, and creation and import options using{customElementRegistry:...}.The polyfill functions only where native support is missing or incomplete. Chrome ~150+, Safari 26.6+, and Firefox 160 (currently in Nightly) have native support but Safari fails detection because it can incorrectly customize null-registry elements. Chrome/Firefox use native support unless the polyfill is forced by setting
window.CustomElementRegistryPolyfill = {force: true}before loading the polyfill script.Size: 30.1 KB minified, 9.2 KB gzipped (previous version was 13.0 KB and 4.2 KB).
How it works and what's changed in this version
(ancestors, null-registry attributes, declarative roots). One call can mix several registries, which a stack can't express.
So the polyfill records each node's registry once the native call has built its tree, via a walk of the new content.
MutationObserverruns while the document loads and customizes parsed elements once they're inserted, so a script that follows an element sees it upgraded, meaning the queue/flush isn't observable.attachInternals,disabledFeaturesand form-associated elements are handled per element's own class but need special wrapping handling since the polyfill interacts with them.Compatibility and behavior changes
registryandcustomElementsoptions toattachShadowstill work (for backwards compatibility with the previous polyfill version).polyfill-shadowrootcustomelementregistryon its host, alongside the standard attribute on its template. This is because the polyfill cannot observe theshadowrootcustomelementregistryattribute on the DSDtemplateelement.:definedmatches stand-ins that haven't been customized, so use:is(:not(:defined), :state(polyfill-undefined))instead.CustomElementRegistryPolyfill.forceloads the polyfill anyway.Where to look. Start with the "How it works" comment near the top of the source, then:
withDeferredUpgradesandflushUpgrades: the queues;getRegistry: how a node's registry is worked out;customize: the upgrade, constructor identity and re-entry;observeParsing;cloneWithRegistries,pairClonedElementandpairUnreachableCopyRoots;adoptRegistries;isFormControland the collection proxy).Tests
Roughly 370 tests per browser, run in Chromium, Firefox and WebKit, and again in Chromium with the polyfill forced. They cover:
#669 adds the WPT custom-element registry tests to the suite: about 2,400 per browser, with a small per-browser list of known failures, each with a known cause.
Follow-ups
setHTMLUnsafelate, so those upgrade a microtask late (microtask could be removed is supporting Firefox < 158 is unnecessary).