Bug 1556342 - Implement customElements.define's form-associated; r=edgar,smaug

Differential Revision: https://phabricator.services.mozilla.com/D85734
This commit is contained in:
John Dai 2020-08-05 09:35:56 +00:00
Родитель 4711a353c1
Коммит 7e2fb3fe0d
10 изменённых файлов: 40 добавлений и 22 удалений

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/ShadowIncludingTreeIterator.h"
#include "mozilla/dom/XULElementBinding.h"
#include "mozilla/dom/Promise.h"
@ -847,6 +848,7 @@ void CustomElementRegistry::Define(
auto callbacksHolder = MakeUnique<LifecycleCallbacks>();
nsTArray<RefPtr<nsAtom>> observedAttributes;
AutoTArray<RefPtr<nsAtom>, 2> disabledFeatures;
bool formAssociated = false;
bool disableInternals = false;
bool disableShadow = false;
{ // Set mIsCustomDefinitionRunning.
@ -921,7 +923,7 @@ void CustomElementRegistry::Define(
* disabledFeaturesIterable to a sequence<DOMString>.
* Rethrow any exceptions from the conversion.
*/
if (StaticPrefs::dom_webcomponents_elementInternals_enabled()) {
if (StaticPrefs::dom_webcomponents_formAssociatedCustomElement_enabled()) {
if (!JSObjectToAtomArray(aCx, constructor, u"disabledFeatures"_ns,
disabledFeatures, aRv)) {
return;
@ -936,6 +938,24 @@ void CustomElementRegistry::Define(
// "shadow".
disableShadow = disabledFeatures.Contains(
static_cast<nsStaticAtom*>(nsGkAtoms::shadow));
// 14.11. Let formAssociatedValue be Get(constructor, "formAssociated").
// Rethrow any exceptions.
JS::Rooted<JS::Value> formAssociatedValue(aCx);
if (!JS_GetProperty(aCx, constructor, "formAssociated",
&formAssociatedValue)) {
aRv.NoteJSContextException(aCx);
return;
}
// 14.12. Set formAssociated to the result of converting
// formAssociatedValue to a boolean. Rethrow any exceptions from
// the conversion.
if (!ValueToPrimitive<bool, eDefault>(
aCx, formAssociatedValue, "formAssociated", &formAssociated)) {
aRv.NoteJSContextException(aCx);
return;
}
}
} // Unset mIsCustomDefinitionRunning
@ -958,7 +978,7 @@ void CustomElementRegistry::Define(
RefPtr<CustomElementDefinition> definition = new CustomElementDefinition(
nameAtom, localNameAtom, nameSpaceID, &aFunctionConstructor,
std::move(observedAttributes), std::move(callbacksHolder),
std::move(observedAttributes), std::move(callbacksHolder), formAssociated,
disableInternals, disableShadow);
CustomElementDefinition* def = definition.get();
@ -1470,14 +1490,15 @@ CustomElementDefinition::CustomElementDefinition(
nsAtom* aType, nsAtom* aLocalName, int32_t aNamespaceID,
CustomElementConstructor* aConstructor,
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
UniquePtr<LifecycleCallbacks>&& aCallbacks, bool aDisableInternals,
bool aDisableShadow)
UniquePtr<LifecycleCallbacks>&& aCallbacks, bool aFormAssociated,
bool aDisableInternals, bool aDisableShadow)
: mType(aType),
mLocalName(aLocalName),
mNamespaceID(aNamespaceID),
mConstructor(aConstructor),
mObservedAttributes(std::move(aObservedAttributes)),
mCallbacks(std::move(aCallbacks)),
mFormAssociated(aFormAssociated),
mDisableInternals(aDisableInternals),
mDisableShadow(aDisableShadow) {}

Просмотреть файл

@ -141,7 +141,8 @@ struct CustomElementDefinition {
CustomElementConstructor* aConstructor,
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
UniquePtr<LifecycleCallbacks>&& aCallbacks,
bool aDisableInternals, bool aDisableShadow);
bool aFormAssociated, bool aDisableInternals,
bool aDisableShadow);
// The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
// this would be x-foo.
@ -162,6 +163,10 @@ struct CustomElementDefinition {
// The lifecycle callbacks to call for this custom element.
UniquePtr<LifecycleCallbacks> mCallbacks;
// If this is true, user agent treats elements associated to this custom
// element definition as form-associated custom elements.
bool mFormAssociated = false;
// Determine whether to allow to attachInternals() for this custom element.
bool mDisableInternals = false;

Просмотреть файл

@ -1029,7 +1029,8 @@ bool Element::CanAttachShadowDOM() const {
// It will always have CustomElementData when the element is a valid custom
// element or has is value.
CustomElementData* ceData = GetCustomElementData();
if (StaticPrefs::dom_webcomponents_elementInternals_enabled() && ceData) {
if (StaticPrefs::dom_webcomponents_formAssociatedCustomElement_enabled() &&
ceData) {
CustomElementDefinition* definition = ceData->GetCustomElementDefinition();
// If the definition is null, the element possible hasn't yet upgraded.
// Fallback to use LookupCustomElementDefinition to find its definition.

Просмотреть файл

@ -7,7 +7,7 @@
* https://html.spec.whatwg.org/#elementinternals
*/
[Pref="dom.webcomponents.elementInternals.enabled", Exposed=Window]
[Pref="dom.webcomponents.formAssociatedCustomElement.enabled", Exposed=Window]
interface ElementInternals {
};

Просмотреть файл

@ -68,7 +68,7 @@ interface HTMLElement : Element {
//readonly attribute boolean? commandChecked;
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals
[Pref="dom.webcomponents.elementInternals.enabled", Throws]
[Pref="dom.webcomponents.formAssociatedCustomElement.enabled", Throws]
ElementInternals attachInternals();
};

Просмотреть файл

@ -3232,8 +3232,8 @@
value: false
mirror: always
# Is support for elementInternals enabled?
- name: dom.webcomponents.elementInternals.enabled
# Is support for form-associated custom element enabled?
- name: dom.webcomponents.formAssociatedCustomElement.enabled
type: bool
value: @IS_NIGHTLY_BUILD@
mirror: always

Просмотреть файл

@ -11,18 +11,9 @@
[customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present]
expected: FAIL
[customElements.define must rethrow an exception thrown while getting formAssociated on the constructor prototype]
expected: FAIL
[customElements.define must rethrow an exception thrown while getting additional formAssociated callbacks on the constructor prototype]
expected: FAIL
[customElements.define must get four additional callbacks on the prototype if formAssociated is converted to true]
expected: FAIL
[customElements.define must get "prototype", "disabledFeatures", and "formAssociated" property of the constructor]
expected: FAIL
[customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")]
expected: FAIL

Просмотреть файл

@ -1,2 +1,2 @@
prefs: [dom.webcomponents.elementInternals.enabled:true]
prefs: [dom.webcomponents.formAssociatedCustomElement.enabled:true]
leak-threshold: [default:51200]

Просмотреть файл

@ -1,4 +1,4 @@
prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.experimental.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true, dom.webcomponents.elementInternals.enabled:true, dom.forms.requestsubmit.enabled:true, dom.forms.inputmode:true, dom.forms.enterkeyhint:true]
prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.experimental.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true, dom.webcomponents.formAssociatedCustomElement.enabled:true, dom.forms.requestsubmit.enabled:true, dom.forms.inputmode:true, dom.forms.enterkeyhint:true]
[idlharness.https.html?exclude=(Document|Window|HTML.*)]
[OffscreenCanvasRenderingContext2D interface: operation lineTo(unrestricted double, unrestricted double)]
expected: FAIL

Просмотреть файл

@ -1 +1 @@
prefs: [dom.webcomponents.elementInternals.enabled:true]
prefs: [dom.webcomponents.formAssociatedCustomElement.enabled:true]