зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1552313 - Implement custom element disabledFeatures and disableInternals; r=smaug,edgar
- Introduce `dom.webcomponents.elementInternals.enabled` for custom element's elementInternals. - Implement disabledFeatures static field and disableInternals. - Refactor get observedAttributes sequence. Differential Revision: https://phabricator.services.mozilla.com/D52156 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
5188ad0370
Коммит
e95dd01125
|
@ -636,6 +636,61 @@ int32_t CustomElementRegistry::InferNamespace(
|
||||||
return kNameSpaceID_XHTML;
|
return kNameSpaceID_XHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CustomElementRegistry::JSObjectToAtomArray(
|
||||||
|
JSContext* aCx, JS::Handle<JSObject*> aConstructor, const char16_t* aName,
|
||||||
|
nsTArray<RefPtr<nsAtom>>& aArray, ErrorResult& aRv) {
|
||||||
|
JS::RootedValue iterable(aCx, JS::UndefinedValue());
|
||||||
|
if (!JS_GetUCProperty(aCx, aConstructor, aName,
|
||||||
|
std::char_traits<char16_t>::length(aName), &iterable)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iterable.isUndefined()) {
|
||||||
|
if (!iterable.isObject()) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(nsDependentString(aName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::ForOfIterator iter(aCx);
|
||||||
|
if (!iter.init(iterable, JS::ForOfIterator::AllowNonIterable)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iter.valueIsIterable()) {
|
||||||
|
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(nsDependentString(aName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> attribute(aCx);
|
||||||
|
while (true) {
|
||||||
|
bool done;
|
||||||
|
if (!iter.next(&attribute, &done)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString attrStr;
|
||||||
|
if (!ConvertJSValueToString(aCx, attribute, eStringify, eStringify,
|
||||||
|
attrStr)) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aArray.AppendElement(NS_Atomize(attrStr))) {
|
||||||
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/scripting.html#element-definition
|
// https://html.spec.whatwg.org/multipage/scripting.html#element-definition
|
||||||
void CustomElementRegistry::Define(
|
void CustomElementRegistry::Define(
|
||||||
JSContext* aCx, const nsAString& aName,
|
JSContext* aCx, const nsAString& aName,
|
||||||
|
@ -782,6 +837,8 @@ void CustomElementRegistry::Define(
|
||||||
|
|
||||||
auto callbacksHolder = MakeUnique<LifecycleCallbacks>();
|
auto callbacksHolder = MakeUnique<LifecycleCallbacks>();
|
||||||
nsTArray<RefPtr<nsAtom>> observedAttributes;
|
nsTArray<RefPtr<nsAtom>> observedAttributes;
|
||||||
|
AutoTArray<RefPtr<nsAtom>, 2> disabledFeatures;
|
||||||
|
bool disableInternals = false;
|
||||||
{ // Set mIsCustomDefinitionRunning.
|
{ // Set mIsCustomDefinitionRunning.
|
||||||
/**
|
/**
|
||||||
* 9. Set this CustomElementRegistry's element definition is running flag.
|
* 9. Set this CustomElementRegistry's element definition is running flag.
|
||||||
|
@ -841,58 +898,31 @@ void CustomElementRegistry::Define(
|
||||||
* any exceptions from the conversion.
|
* any exceptions from the conversion.
|
||||||
*/
|
*/
|
||||||
if (callbacksHolder->mAttributeChangedCallback.WasPassed()) {
|
if (callbacksHolder->mAttributeChangedCallback.WasPassed()) {
|
||||||
JS::Rooted<JS::Value> observedAttributesIterable(aCx);
|
if (!JSObjectToAtomArray(aCx, constructor, u"observedAttributes",
|
||||||
|
observedAttributes, aRv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!JS_GetProperty(aCx, constructor, "observedAttributes",
|
/**
|
||||||
&observedAttributesIterable)) {
|
* 14.6. Let disabledFeatures be an empty sequence<DOMString>.
|
||||||
aRv.NoteJSContextException(aCx);
|
* 14.7. Let disabledFeaturesIterable be Get(constructor,
|
||||||
|
* "disabledFeatures"). Rethrow any exceptions.
|
||||||
|
* 14.8. If disabledFeaturesIterable is not undefined, then set
|
||||||
|
* disabledFeatures to the result of converting
|
||||||
|
* disabledFeaturesIterable to a sequence<DOMString>.
|
||||||
|
* Rethrow any exceptions from the conversion.
|
||||||
|
*/
|
||||||
|
if (StaticPrefs::dom_webcomponents_elementInternals_enabled()) {
|
||||||
|
if (!JSObjectToAtomArray(aCx, constructor, u"disabledFeatures",
|
||||||
|
disabledFeatures, aRv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!observedAttributesIterable.isUndefined()) {
|
// 14.9. Set disableInternals to true if disabledFeaturesSequence contains
|
||||||
if (!observedAttributesIterable.isObject()) {
|
// "internals".
|
||||||
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(
|
disableInternals = disabledFeatures.Contains(
|
||||||
NS_LITERAL_STRING("observedAttributes"));
|
static_cast<nsStaticAtom*>(nsGkAtoms::internals));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::ForOfIterator iter(aCx);
|
|
||||||
if (!iter.init(observedAttributesIterable,
|
|
||||||
JS::ForOfIterator::AllowNonIterable)) {
|
|
||||||
aRv.NoteJSContextException(aCx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iter.valueIsIterable()) {
|
|
||||||
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(
|
|
||||||
NS_LITERAL_STRING("observedAttributes"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> attribute(aCx);
|
|
||||||
while (true) {
|
|
||||||
bool done;
|
|
||||||
if (!iter.next(&attribute, &done)) {
|
|
||||||
aRv.NoteJSContextException(aCx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (done) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString attrStr;
|
|
||||||
if (!ConvertJSValueToString(aCx, attribute, eStringify, eStringify,
|
|
||||||
attrStr)) {
|
|
||||||
aRv.NoteJSContextException(aCx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!observedAttributes.AppendElement(NS_Atomize(attrStr))) {
|
|
||||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // Unset mIsCustomDefinitionRunning
|
} // Unset mIsCustomDefinitionRunning
|
||||||
|
|
||||||
|
@ -915,7 +945,8 @@ void CustomElementRegistry::Define(
|
||||||
|
|
||||||
RefPtr<CustomElementDefinition> definition = new CustomElementDefinition(
|
RefPtr<CustomElementDefinition> definition = new CustomElementDefinition(
|
||||||
nameAtom, localNameAtom, nameSpaceID, &aFunctionConstructor,
|
nameAtom, localNameAtom, nameSpaceID, &aFunctionConstructor,
|
||||||
std::move(observedAttributes), std::move(callbacksHolder));
|
std::move(observedAttributes), std::move(callbacksHolder),
|
||||||
|
disableInternals);
|
||||||
|
|
||||||
CustomElementDefinition* def = definition.get();
|
CustomElementDefinition* def = definition.get();
|
||||||
mCustomDefinitions.Put(nameAtom, definition.forget());
|
mCustomDefinitions.Put(nameAtom, definition.forget());
|
||||||
|
@ -1405,13 +1436,14 @@ CustomElementDefinition::CustomElementDefinition(
|
||||||
nsAtom* aType, nsAtom* aLocalName, int32_t aNamespaceID,
|
nsAtom* aType, nsAtom* aLocalName, int32_t aNamespaceID,
|
||||||
CustomElementConstructor* aConstructor,
|
CustomElementConstructor* aConstructor,
|
||||||
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
||||||
UniquePtr<LifecycleCallbacks>&& aCallbacks)
|
UniquePtr<LifecycleCallbacks>&& aCallbacks, bool aDisableInternals)
|
||||||
: mType(aType),
|
: mType(aType),
|
||||||
mLocalName(aLocalName),
|
mLocalName(aLocalName),
|
||||||
mNamespaceID(aNamespaceID),
|
mNamespaceID(aNamespaceID),
|
||||||
mConstructor(aConstructor),
|
mConstructor(aConstructor),
|
||||||
mObservedAttributes(std::move(aObservedAttributes)),
|
mObservedAttributes(std::move(aObservedAttributes)),
|
||||||
mCallbacks(std::move(aCallbacks)) {}
|
mCallbacks(std::move(aCallbacks)),
|
||||||
|
mDisableInternals(aDisableInternals) {}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -137,7 +137,8 @@ struct CustomElementDefinition {
|
||||||
int32_t aNamespaceID,
|
int32_t aNamespaceID,
|
||||||
CustomElementConstructor* aConstructor,
|
CustomElementConstructor* aConstructor,
|
||||||
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
||||||
UniquePtr<LifecycleCallbacks>&& aCallbacks);
|
UniquePtr<LifecycleCallbacks>&& aCallbacks,
|
||||||
|
bool aDisableInternals);
|
||||||
|
|
||||||
// The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
|
// The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
|
||||||
// this would be x-foo.
|
// this would be x-foo.
|
||||||
|
@ -158,6 +159,9 @@ struct CustomElementDefinition {
|
||||||
// The lifecycle callbacks to call for this custom element.
|
// The lifecycle callbacks to call for this custom element.
|
||||||
UniquePtr<LifecycleCallbacks> mCallbacks;
|
UniquePtr<LifecycleCallbacks> mCallbacks;
|
||||||
|
|
||||||
|
// Determine whether to allow to attachInternals() for this custom element.
|
||||||
|
bool mDisableInternals = false;
|
||||||
|
|
||||||
// A construction stack. Use nullptr to represent an "already constructed
|
// A construction stack. Use nullptr to represent an "already constructed
|
||||||
// marker".
|
// marker".
|
||||||
nsTArray<RefPtr<Element>> mConstructionStack;
|
nsTArray<RefPtr<Element>> mConstructionStack;
|
||||||
|
@ -458,6 +462,10 @@ class CustomElementRegistry final : public nsISupports, public nsWrapperCache {
|
||||||
private:
|
private:
|
||||||
~CustomElementRegistry();
|
~CustomElementRegistry();
|
||||||
|
|
||||||
|
bool JSObjectToAtomArray(JSContext* aCx, JS::Handle<JSObject*> aConstructor,
|
||||||
|
const char16_t* aName,
|
||||||
|
nsTArray<RefPtr<nsAtom>>& aArray, ErrorResult& aRv);
|
||||||
|
|
||||||
static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
||||||
Document::ElementCallbackType aType, Element* aCustomElement,
|
Document::ElementCallbackType aType, Element* aCustomElement,
|
||||||
LifecycleCallbackArgs* aArgs,
|
LifecycleCallbackArgs* aArgs,
|
||||||
|
|
|
@ -2620,6 +2620,12 @@
|
||||||
value: false
|
value: false
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
|
# Is support for elementInternals enabled?
|
||||||
|
- name: dom.webcomponents.elementInternals.enabled
|
||||||
|
type: bool
|
||||||
|
value: @IS_NIGHTLY_BUILD@
|
||||||
|
mirror: always
|
||||||
|
|
||||||
# Is support for the Web GPU API enabled?
|
# Is support for the Web GPU API enabled?
|
||||||
- name: dom.webgpu.enable
|
- name: dom.webgpu.enable
|
||||||
type: RelaxedAtomicBool
|
type: RelaxedAtomicBool
|
||||||
|
|
|
@ -17,18 +17,11 @@
|
||||||
[customElements.define must rethrow an exception thrown while getting additional formAssociated callbacks on the constructor prototype]
|
[customElements.define must rethrow an exception thrown while getting additional formAssociated callbacks on the constructor prototype]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on disabledFeatures]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must get four additional callbacks on the prototype if formAssociated is converted to true]
|
[customElements.define must get four additional callbacks on the prototype if formAssociated is converted to true]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while getting disabledFeatures on the constructor prototype]
|
[customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")]
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while iterating over disabledFeatures to sequence<DOMString>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while converting the value of disabledFeatures to sequence<DOMString>]
|
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[customElements.define must get "prototype" property of the constructor ]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1 @@
|
||||||
|
prefs: [dom.webcomponents.elementInternals.enabled:true]
|
|
@ -537,6 +537,7 @@ STATIC_ATOMS = [
|
||||||
Atom("insertion", "insertion"),
|
Atom("insertion", "insertion"),
|
||||||
Atom("integer", "integer"),
|
Atom("integer", "integer"),
|
||||||
Atom("integrity", "integrity"),
|
Atom("integrity", "integrity"),
|
||||||
|
Atom("internals", "internals"),
|
||||||
Atom("intersection", "intersection"),
|
Atom("intersection", "intersection"),
|
||||||
Atom("intersectionobserverlist", "intersectionobserverlist"),
|
Atom("intersectionobserverlist", "intersectionobserverlist"),
|
||||||
Atom("is", "is"),
|
Atom("is", "is"),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче