Closed Bug 1392970 Opened 7 years ago Closed 7 years ago

Consider having a reference of the CustomElementDefinition in the custom element itself

Categories

(Core :: DOM: Core & HTML, enhancement, P2)

enhancement

Tracking

()

RESOLVED FIXED
mozilla58
Tracking Status
firefox58 --- fixed

People

(Reporter: jessica, Assigned: jessica)

References

Details

(Whiteboard: dom-ce-m3)

Attachments

(2 files, 3 obsolete files)

Now, we store the list of CustomElementDefinitions in CustomElementRegistry, but we need to go through the list every time when want to get the custom element definition of a given element. It'd save us a lot of time if we keep a reference of the CustomElementDefinition in the custom element itself.
The idea is to put CustomElementDefinition in CustomElementData. CustomElementData is created when an element might be a custom element: has a valid custom element name or has an 'is' attribute. There may be the case where the CustomElementData is created without having a CustomElementDefinition, but we can always fill in the CustomElementDefinition when the custom element is later upgraded. Right now, we put the custom element state [1] 'mState' in CustomElementData (which is stored in an element's extended slots), I wonder whether we should move this to Element since a non-custom element may not have a CustomElementData but its state should be 'uncustomized'. [1] https://dom.spec.whatwg.org/#concept-element-custom-element-state
Priority: -- → P2
Hi Olli, this is just the first step, may I have your early feedback? especially on those CC stuff. Thanks.
Attachment #8902227 - Flags: feedback?(bugs)
Comment on attachment 8902227 [details] [diff] [review] Part 1: Make CE Definition ref-counted and put in in CE Data. >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition) >+ auto& callbacks = tmp->mCallbacks; I know you just moved the code here, but I wouldn't mind remove use of auto& and use the actual type. Would make reading the code easier. >+ void >+ SetCustomElementDefinition(CustomElementDefinition* aDefinition) >+ { >+ MOZ_ASSERT(!mCustomElementDefinition); >+ >+ mCustomElementDefinition = aDefinition; >+ } >+ >+ CustomElementDefinition* >+ GetCustomElementDefinition() >+ { >+ if (mState != State::eCustom) { >+ return nullptr; >+ } >+ >+ return mCustomElementDefinition; This could use a comment. How state can be non-custom, yet mCustomElementDefinition non-null? >+ void Unlink() >+ { >+ CustomElementDefinition* tmp = this; >+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mConstructor) >+ mPrototype = nullptr; >+ mCallbacks = nullptr; >+ } It is unclear why we need this, and why this isn't in _UNLINK nsDOMSlots::Unlink should be able to just set the mCustomElementDefinition to null. >+CustomElementDefinition* >+Element::GetCustomElementDefinition() const >+{ >+ CustomElementData* data = GetCustomElementData(); >+ MOZ_ASSERT(data); GetCustomElementData() may return null, so this probably shouldn't just assert. >+Element::SetCustomElementDefinition(CustomElementDefinition* aDefinition) >+{ >+ MOZ_ASSERT(aDefinition); >+ >+ CustomElementData* data = GetCustomElementData(); >+ MOZ_ASSERT(data); Same here >+ /** >+ * Gets the custom element definition used by web components custom element. >+ * >+ * @return The custom element definition or null if custom element state is >+ * not 'custom' or custom element is not defined yet. >+ */ >+ CustomElementDefinition* GetCustomElementDefinition() const; And this even documents that null is returned if state isn't custom. > if (mExtendedSlots->mCustomElementData) { > for (uint32_t i = 0; > i < mExtendedSlots->mCustomElementData->mReactionQueue.Length(); i++) { > if (mExtendedSlots->mCustomElementData->mReactionQueue[i]) { > mExtendedSlots->mCustomElementData->mReactionQueue[i]->Traverse(cb); > } > } >+ >+ if (mExtendedSlots->mCustomElementData->mCustomElementDefinition) { >+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, >+ "mExtendedSlots->mCustomElementData->mCustomElementDefinition"); >+ cb.NoteNativeChild(mExtendedSlots->mCustomElementData->mCustomElementDefinition, >+ NS_CYCLE_COLLECTION_PARTICIPANT(CustomElementDefinition)); >+ } > } > > for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter(); > !iter.Done(); iter.Next()) { > DOMIntersectionObserver* observer = iter.Key(); > NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, > "mExtendedSlots->mRegisteredIntersectionObservers[i]"); > cb.NoteXPCOMChild(observer); >@@ -844,16 +851,22 @@ FragmentOrElement::nsDOMSlots::Unlink() > mExtendedSlots->mSMILOverrideStyle = nullptr; > mExtendedSlots->mControllers = nullptr; > mExtendedSlots->mLabelsList = nullptr; > mExtendedSlots->mShadowRoot = nullptr; > mExtendedSlots->mContainingShadow = nullptr; > MOZ_ASSERT(!(mExtendedSlots->mXBLBinding)); > mExtendedSlots->mXBLInsertionParent = nullptr; > mExtendedSlots->mCustomElementData = nullptr; >+ if (mExtendedSlots->mCustomElementData) { This can't be right. You first set mExtendedSlots->mCustomElementData to null and then check that it isn't null ;)
Attachment #8902227 - Flags: feedback?(bugs) → feedback+
(In reply to Olli Pettay [:smaug] from comment #3) > Comment on attachment 8902227 [details] [diff] [review] > Part 1: Make CE Definition ref-counted and put in in CE Data. > > >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition) > >+ auto& callbacks = tmp->mCallbacks; > I know you just moved the code here, but I wouldn't mind remove use of auto& > and use the > actual type. Would make reading the code easier. Sure, will do. > >+ void > >+ SetCustomElementDefinition(CustomElementDefinition* aDefinition) > >+ { > >+ MOZ_ASSERT(!mCustomElementDefinition); > >+ > >+ mCustomElementDefinition = aDefinition; > >+ } > >+ > >+ CustomElementDefinition* > >+ GetCustomElementDefinition() > >+ { > >+ if (mState != State::eCustom) { > >+ return nullptr; > >+ } > >+ > >+ return mCustomElementDefinition; > This could use a comment. How state can be non-custom, yet > mCustomElementDefinition non-null? Ok, will add some comments here. > > >+ void Unlink() > >+ { > >+ CustomElementDefinition* tmp = this; > >+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mConstructor) > >+ mPrototype = nullptr; > >+ mCallbacks = nullptr; > >+ } > It is unclear why we need this, and why this isn't in _UNLINK > nsDOMSlots::Unlink should be able to just set the mCustomElementDefinition > to null. I see, I'll remove this function and move these lines in _UNLINK. > > > >+CustomElementDefinition* > >+Element::GetCustomElementDefinition() const > >+{ > >+ CustomElementData* data = GetCustomElementData(); > >+ MOZ_ASSERT(data); > GetCustomElementData() may return null, so this probably shouldn't just > assert. You're right, we should just return null if there is no CustomElementData. > > > >+Element::SetCustomElementDefinition(CustomElementDefinition* aDefinition) > >+{ > >+ MOZ_ASSERT(aDefinition); > >+ > >+ CustomElementData* data = GetCustomElementData(); > >+ MOZ_ASSERT(data); > Same here I'd prefer to keep the assertion here, if we set a CE definition to a non-custom element, that's probably wrong and there should only be a few places where we set the the custom element definition to an element. > > > >+ /** > >+ * Gets the custom element definition used by web components custom element. > >+ * > >+ * @return The custom element definition or null if custom element state is > >+ * not 'custom' or custom element is not defined yet. > >+ */ > >+ CustomElementDefinition* GetCustomElementDefinition() const; > And this even documents that null is returned if state isn't custom. > > if (mExtendedSlots->mCustomElementData) { > > for (uint32_t i = 0; > > i < mExtendedSlots->mCustomElementData->mReactionQueue.Length(); i++) { > > if (mExtendedSlots->mCustomElementData->mReactionQueue[i]) { > > mExtendedSlots->mCustomElementData->mReactionQueue[i]->Traverse(cb); > > } > > } > >+ > >+ if (mExtendedSlots->mCustomElementData->mCustomElementDefinition) { > >+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, > >+ "mExtendedSlots->mCustomElementData->mCustomElementDefinition"); > >+ cb.NoteNativeChild(mExtendedSlots->mCustomElementData->mCustomElementDefinition, > >+ NS_CYCLE_COLLECTION_PARTICIPANT(CustomElementDefinition)); > >+ } > > } > > > > for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter(); > > !iter.Done(); iter.Next()) { > > DOMIntersectionObserver* observer = iter.Key(); > > NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, > > "mExtendedSlots->mRegisteredIntersectionObservers[i]"); > > cb.NoteXPCOMChild(observer); > >@@ -844,16 +851,22 @@ FragmentOrElement::nsDOMSlots::Unlink() > > mExtendedSlots->mSMILOverrideStyle = nullptr; > > mExtendedSlots->mControllers = nullptr; > > mExtendedSlots->mLabelsList = nullptr; > > mExtendedSlots->mShadowRoot = nullptr; > > mExtendedSlots->mContainingShadow = nullptr; > > MOZ_ASSERT(!(mExtendedSlots->mXBLBinding)); > > mExtendedSlots->mXBLInsertionParent = nullptr; > > mExtendedSlots->mCustomElementData = nullptr; > >+ if (mExtendedSlots->mCustomElementData) { > This can't be right. > You first set mExtendedSlots->mCustomElementData to null and then check that > it isn't null ;) Oops, I meant to move that line into the if statement.
(In reply to Jessica Jong [:jessica] from comment #4) > (In reply to Olli Pettay [:smaug] from comment #3) > > >+ void > > >+ SetCustomElementDefinition(CustomElementDefinition* aDefinition) > > >+ { > > >+ MOZ_ASSERT(!mCustomElementDefinition); > > >+ > > >+ mCustomElementDefinition = aDefinition; > > >+ } > > >+ > > >+ CustomElementDefinition* > > >+ GetCustomElementDefinition() > > >+ { > > >+ if (mState != State::eCustom) { > > >+ return nullptr; > > >+ } > > >+ > > >+ return mCustomElementDefinition; > > This could use a comment. How state can be non-custom, yet > > mCustomElementDefinition non-null? > > Ok, will add some comments here. > Actually, we only set custom element definition when custom element state is eCustom, mCustomElementDefinition should be null in other states, so I guess I can just return mCustomElementDefinition here.
Looks like we can't change to use CustomElementDefinition in CustomElementData just yet, since CustomElementDefinition will be put into CustomElementData when: - upgrading - running html constructor And bug 1301024 is in charge of calling the above functions at the correct time for createElement/createElementNS. So using Element::GetCustomElementDefinition will work correctly only after bug 1301024. I can land the part where we set CustomElementDefinition though...
Assignee: nobody → jjong
Whiteboard: dom-ce-m3
Attachment #8902227 - Attachment is obsolete: true
Attachment #8904290 - Flags: review?(bugs)
I'd like to get the patches reviewed first but they need to land AFTER bug 1301024.
Attachment #8904290 - Flags: review?(bugs) → review+
Comment on attachment 8904291 [details] [diff] [review] Part 2: Get CE Defintion from CE Data when possible, v1. ># HG changeset patch ># User Jessica Jong <jjong@mozilla.com> ># Parent 07c702fd588696cdb0ea534e6800ee28918d97eb >Bug 1392970 - Part 2: Get CustomElementDefinition from CustomElementData when possible. r=smaug > >MozReview-Commit-ID: L6DCtGXBesX > >diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp >--- a/dom/base/CustomElementRegistry.cpp >+++ b/dom/base/CustomElementRegistry.cpp >@@ -31,18 +31,30 @@ CustomElementCallback::Call() > // this now in order to enqueue the attached callback. This is a spec > // bug (w3c bug 27437). > mOwnerData->mCreatedCallbackInvoked = true; > > // If ELEMENT is in a document and this document has a browsing context, > // enqueue attached callback for ELEMENT. > nsIDocument* document = mThisObject->GetComposedDoc(); > if (document && document->GetDocShell()) { >+ NodeInfo *ni = mThisObject->NodeInfo(); Nit, * goes with the type >+ nsString extType = nsDependentAtomString(mOwnerData->mType); nsDependentAtomString extType(mOwnerData->mType); that way you avoid creating temporary heap allocated string. Or does that not compile? >+ >+ // We need to do this because at this point, CustomElementDefinition is >+ // not set to CustomElementData yet, so EnqueueLifecycleCallback will >+ // fail to find the CE definition for this custom element. >+ // This way go away eventually since there is no created callback in v1. s/way/may/ ? >+ CustomElementDefinition *definition = Nit, * with the type
Attachment #8904291 - Flags: review?(bugs) → review+
(In reply to Olli Pettay [:smaug] from comment #10) > Comment on attachment 8904291 [details] [diff] [review] > Part 2: Get CE Defintion from CE Data when possible, v1. > > ># HG changeset patch > ># User Jessica Jong <jjong@mozilla.com> > ># Parent 07c702fd588696cdb0ea534e6800ee28918d97eb > >Bug 1392970 - Part 2: Get CustomElementDefinition from CustomElementData when possible. r=smaug > > > >MozReview-Commit-ID: L6DCtGXBesX > > > >diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp > >--- a/dom/base/CustomElementRegistry.cpp > >+++ b/dom/base/CustomElementRegistry.cpp > >@@ -31,18 +31,30 @@ CustomElementCallback::Call() > > // this now in order to enqueue the attached callback. This is a spec > > // bug (w3c bug 27437). > > mOwnerData->mCreatedCallbackInvoked = true; > > > > // If ELEMENT is in a document and this document has a browsing context, > > // enqueue attached callback for ELEMENT. > > nsIDocument* document = mThisObject->GetComposedDoc(); > > if (document && document->GetDocShell()) { > >+ NodeInfo *ni = mThisObject->NodeInfo(); > Nit, * goes with the type Sorry that you need to keep correcting me about this. :( > > >+ nsString extType = nsDependentAtomString(mOwnerData->mType); > nsDependentAtomString extType(mOwnerData->mType); > that way you avoid creating temporary heap allocated string. > Or does that not compile? Yes, it compiles, will change it in the final patch. > > > >+ > >+ // We need to do this because at this point, CustomElementDefinition is > >+ // not set to CustomElementData yet, so EnqueueLifecycleCallback will > >+ // fail to find the CE definition for this custom element. > >+ // This way go away eventually since there is no created callback in v1. > s/way/may/ ? Actually, I meant to write: "This will go away...", ha. > > >+ CustomElementDefinition *definition = > Nit, * with the type Will do.
Rebased and addressed review comment 10.
Attachment #8904291 - Attachment is obsolete: true
Attachment #8911720 - Flags: review+
Attachment #8911719 - Flags: review+
Pushed by ryanvm@gmail.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/d18275f35b3d Part 1: Make CustomElementDefinition ref-counted and put it in CustomElementData. r=smaug https://hg.mozilla.org/integration/mozilla-inbound/rev/05e1f74416aa Part 2: Get CustomElementDefinition from CustomElementData when possible. r=smaug
Keywords: checkin-needed
Blocks: 1396567
Blocks: 1408828
Blocks: 1410790
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: