зеркало из 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;
|
||||
}
|
||||
|
||||
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
|
||||
void CustomElementRegistry::Define(
|
||||
JSContext* aCx, const nsAString& aName,
|
||||
|
@ -782,6 +837,8 @@ void CustomElementRegistry::Define(
|
|||
|
||||
auto callbacksHolder = MakeUnique<LifecycleCallbacks>();
|
||||
nsTArray<RefPtr<nsAtom>> observedAttributes;
|
||||
AutoTArray<RefPtr<nsAtom>, 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<JS::Value> 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<DOMString>.
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (!observedAttributesIterable.isUndefined()) {
|
||||
if (!observedAttributesIterable.isObject()) {
|
||||
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(
|
||||
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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 14.9. Set disableInternals to true if disabledFeaturesSequence contains
|
||||
// "internals".
|
||||
disableInternals = disabledFeatures.Contains(
|
||||
static_cast<nsStaticAtom*>(nsGkAtoms::internals));
|
||||
}
|
||||
} // Unset mIsCustomDefinitionRunning
|
||||
|
||||
|
@ -915,7 +945,8 @@ void CustomElementRegistry::Define(
|
|||
|
||||
RefPtr<CustomElementDefinition> 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<RefPtr<nsAtom>>&& aObservedAttributes,
|
||||
UniquePtr<LifecycleCallbacks>&& aCallbacks)
|
||||
UniquePtr<LifecycleCallbacks>&& 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
|
||||
|
|
|
@ -137,7 +137,8 @@ struct CustomElementDefinition {
|
|||
int32_t aNamespaceID,
|
||||
CustomElementConstructor* aConstructor,
|
||||
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>
|
||||
// this would be x-foo.
|
||||
|
@ -158,6 +159,9 @@ struct CustomElementDefinition {
|
|||
// The lifecycle callbacks to call for this custom element.
|
||||
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
|
||||
// marker".
|
||||
nsTArray<RefPtr<Element>> mConstructionStack;
|
||||
|
@ -458,6 +462,10 @@ class CustomElementRegistry final : public nsISupports, public nsWrapperCache {
|
|||
private:
|
||||
~CustomElementRegistry();
|
||||
|
||||
bool JSObjectToAtomArray(JSContext* aCx, JS::Handle<JSObject*> aConstructor,
|
||||
const char16_t* aName,
|
||||
nsTArray<RefPtr<nsAtom>>& aArray, ErrorResult& aRv);
|
||||
|
||||
static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
||||
Document::ElementCallbackType aType, Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
|
|
|
@ -2620,6 +2620,12 @@
|
|||
value: false
|
||||
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?
|
||||
- name: dom.webgpu.enable
|
||||
type: RelaxedAtomicBool
|
||||
|
|
|
@ -17,18 +17,11 @@
|
|||
[customElements.define must rethrow an exception thrown while getting additional formAssociated callbacks on the constructor prototype]
|
||||
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]
|
||||
expected: FAIL
|
||||
|
||||
[customElements.define must rethrow an exception thrown while getting disabledFeatures on the 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>]
|
||||
[customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")]
|
||||
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("integer", "integer"),
|
||||
Atom("integrity", "integrity"),
|
||||
Atom("internals", "internals"),
|
||||
Atom("intersection", "intersection"),
|
||||
Atom("intersectionobserverlist", "intersectionobserverlist"),
|
||||
Atom("is", "is"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче