Skip to content

Commit

Permalink
Bug 1552313 - Implement disableShadow; r=smaug,edgar
Browse files Browse the repository at this point in the history
Differential Revision: https://phabricator.services.mozilla.com/D52157

--HG--
extra : moz-landing-system : lando
  • Loading branch information
johndai1984 committed Nov 11, 2019
1 parent e95dd01 commit 708988d
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 28 deletions.
30 changes: 25 additions & 5 deletions dom/base/CustomElementRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,7 @@ void CustomElementRegistry::Define(
nsTArray<RefPtr<nsAtom>> observedAttributes;
AutoTArray<RefPtr<nsAtom>, 2> disabledFeatures;
bool disableInternals = false;
bool disableShadow = false;
{ // Set mIsCustomDefinitionRunning.
/**
* 9. Set this CustomElementRegistry's element definition is running flag.
Expand Down Expand Up @@ -923,6 +924,11 @@ void CustomElementRegistry::Define(
// "internals".
disableInternals = disabledFeatures.Contains(
static_cast<nsStaticAtom*>(nsGkAtoms::internals));

// 14.10. Set disableShadow to true if disabledFeaturesSequence contains
// "shadow".
disableShadow = disabledFeatures.Contains(
static_cast<nsStaticAtom*>(nsGkAtoms::shadow));
}
} // Unset mIsCustomDefinitionRunning

Expand All @@ -946,7 +952,7 @@ void CustomElementRegistry::Define(
RefPtr<CustomElementDefinition> definition = new CustomElementDefinition(
nameAtom, localNameAtom, nameSpaceID, &aFunctionConstructor,
std::move(observedAttributes), std::move(callbacksHolder),
disableInternals);
disableInternals, disableShadow);

CustomElementDefinition* def = definition.get();
mCustomDefinitions.Put(nameAtom, definition.forget());
Expand Down Expand Up @@ -1083,8 +1089,19 @@ already_AddRefed<Promise> CustomElementRegistry::WhenDefined(
namespace {

MOZ_CAN_RUN_SCRIPT
static void DoUpgrade(Element* aElement, CustomElementConstructor* aConstructor,
static void DoUpgrade(Element* aElement, CustomElementDefinition* aDefinition,
CustomElementConstructor* aConstructor,
ErrorResult& aRv) {
if (aDefinition->mDisableShadow && aElement->GetShadowRoot()) {
aRv.ThrowDOMException(
NS_ERROR_DOM_NOT_SUPPORTED_ERR,
nsPrintfCString(
"Custom element upgrade to '%s' is disabled due to shadow root "
"already exists",
NS_ConvertUTF16toUTF8(aDefinition->mType->GetUTF16String()).get()));
return;
}

JS::Rooted<JS::Value> constructResult(RootingCx());
// Rethrow the exception since it might actually throw the exception from the
// upgrade steps back out to the caller of document.createElement.
Expand Down Expand Up @@ -1155,7 +1172,8 @@ void CustomElementRegistry::Upgrade(Element* aElement,
AutoConstructionStackEntry acs(aDefinition->mConstructionStack, aElement);

// Step 6 and step 7.
DoUpgrade(aElement, MOZ_KnownLive(aDefinition->mConstructor), aRv);
DoUpgrade(aElement, aDefinition, MOZ_KnownLive(aDefinition->mConstructor),
aRv);
if (aRv.Failed()) {
data->mState = CustomElementData::State::eFailed;
// Empty element's custom element reaction queue.
Expand Down Expand Up @@ -1436,14 +1454,16 @@ CustomElementDefinition::CustomElementDefinition(
nsAtom* aType, nsAtom* aLocalName, int32_t aNamespaceID,
CustomElementConstructor* aConstructor,
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
UniquePtr<LifecycleCallbacks>&& aCallbacks, bool aDisableInternals)
UniquePtr<LifecycleCallbacks>&& aCallbacks, bool aDisableInternals,
bool aDisableShadow)
: mType(aType),
mLocalName(aLocalName),
mNamespaceID(aNamespaceID),
mConstructor(aConstructor),
mObservedAttributes(std::move(aObservedAttributes)),
mCallbacks(std::move(aCallbacks)),
mDisableInternals(aDisableInternals) {}
mDisableInternals(aDisableInternals),
mDisableShadow(aDisableShadow) {}

} // namespace dom
} // namespace mozilla
5 changes: 4 additions & 1 deletion dom/base/CustomElementRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ struct CustomElementDefinition {
CustomElementConstructor* aConstructor,
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
UniquePtr<LifecycleCallbacks>&& aCallbacks,
bool aDisableInternals);
bool aDisableInternals, bool aDisableShadow);

// The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
// this would be x-foo.
Expand All @@ -162,6 +162,9 @@ struct CustomElementDefinition {
// Determine whether to allow to attachInternals() for this custom element.
bool mDisableInternals = false;

// Determine whether to allow to attachShadow() for this custom element.
bool mDisableShadow = false;

// A construction stack. Use nullptr to represent an "already constructed
// marker".
nsTArray<RefPtr<Element>> mConstructionStack;
Expand Down
34 changes: 29 additions & 5 deletions dom/base/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,8 @@ bool Element::CanAttachShadowDOM() const {
* return false.
*/
nsAtom* nameAtom = NodeInfo()->NameAtom();
if (!(nsContentUtils::IsCustomElementName(nameAtom,
NodeInfo()->NamespaceID()) ||
uint32_t namespaceID = NodeInfo()->NamespaceID();
if (!(nsContentUtils::IsCustomElementName(nameAtom, namespaceID) ||
nameAtom == nsGkAtoms::article || nameAtom == nsGkAtoms::aside ||
nameAtom == nsGkAtoms::blockquote || nameAtom == nsGkAtoms::body ||
nameAtom == nsGkAtoms::div || nameAtom == nsGkAtoms::footer ||
Expand All @@ -991,6 +991,30 @@ bool Element::CanAttachShadowDOM() const {
return false;
}

/**
* 3. If context object’s local name is a valid custom element name, or
* context object’s is value is not null, then:
* If definition is not null and definition’s disable shadow is true, then
* return false.
*/
// 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) {
CustomElementDefinition* definition = ceData->GetCustomElementDefinition();
// If the definition is null, the element possible hasn't yet upgraded.
// Fallback to use LookupCustomElementDefinition to find its definition.
if (!definition) {
definition = nsContentUtils::LookupCustomElementDefinition(
NodeInfo()->GetDocument(), nameAtom, namespaceID,
ceData->GetCustomElementType());
}

if (definition && definition->mDisableShadow) {
return false;
}
}

return true;
}

Expand All @@ -1009,11 +1033,11 @@ already_AddRefed<ShadowRoot> Element::AttachShadow(const ShadowRootInit& aInit,
}

/**
* 3. If context object is a shadow host, then throw
* an "InvalidStateError" DOMException.
* 4. If context object is a shadow host, then throw
* an "NotSupportedError" DOMException.
*/
if (GetShadowRoot()) {
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}

Expand Down
5 changes: 0 additions & 5 deletions testing/web-platform/meta/custom-elements/upgrading.html.ini

This file was deleted.

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions testing/web-platform/meta/shadow-dom/__dir__.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
prefs: [dom.webcomponents.elementInternals.enabled:true]
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@

test(() => {
class CapitalShadowDisabledElement extends HTMLElement {
static get disabledFeatures() { return ['shadow']; }
static get disabledFeatures() { return ['SHADOW']; }
}

customElements.define('capital-shadow-disabled-element', CapitalShadowDisabledElement);
Expand Down
1 change: 1 addition & 0 deletions xpcom/ds/StaticAtoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,7 @@
Atom("seltype", "seltype"),
Atom("setcookie", "set-cookie"),
Atom("setter", "setter"),
Atom("shadow", "shadow"),
Atom("shape", "shape"),
Atom("show", "show"),
Atom("showcaret", "showcaret"),
Expand Down

0 comments on commit 708988d

Please sign in to comment.