зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1556352 - Part 2: Implement formAssociatedCallback; r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D129197
This commit is contained in:
Родитель
3f791b5050
Коммит
da31a82815
|
@ -164,6 +164,12 @@ UniquePtr<CustomElementCallback> CustomElementCallback::Create(
|
|||
}
|
||||
break;
|
||||
|
||||
case ElementCallbackType::eFormAssociated:
|
||||
if (aDefinition->mCallbacks->mFormAssociatedCallback.WasPassed()) {
|
||||
func = aDefinition->mCallbacks->mFormAssociatedCallback.Value();
|
||||
}
|
||||
break;
|
||||
|
||||
case ElementCallbackType::eFormReset:
|
||||
if (aDefinition->mCallbacks->mFormResetCallback.WasPassed()) {
|
||||
func = aDefinition->mCallbacks->mFormResetCallback.Value();
|
||||
|
@ -209,6 +215,10 @@ void CustomElementCallback::Call() {
|
|||
->Call(mThisObject, mArgs.mName, mArgs.mOldValue, mArgs.mNewValue,
|
||||
mArgs.mNamespaceURI);
|
||||
break;
|
||||
case ElementCallbackType::eFormAssociated:
|
||||
static_cast<LifecycleFormAssociatedCallback*>(mCallback.get())
|
||||
->Call(mThisObject, mArgs.mForm);
|
||||
break;
|
||||
case ElementCallbackType::eFormReset:
|
||||
static_cast<LifecycleFormResetCallback*>(mCallback.get())
|
||||
->Call(mThisObject);
|
||||
|
@ -1561,6 +1571,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition)
|
|||
cb.NoteXPCOMChild(callbacks->mAdoptedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mFormAssociatedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mCallbacks->mFormAssociatedCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mFormAssociatedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mFormResetCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mFormResetCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mFormResetCallback.Value());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ElementInternals.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
@ -39,6 +40,7 @@ enum class ElementCallbackType {
|
|||
eDisconnected,
|
||||
eAdopted,
|
||||
eAttributeChanged,
|
||||
eFormAssociated,
|
||||
eFormReset,
|
||||
eFormDisabled,
|
||||
eGetCustomInterface
|
||||
|
@ -55,6 +57,9 @@ struct LifecycleCallbackArgs {
|
|||
RefPtr<Document> mOldDocument;
|
||||
RefPtr<Document> mNewDocument;
|
||||
|
||||
// Used by the form associated callback.
|
||||
RefPtr<HTMLFormElement> mForm;
|
||||
|
||||
// Used by the form disabled callback.
|
||||
bool mDisabled;
|
||||
|
||||
|
|
|
@ -137,6 +137,16 @@ already_AddRefed<ElementInternals> HTMLElement::AttachInternals(
|
|||
return do_AddRef(ceData->GetOrCreateElementInternals(this));
|
||||
}
|
||||
|
||||
void HTMLElement::AfterClearForm(bool aUnbindOrDelete) {
|
||||
// No need to enqueue formAssociated callback if we aren't releasing or
|
||||
// unbinding from tree, UpdateFormOwner() will handle it.
|
||||
if (aUnbindOrDelete) {
|
||||
MOZ_ASSERT(IsFormAssociatedElement());
|
||||
nsContentUtils::EnqueueLifecycleCallback(
|
||||
ElementCallbackType::eFormAssociated, this, {});
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLElement::UpdateFormOwner() {
|
||||
MOZ_ASSERT(IsFormAssociatedElement());
|
||||
|
||||
|
@ -147,7 +157,7 @@ void HTMLElement::UpdateFormOwner() {
|
|||
// call UpdateFormOwner if none of these conditions are fulfilled.
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ? IsInComposedDoc()
|
||||
: !!GetParent()) {
|
||||
nsGenericHTMLFormElement::UpdateFormOwner(true, nullptr);
|
||||
UpdateFormOwner(true, nullptr);
|
||||
}
|
||||
UpdateFieldSet(true);
|
||||
UpdateDisabledState(true);
|
||||
|
@ -208,6 +218,18 @@ void HTMLElement::UpdateDisabledState(bool aNotify) {
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLElement::UpdateFormOwner(bool aBindToTree, Element* aFormIdElement) {
|
||||
HTMLFormElement* oldForm = GetFormInternal();
|
||||
nsGenericHTMLFormElement::UpdateFormOwner(aBindToTree, aFormIdElement);
|
||||
HTMLFormElement* newForm = GetFormInternal();
|
||||
if (newForm != oldForm) {
|
||||
LifecycleCallbackArgs args;
|
||||
args.mForm = newForm;
|
||||
nsContentUtils::EnqueueLifecycleCallback(
|
||||
ElementCallbackType::eFormAssociated, this, args);
|
||||
}
|
||||
}
|
||||
|
||||
bool HTMLElement::IsFormAssociatedElement() const {
|
||||
CustomElementData* data = GetCustomElementData();
|
||||
bool isFormAssociatedCustomElement = data && data->IsFormAssociated();
|
||||
|
|
|
@ -35,6 +35,7 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
|
||||
// nsGenericHTMLFormElement
|
||||
bool IsFormAssociatedElement() const override;
|
||||
void AfterClearForm(bool aUnbindOrDelete) override;
|
||||
|
||||
void UpdateFormOwner();
|
||||
|
||||
|
@ -58,6 +59,7 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
bool CanBeDisabled() const override;
|
||||
bool DoesReadOnlyApply() const override;
|
||||
void UpdateDisabledState(bool aNotify) override;
|
||||
void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement) override;
|
||||
|
||||
ElementInternals* GetElementInternals() const;
|
||||
};
|
||||
|
|
|
@ -1040,7 +1040,7 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
|||
* @note Callers of UpdateFormOwner have to be sure the element is in a
|
||||
* document (GetUncomposedDoc() != nullptr).
|
||||
*/
|
||||
void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement);
|
||||
virtual void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement);
|
||||
|
||||
/**
|
||||
* This method will update mFieldset and set it to the first fieldset parent.
|
||||
|
|
|
@ -38,6 +38,8 @@ callback LifecycleAttributeChangedCallback = void(DOMString attrName,
|
|||
DOMString? newValue,
|
||||
DOMString? namespaceURI);
|
||||
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
|
||||
callback LifecycleFormAssociatedCallback = void(HTMLFormElement? form);
|
||||
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
|
||||
callback LifecycleFormResetCallback = void();
|
||||
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
|
||||
callback LifecycleFormDisabledCallback = void(boolean disabled);
|
||||
|
@ -50,6 +52,7 @@ dictionary LifecycleCallbacks {
|
|||
LifecycleDisconnectedCallback disconnectedCallback;
|
||||
LifecycleAdoptedCallback adoptedCallback;
|
||||
LifecycleAttributeChangedCallback attributeChangedCallback;
|
||||
LifecycleFormAssociatedCallback formAssociatedCallback;
|
||||
LifecycleFormResetCallback formResetCallback;
|
||||
LifecycleFormDisabledCallback formDisabledCallback;
|
||||
[ChromeOnly] LifecycleGetCustomInterfaceCallback getCustomInterfaceCallback;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[form-associated-callback.html]
|
||||
[Associate by parser, customized at element creation]
|
||||
expected: FAIL
|
||||
|
||||
[Parsed, connected, then upgraded]
|
||||
expected: FAIL
|
||||
|
||||
[Disassociation]
|
||||
expected: FAIL
|
|
@ -176,20 +176,34 @@ test(() => {
|
|||
|
||||
test(() => {
|
||||
$('#container').innerHTML = '<form id="form1"></form>' +
|
||||
'<pre-defined id="pd1"></pre-defined><form id="form2"></form>';
|
||||
'<pre-defined id="pd1"></pre-defined><form id="form2">' +
|
||||
'</form><form id="form3"></form>';
|
||||
const pd1 = $('#pd1');
|
||||
const form1 = $('#form1');
|
||||
const form2 = $('#form2');
|
||||
const form3 = $('#form3');
|
||||
assert_equals(pd1.form, null);
|
||||
assert_array_equals(pd1.formHistory(), []);
|
||||
|
||||
pd1.setAttribute('form', 'form1');
|
||||
assert_equals(pd1.form, form1);
|
||||
assert_array_equals(pd1.formHistory(), [form1]);
|
||||
|
||||
pd1.setAttribute('form', 'invalid');
|
||||
assert_equals(pd1.form, null);
|
||||
assert_array_equals(pd1.formHistory(), [form1, null]);
|
||||
|
||||
pd1.setAttribute('form', 'form2');
|
||||
assert_equals(pd1.form, form2);
|
||||
assert_array_equals(pd1.formHistory(), [form1, null, form2]);
|
||||
|
||||
pd1.setAttribute('form', 'form3');
|
||||
assert_equals(pd1.form, form3);
|
||||
assert_array_equals(pd1.formHistory(), [form1, null, form2, form3]);
|
||||
|
||||
$('#container').innerHTML = '';
|
||||
assert_equals(pd1.form, null);
|
||||
assert_array_equals(pd1.formHistory(), [form1, null, form2, form3, null]);
|
||||
}, 'Updating "form" content attribute');
|
||||
</script>
|
||||
</body>
|
||||
|
|
Загрузка…
Ссылка в новой задаче