diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 940c5d721ce2..76ebf29b85d8 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -636,6 +636,61 @@ int32_t CustomElementRegistry::InferNamespace( return kNameSpaceID_XHTML; } +bool CustomElementRegistry::JSObjectToAtomArray( + JSContext* aCx, JS::Handle aConstructor, const char16_t* aName, + nsTArray>& aArray, ErrorResult& aRv) { + JS::RootedValue iterable(aCx, JS::UndefinedValue()); + if (!JS_GetUCProperty(aCx, aConstructor, aName, + std::char_traits::length(aName), &iterable)) { + aRv.NoteJSContextException(aCx); + return false; + } + + if (!iterable.isUndefined()) { + if (!iterable.isObject()) { + aRv.ThrowTypeError(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(nsDependentString(aName)); + return false; + } + + JS::Rooted 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 void CustomElementRegistry::Define( JSContext* aCx, const nsAString& aName, @@ -782,6 +837,8 @@ void CustomElementRegistry::Define( auto callbacksHolder = MakeUnique(); nsTArray> observedAttributes; + AutoTArray, 2> disabledFeatures; + bool disableInternals = false; { // Set mIsCustomDefinitionRunning. /** * 9. Set this CustomElementRegistry's element definition is running flag. @@ -841,58 +898,31 @@ void CustomElementRegistry::Define( * any exceptions from the conversion. */ if (callbacksHolder->mAttributeChangedCallback.WasPassed()) { - JS::Rooted observedAttributesIterable(aCx); + if (!JSObjectToAtomArray(aCx, constructor, u"observedAttributes", + observedAttributes, aRv)) { + return; + } + } - if (!JS_GetProperty(aCx, constructor, "observedAttributes", - &observedAttributesIterable)) { - aRv.NoteJSContextException(aCx); + /** + * 14.6. Let disabledFeatures be an empty sequence. + * 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. + * Rethrow any exceptions from the conversion. + */ + if (StaticPrefs::dom_webcomponents_elementInternals_enabled()) { + if (!JSObjectToAtomArray(aCx, constructor, u"disabledFeatures", + disabledFeatures, aRv)) { return; } - if (!observedAttributesIterable.isUndefined()) { - if (!observedAttributesIterable.isObject()) { - aRv.ThrowTypeError( - NS_LITERAL_STRING("observedAttributes")); - return; - } - - JS::ForOfIterator iter(aCx); - if (!iter.init(observedAttributesIterable, - JS::ForOfIterator::AllowNonIterable)) { - aRv.NoteJSContextException(aCx); - return; - } - - if (!iter.valueIsIterable()) { - aRv.ThrowTypeError( - NS_LITERAL_STRING("observedAttributes")); - return; - } - - JS::Rooted 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; - } - } - } + // 14.9. Set disableInternals to true if disabledFeaturesSequence contains + // "internals". + disableInternals = disabledFeatures.Contains( + static_cast(nsGkAtoms::internals)); } } // Unset mIsCustomDefinitionRunning @@ -915,7 +945,8 @@ void CustomElementRegistry::Define( RefPtr definition = new CustomElementDefinition( nameAtom, localNameAtom, nameSpaceID, &aFunctionConstructor, - std::move(observedAttributes), std::move(callbacksHolder)); + std::move(observedAttributes), std::move(callbacksHolder), + disableInternals); CustomElementDefinition* def = definition.get(); mCustomDefinitions.Put(nameAtom, definition.forget()); @@ -1405,13 +1436,14 @@ CustomElementDefinition::CustomElementDefinition( nsAtom* aType, nsAtom* aLocalName, int32_t aNamespaceID, CustomElementConstructor* aConstructor, nsTArray>&& aObservedAttributes, - UniquePtr&& aCallbacks) + UniquePtr&& aCallbacks, bool aDisableInternals) : mType(aType), mLocalName(aLocalName), mNamespaceID(aNamespaceID), mConstructor(aConstructor), mObservedAttributes(std::move(aObservedAttributes)), - mCallbacks(std::move(aCallbacks)) {} + mCallbacks(std::move(aCallbacks)), + mDisableInternals(aDisableInternals) {} } // namespace dom } // namespace mozilla diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h index aaa4557c3bff..dc54a361d29c 100644 --- a/dom/base/CustomElementRegistry.h +++ b/dom/base/CustomElementRegistry.h @@ -137,7 +137,8 @@ struct CustomElementDefinition { int32_t aNamespaceID, CustomElementConstructor* aConstructor, nsTArray>&& aObservedAttributes, - UniquePtr&& aCallbacks); + UniquePtr&& aCallbacks, + bool aDisableInternals); // The type (name) for this custom element, for