зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 08f12e7fa5f0 (bug 1556358) for causing bustage on ElementInternals.cpp. CLOSED TREE
This commit is contained in:
Родитель
bc528a1c76
Коммит
ddf6d6b447
|
@ -150,7 +150,6 @@
|
|||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "mozilla/dom/CustomElementRegistryBinding.h"
|
||||
#include "mozilla/dom/CustomElementTypes.h"
|
||||
#include "mozilla/dom/DOMArena.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
@ -169,10 +168,8 @@
|
|||
#include "mozilla/dom/FileBlobImpl.h"
|
||||
#include "mozilla/dom/FileSystemSecurity.h"
|
||||
#include "mozilla/dom/FilteredNodeIterator.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
#include "mozilla/dom/FragmentOrElement.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/dom/HTMLElement.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||
|
@ -9943,97 +9940,6 @@ void nsContentUtils::EnqueueLifecycleCallback(
|
|||
aDefinition);
|
||||
}
|
||||
|
||||
/* static */
|
||||
CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
|
||||
const OwningFileOrUSVStringOrFormData& aState) {
|
||||
if (aState.IsFile()) {
|
||||
RefPtr<BlobImpl> impl = aState.GetAsFile()->Impl();
|
||||
return {std::move(impl)};
|
||||
}
|
||||
if (aState.IsUSVString()) {
|
||||
return aState.GetAsUSVString();
|
||||
}
|
||||
nsTArray<FormDataTuple> array;
|
||||
aState.GetAsFormData()->ForEach(
|
||||
[&array](const nsString& aName,
|
||||
const OwningBlobOrDirectoryOrUSVString& aValue) {
|
||||
FormDataTuple data;
|
||||
data.name() = aName;
|
||||
|
||||
if (aValue.IsBlob()) {
|
||||
FormDataValue value(WrapNotNull(aValue.GetAsBlob()->Impl()));
|
||||
data.value() = std::move(value);
|
||||
} else if (aValue.IsUSVString()) {
|
||||
data.value() = aValue.GetAsUSVString();
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Can't save FormData entry Directory value!");
|
||||
}
|
||||
|
||||
array.AppendElement(data);
|
||||
return true;
|
||||
});
|
||||
return std::move(array);
|
||||
}
|
||||
|
||||
/* static */
|
||||
Nullable<OwningFileOrUSVStringOrFormData>
|
||||
nsContentUtils::ExtractFormAssociatedCustomElementValue(
|
||||
mozilla::dom::HTMLElement* aElement,
|
||||
const mozilla::dom::CustomElementFormValue& aCEValue) {
|
||||
OwningFileOrUSVStringOrFormData value;
|
||||
switch (aCEValue.type()) {
|
||||
case CustomElementFormValue::TBlobImpl: {
|
||||
nsPIDOMWindowInner* window = aElement->OwnerDoc()->GetInnerWindow();
|
||||
if (!window) {
|
||||
return {};
|
||||
}
|
||||
RefPtr<File> file =
|
||||
File::Create(window->AsGlobal(), aCEValue.get_BlobImpl());
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return {};
|
||||
}
|
||||
value.SetAsFile() = file;
|
||||
} break;
|
||||
|
||||
case CustomElementFormValue::TnsString:
|
||||
value.SetAsUSVString() = aCEValue.get_nsString();
|
||||
break;
|
||||
|
||||
case CustomElementFormValue::TArrayOfFormDataTuple: {
|
||||
const auto& array = aCEValue.get_ArrayOfFormDataTuple();
|
||||
auto formData = MakeRefPtr<FormData>();
|
||||
|
||||
for (auto i = 0ul; i < array.Length(); ++i) {
|
||||
const auto& item = array.ElementAt(i);
|
||||
switch (item.value().type()) {
|
||||
case FormDataValue::TnsString:
|
||||
formData->AddNameValuePair(item.name(),
|
||||
item.value().get_nsString());
|
||||
break;
|
||||
|
||||
case FormDataValue::TBlobImpl: {
|
||||
auto blobImpl = item.value().get_BlobImpl();
|
||||
auto* blob = Blob::Create(
|
||||
aElement->GetComposedDoc()->GetOwnerGlobal(), blobImpl);
|
||||
formData->AddNameBlobPair(item.name(), blob);
|
||||
} break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
value.SetAsFormData() = formData;
|
||||
} break;
|
||||
case CustomElementFormValue::Tvoid_t:
|
||||
return {};
|
||||
default:
|
||||
NS_WARNING("Invalid CustomElementContentData type!");
|
||||
return {};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
|
||||
Document* aDocument, nsTArray<nsIContent*>& aElements) {
|
||||
|
|
|
@ -174,7 +174,6 @@ class ContentChild;
|
|||
class ContentFrameMessageManager;
|
||||
class ContentParent;
|
||||
struct CustomElementDefinition;
|
||||
class CustomElementFormValue;
|
||||
class CustomElementRegistry;
|
||||
class DataTransfer;
|
||||
class Document;
|
||||
|
@ -183,7 +182,6 @@ class DOMArena;
|
|||
class Element;
|
||||
class Event;
|
||||
class EventTarget;
|
||||
class HTMLElement;
|
||||
class HTMLInputElement;
|
||||
class IPCTransferable;
|
||||
class IPCTransferableData;
|
||||
|
@ -192,7 +190,6 @@ class IPCTransferableDataItem;
|
|||
struct LifecycleCallbackArgs;
|
||||
class MessageBroadcaster;
|
||||
class NodeInfo;
|
||||
class OwningFileOrUSVStringOrFormData;
|
||||
class Selection;
|
||||
struct StructuredSerializeOptions;
|
||||
class WorkerPrivate;
|
||||
|
@ -3052,14 +3049,6 @@ class nsContentUtils {
|
|||
const mozilla::dom::LifecycleCallbackArgs& aArgs,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
|
||||
|
||||
static mozilla::dom::CustomElementFormValue ConvertToCustomElementFormValue(
|
||||
const mozilla::dom::OwningFileOrUSVStringOrFormData& aState);
|
||||
|
||||
static mozilla::dom::Nullable<mozilla::dom::OwningFileOrUSVStringOrFormData>
|
||||
ExtractFormAssociatedCustomElementValue(
|
||||
mozilla::dom::HTMLElement* aElement,
|
||||
const mozilla::dom::CustomElementFormValue& aCEValue);
|
||||
|
||||
/**
|
||||
* Appends all "document level" native anonymous content subtree roots for
|
||||
* aDocument to aElements. Document level NAC subtrees are those created
|
||||
|
|
|
@ -455,20 +455,14 @@ class nsIContent : public nsINode {
|
|||
*/
|
||||
static inline bool RequiresDoneCreatingElement(int32_t aNamespace,
|
||||
nsAtom* aName) {
|
||||
if (aNamespace == kNameSpaceID_XHTML) {
|
||||
if (aName == nsGkAtoms::input || aName == nsGkAtoms::button ||
|
||||
aName == nsGkAtoms::audio || aName == nsGkAtoms::video) {
|
||||
MOZ_ASSERT(!RequiresDoneAddingChildren(aNamespace, aName),
|
||||
"Both DoneCreatingElement and DoneAddingChildren on a "
|
||||
"same element isn't supported.");
|
||||
return true;
|
||||
}
|
||||
if (aName->IsDynamic()) {
|
||||
// This could be a form-associated custom element, so check if its
|
||||
// name includes a -.
|
||||
nsDependentString name(aName->GetUTF16String());
|
||||
return name.Contains('-');
|
||||
}
|
||||
if (aNamespace == kNameSpaceID_XHTML &&
|
||||
(aName == nsGkAtoms::input || aName == nsGkAtoms::button ||
|
||||
aName == nsGkAtoms::audio || aName == nsGkAtoms::video)) {
|
||||
MOZ_ASSERT(
|
||||
!RequiresDoneAddingChildren(aNamespace, aName),
|
||||
"Both DoneCreatingElement and DoneAddingChildren on a same element "
|
||||
"isn't supported.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ ElementInternals::ElementInternals(HTMLElement* aTarget)
|
|||
: nsIFormControl(FormControlType::FormAssociatedCustomElement),
|
||||
mTarget(aTarget),
|
||||
mForm(nullptr),
|
||||
mFieldSet(nullptr),
|
||||
mControlNumber(-1) {}
|
||||
mFieldSet(nullptr) {}
|
||||
|
||||
nsISupports* ElementInternals::GetParentObject() { return ToSupports(mTarget); }
|
||||
|
||||
|
@ -458,26 +457,4 @@ DocGroup* ElementInternals::GetDocGroup() {
|
|||
return mTarget->OwnerDoc()->GetDocGroup();
|
||||
}
|
||||
|
||||
void ElementInternals::RestoreFormValue(
|
||||
Nullable<OwningFileOrUSVStringOrFormData>&& aValue,
|
||||
Nullable<OwningFileOrUSVStringOrFormData>&& aState) {
|
||||
mSubmissionValue = aValue;
|
||||
mState = aState;
|
||||
|
||||
if (!mState.IsNull()) {
|
||||
nsContentUtils::EnqueueLifecycleCallback(
|
||||
ElementCallbackType::eFormStateRestore, mTarget,
|
||||
{
|
||||
.mState = mState,
|
||||
.mReason = RestoreReason::Restore,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ElementInternals::InitializeControlNumber() {
|
||||
MOZ_ASSERT(mControlNumber == -1,
|
||||
"FACE control number should only be initialized once!");
|
||||
mControlNumber = mTarget->OwnerDoc()->GetNextControlNumber();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -82,33 +82,11 @@ class ElementInternals final : public nsIFormControl,
|
|||
NS_IMETHOD Reset() override;
|
||||
NS_IMETHOD SubmitNamesValues(mozilla::dom::FormData* aFormData) override;
|
||||
bool AllowDrop() override { return true; }
|
||||
int32_t GetParserInsertedControlNumberForStateKey() const override {
|
||||
return mControlNumber;
|
||||
}
|
||||
|
||||
void SetFieldSet(mozilla::dom::HTMLFieldSetElement* aFieldSet) {
|
||||
mFieldSet = aFieldSet;
|
||||
}
|
||||
|
||||
const Nullable<OwningFileOrUSVStringOrFormData>& GetFormSubmissionValue()
|
||||
const {
|
||||
return mSubmissionValue;
|
||||
}
|
||||
|
||||
const Nullable<OwningFileOrUSVStringOrFormData>& GetFormState() const {
|
||||
return mState;
|
||||
}
|
||||
|
||||
void RestoreFormValue(Nullable<OwningFileOrUSVStringOrFormData>&& aValue,
|
||||
Nullable<OwningFileOrUSVStringOrFormData>&& aState);
|
||||
|
||||
const nsCString& GetStateKey() const { return mStateKey; }
|
||||
void SetStateKey(nsCString&& key) {
|
||||
MOZ_ASSERT(mStateKey.IsEmpty(), "FACE state key should only be set once!");
|
||||
mStateKey = key;
|
||||
}
|
||||
void InitializeControlNumber();
|
||||
|
||||
void UpdateFormOwner();
|
||||
void UpdateBarredFromConstraintValidation();
|
||||
|
||||
|
@ -188,8 +166,8 @@ class ElementInternals final : public nsIFormControl,
|
|||
Nullable<OwningFileOrUSVStringOrFormData> mSubmissionValue;
|
||||
|
||||
// https://html.spec.whatwg.org/#face-state
|
||||
// TODO: Bug 1734841 - Figure out how to support autocomplete for
|
||||
// form-associated custom element.
|
||||
// TODO: Bug 1734841 - Figure out how to support form restoration or
|
||||
// autocomplete for form-associated custom element
|
||||
Nullable<OwningFileOrUSVStringOrFormData> mState;
|
||||
|
||||
// https://html.spec.whatwg.org/#face-validation-message
|
||||
|
@ -199,15 +177,6 @@ class ElementInternals final : public nsIFormControl,
|
|||
RefPtr<nsGenericHTMLElement> mValidationAnchor;
|
||||
|
||||
AttrArray mAttrs;
|
||||
|
||||
// Used to store the key to a form-associated custom element in the current
|
||||
// session. Is empty until element has been upgraded.
|
||||
nsCString mStateKey;
|
||||
|
||||
// A number for a form-associated custom element that is unique within its
|
||||
// owner document. This is only set to a number for elements inserted into the
|
||||
// document by the parser from the network. Otherwise, it is -1.
|
||||
int32_t mControlNumber;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -6,27 +6,18 @@
|
|||
|
||||
#include "mozilla/dom/HTMLElement.h"
|
||||
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/PresState.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "mozilla/dom/ElementInternalsBinding.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
#include "mozilla/dom/HTMLElementBinding.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
HTMLElement::HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
FromParser aFromParser)
|
||||
HTMLElement::HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: nsGenericHTMLFormElement(std::move(aNodeInfo)) {
|
||||
if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
|
||||
AddStatesSilently(ElementState::HAS_DIR_ATTR_LIKE_AUTO);
|
||||
}
|
||||
if (aFromParser & FROM_PARSER_NETWORK) {
|
||||
SetFlags(HTML_ELEMENT_FROM_PARSER_NETWORK);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLElement, nsGenericHTMLFormElement)
|
||||
|
@ -82,91 +73,6 @@ void HTMLElement::UnbindFromTree(bool aNullParent) {
|
|||
UpdateBarredFromConstraintValidation();
|
||||
}
|
||||
|
||||
void HTMLElement::DoneCreatingElement() {
|
||||
if (MOZ_UNLIKELY(IsFormAssociatedElement())) {
|
||||
MaybeRestoreFormAssociatedCustomElementState();
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLElement::SaveState() {
|
||||
if (MOZ_LIKELY(!IsFormAssociatedElement())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* internals = GetElementInternals();
|
||||
|
||||
nsCString stateKey = internals->GetStateKey();
|
||||
if (stateKey.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistory(false);
|
||||
if (!history) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the pres state for this key, if it doesn't exist, create one.
|
||||
PresState* result = history->GetState(stateKey);
|
||||
if (!result) {
|
||||
UniquePtr<PresState> newState = NewPresState();
|
||||
result = newState.get();
|
||||
history->AddState(stateKey, std::move(newState));
|
||||
}
|
||||
|
||||
const auto& state = internals->GetFormState();
|
||||
const auto& value = internals->GetFormSubmissionValue();
|
||||
result->contentData() = CustomElementTuple(
|
||||
value.IsNull()
|
||||
? CustomElementFormValue(void_t{})
|
||||
: nsContentUtils::ConvertToCustomElementFormValue(value.Value()),
|
||||
state.IsNull()
|
||||
? CustomElementFormValue(void_t{})
|
||||
: nsContentUtils::ConvertToCustomElementFormValue(state.Value()));
|
||||
}
|
||||
|
||||
void HTMLElement::MaybeRestoreFormAssociatedCustomElementState() {
|
||||
MOZ_ASSERT(IsFormAssociatedElement());
|
||||
|
||||
auto* internals = GetElementInternals();
|
||||
if (internals->GetStateKey().IsEmpty()) {
|
||||
Document* doc = GetUncomposedDoc();
|
||||
nsCString stateKey;
|
||||
nsContentUtils::GenerateStateKey(this, doc, stateKey);
|
||||
internals->SetStateKey(std::move(stateKey));
|
||||
|
||||
RestoreFormAssociatedCustomElementState();
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLElement::RestoreFormAssociatedCustomElementState() {
|
||||
MOZ_ASSERT(IsFormAssociatedElement());
|
||||
|
||||
auto* internals = GetElementInternals();
|
||||
|
||||
const nsCString& stateKey = internals->GetStateKey();
|
||||
if (stateKey.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistory(true);
|
||||
if (!history) {
|
||||
return;
|
||||
}
|
||||
PresState* result = history->GetState(stateKey);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
auto& content = result->contentData();
|
||||
if (content.type() != PresContentData::TCustomElementTuple) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& ce = content.get_CustomElementTuple();
|
||||
internals->RestoreFormValue(
|
||||
nsContentUtils::ExtractFormAssociatedCustomElementValue(this, ce.value()),
|
||||
nsContentUtils::ExtractFormAssociatedCustomElementValue(this,
|
||||
ce.state()));
|
||||
}
|
||||
|
||||
void HTMLElement::SetCustomElementDefinition(
|
||||
CustomElementDefinition* aDefinition) {
|
||||
nsGenericHTMLFormElement::SetCustomElementDefinition(aDefinition);
|
||||
|
@ -178,15 +84,13 @@ void HTMLElement::SetCustomElementDefinition(
|
|||
aDefinition->mFormAssociated) {
|
||||
CustomElementData* data = GetCustomElementData();
|
||||
MOZ_ASSERT(data);
|
||||
auto* internals = data->GetOrCreateElementInternals(this);
|
||||
data->GetOrCreateElementInternals(this);
|
||||
|
||||
// This is for the case that script constructs a custom element directly,
|
||||
// e.g. via new MyCustomElement(), where the upgrade steps won't be ran to
|
||||
// update the disabled state in UpdateFormOwner().
|
||||
if (data->mState == CustomElementData::State::eCustom) {
|
||||
UpdateDisabledState(true);
|
||||
} else if (HasFlag(HTML_ELEMENT_FROM_PARSER_NETWORK)) {
|
||||
internals->InitializeControlNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,8 +198,6 @@ void HTMLElement::UpdateFormOwner() {
|
|||
UpdateFieldSet(true);
|
||||
UpdateDisabledState(true);
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
MaybeRestoreFormAssociatedCustomElementState();
|
||||
}
|
||||
|
||||
bool HTMLElement::IsDisabledForEvents(WidgetEvent* aEvent) {
|
||||
|
@ -436,7 +338,7 @@ nsGenericHTMLElement* NS_NewHTMLElement(
|
|||
mozilla::dom::FromParser aFromParser) {
|
||||
RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
|
||||
auto* nim = nodeInfo->NodeInfoManager();
|
||||
return new (nim) mozilla::dom::HTMLElement(nodeInfo.forget(), aFromParser);
|
||||
return new (nim) mozilla::dom::HTMLElement(nodeInfo.forget());
|
||||
}
|
||||
|
||||
// Distinct from the above in order to have function pointer that compared
|
||||
|
@ -446,5 +348,5 @@ nsGenericHTMLElement* NS_NewCustomElement(
|
|||
mozilla::dom::FromParser aFromParser) {
|
||||
RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
|
||||
auto* nim = nodeInfo->NodeInfoManager();
|
||||
return new (nim) mozilla::dom::HTMLElement(nodeInfo.forget(), aFromParser);
|
||||
return new (nim) mozilla::dom::HTMLElement(nodeInfo.forget());
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ namespace mozilla::dom {
|
|||
|
||||
class HTMLElement final : public nsGenericHTMLFormElement {
|
||||
public:
|
||||
explicit HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
FromParser aFromParser = NOT_FROM_PARSER);
|
||||
explicit HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -31,7 +30,6 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
// nsIContent
|
||||
nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
||||
void UnbindFromTree(bool aNullParent = true) override;
|
||||
void DoneCreatingElement() override;
|
||||
|
||||
// Element
|
||||
void SetCustomElementDefinition(
|
||||
|
@ -48,12 +46,9 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
bool IsFormAssociatedElement() const override;
|
||||
void AfterClearForm(bool aUnbindOrDelete) override;
|
||||
void FieldSetDisabledChanged(bool aNotify) override;
|
||||
void SaveState() override;
|
||||
|
||||
void UpdateFormOwner();
|
||||
|
||||
void MaybeRestoreFormAssociatedCustomElementState();
|
||||
|
||||
protected:
|
||||
virtual ~HTMLElement() = default;
|
||||
|
||||
|
@ -80,9 +75,6 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
void UpdateBarredFromConstraintValidation();
|
||||
|
||||
ElementInternals* GetElementInternals() const;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void RestoreFormAssociatedCustomElementState();
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -1833,9 +1833,6 @@ nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
|||
}
|
||||
|
||||
void nsGenericHTMLFormElement::UnbindFromTree(bool aNullParent) {
|
||||
// Save state before doing anything else.
|
||||
SaveState();
|
||||
|
||||
if (IsFormAssociatedElement()) {
|
||||
if (HTMLFormElement* form = GetFormInternal()) {
|
||||
// Might need to unset form
|
||||
|
@ -2243,12 +2240,6 @@ void nsGenericHTMLFormElement::FieldSetDisabledChanged(bool aNotify) {
|
|||
UpdateDisabledState(aNotify);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormElement::SaveSubtreeState() {
|
||||
SaveState();
|
||||
|
||||
nsGenericHTMLElement::SaveSubtreeState();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void nsGenericHTMLElement::Click(CallerType aCallerType) {
|
||||
|
@ -2582,6 +2573,12 @@ nsINode* nsGenericHTMLFormControlElement::GetScopeChainParent() const {
|
|||
return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent();
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::SaveSubtreeState() {
|
||||
SaveState();
|
||||
|
||||
nsGenericHTMLFormElement::SaveSubtreeState();
|
||||
}
|
||||
|
||||
nsIContent::IMEState nsGenericHTMLFormControlElement::GetDesiredIMEState() {
|
||||
TextEditor* textEditor = GetTextEditorInternal();
|
||||
if (!textEditor) {
|
||||
|
@ -2595,6 +2592,12 @@ nsIContent::IMEState nsGenericHTMLFormControlElement::GetDesiredIMEState() {
|
|||
return state;
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::UnbindFromTree(bool aNullParent) {
|
||||
// Save state before doing anything
|
||||
SaveState();
|
||||
nsGenericHTMLFormElement::UnbindFromTree(aNullParent);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::GetAutocapitalize(
|
||||
nsAString& aValue) const {
|
||||
if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
|
||||
|
@ -2959,7 +2962,7 @@ PresState* nsGenericHTMLFormControlElementWithState::GetPrimaryPresState() {
|
|||
}
|
||||
|
||||
already_AddRefed<nsILayoutHistoryState>
|
||||
nsGenericHTMLFormElement::GetLayoutHistory(bool aRead) {
|
||||
nsGenericHTMLFormControlElementWithState::GetLayoutHistory(bool aRead) {
|
||||
nsCOMPtr<Document> doc = GetUncomposedDoc();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
|
|
|
@ -980,11 +980,10 @@ class HTMLFieldSetElement;
|
|||
enum {
|
||||
// Used to handle keyboard activation.
|
||||
HTML_ELEMENT_ACTIVE_FOR_KEYBOARD = HTML_ELEMENT_FLAG_BIT(0),
|
||||
HTML_ELEMENT_FROM_PARSER_NETWORK = HTML_ELEMENT_FLAG_BIT(1),
|
||||
|
||||
// Remaining bits are type specific.
|
||||
HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET =
|
||||
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2,
|
||||
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1,
|
||||
};
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
|
||||
|
@ -1028,7 +1027,6 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
|||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
||||
// nsIContent
|
||||
void SaveSubtreeState() override;
|
||||
nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
||||
void UnbindFromTree(bool aNullParent = true) override;
|
||||
|
||||
|
@ -1056,15 +1054,6 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
|||
|
||||
void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete);
|
||||
|
||||
/**
|
||||
* Get the layout history object for a particular piece of content.
|
||||
*
|
||||
* @param aRead if true, won't return a layout history state if the
|
||||
* layout history state is empty.
|
||||
* @return the history state object
|
||||
*/
|
||||
already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead);
|
||||
|
||||
protected:
|
||||
virtual ~nsGenericHTMLFormElement() = default;
|
||||
|
||||
|
@ -1158,13 +1147,6 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
|||
* See https://html.spec.whatwg.org/#form-associated-element.
|
||||
*/
|
||||
virtual bool IsFormAssociatedElement() const { return false; }
|
||||
|
||||
/**
|
||||
* Save to presentation state. The form element will determine whether it
|
||||
* has anything to save and if so, create an entry in the layout history for
|
||||
* its pres context.
|
||||
*/
|
||||
virtual void SaveState() {}
|
||||
};
|
||||
|
||||
class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
|
||||
|
@ -1183,7 +1165,9 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
|
|||
bool IsHTMLFormControlElement() const final { return true; }
|
||||
|
||||
// nsIContent
|
||||
void SaveSubtreeState() override;
|
||||
IMEState GetDesiredIMEState() override;
|
||||
void UnbindFromTree(bool aNullParent = true) override;
|
||||
|
||||
// nsGenericHTMLElement
|
||||
// autocapitalize attribute support
|
||||
|
@ -1227,6 +1211,13 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
|
|||
|
||||
bool IsAutocapitalizeInheriting() const;
|
||||
|
||||
/**
|
||||
* Save to presentation state. The form control will determine whether it
|
||||
* has anything to save and if so, create an entry in the layout history for
|
||||
* its pres context.
|
||||
*/
|
||||
virtual void SaveState() {}
|
||||
|
||||
nsresult SubmitDirnameDir(mozilla::dom::FormData* aFormData);
|
||||
|
||||
/** The form that contains this control */
|
||||
|
@ -1280,6 +1271,15 @@ class nsGenericHTMLFormControlElementWithState
|
|||
*/
|
||||
mozilla::PresState* GetPrimaryPresState();
|
||||
|
||||
/**
|
||||
* Get the layout history object for a particular piece of content.
|
||||
*
|
||||
* @param aRead if true, won't return a layout history state if the
|
||||
* layout history state is empty.
|
||||
* @return the history state object
|
||||
*/
|
||||
already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead);
|
||||
|
||||
/**
|
||||
* Called when we have been cloned and adopted, and the information of the
|
||||
* node has been changed.
|
||||
|
|
|
@ -101,8 +101,6 @@ skip-if = os == "android"
|
|||
[test_radio_radionodelist.html]
|
||||
[test_required_attribute.html]
|
||||
[test_restore_form_elements.html]
|
||||
[test_save_restore_custom_elements.html]
|
||||
support-files = save_restore_custom_elements_sample.html
|
||||
[test_save_restore_radio_groups.html]
|
||||
[test_select_change_event.html]
|
||||
skip-if = os == 'mac'
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<script>
|
||||
class CEBase extends HTMLElement {
|
||||
static formAssociated = true;
|
||||
constructor() {
|
||||
super();
|
||||
this.internals = this.attachInternals();
|
||||
this.state_ = undefined;
|
||||
}
|
||||
formStateRestoreCallback(state, reason) {
|
||||
if (reason == "restore") {
|
||||
this.state_ = state;
|
||||
}
|
||||
}
|
||||
set(state, value) {
|
||||
this.state_ = state;
|
||||
this.value_ = value;
|
||||
this.internals.setFormValue(value, state);
|
||||
}
|
||||
get state() {
|
||||
return this.state_;
|
||||
}
|
||||
get value() {
|
||||
return this.value_;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("c-e", class extends CEBase {});
|
||||
</script>
|
||||
<form>
|
||||
<c-e id="custom0"></c-e>
|
||||
<c-e id="custom1"></c-e>
|
||||
<c-e id="custom2"></c-e>
|
||||
<c-e id="custom3"></c-e>
|
||||
<c-e id="custom4"></c-e>
|
||||
<upgraded-ce id="upgraded0"></upgraded-ce>
|
||||
<upgraded-ce id="upgraded1"></upgraded-ce>
|
||||
<upgraded-ce id="upgraded2"></upgraded-ce>
|
||||
<upgraded-ce id="upgraded3"></upgraded-ce>
|
||||
<upgraded-ce id="upgraded4"></upgraded-ce>
|
||||
</form>
|
||||
<script>
|
||||
customElements.define("upgraded-ce", class extends CEBase {});
|
||||
</script>
|
|
@ -1,90 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1556358
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Test for Bug 1556358</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1556358">Mozilla Bug 1556358</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe src="save_restore_custom_elements_sample.html"></iframe>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1556358 **/
|
||||
|
||||
function formDataWith(...entries) {
|
||||
const formData = new FormData();
|
||||
for (let [key, value] of entries) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
const states = [
|
||||
"test state",
|
||||
new File(["state"], "state.txt"),
|
||||
formDataWith(["1", "state"], ["2", new Blob(["state_blob"])]),
|
||||
null,
|
||||
undefined,
|
||||
];
|
||||
const values = [
|
||||
"test value",
|
||||
new File(["value"], "value.txt"),
|
||||
formDataWith(["1", "value"], ["2", new Blob(["value_blob"])]),
|
||||
"null state",
|
||||
"both value and state",
|
||||
];
|
||||
|
||||
add_task(async () => {
|
||||
const frame = document.querySelector("iframe");
|
||||
const elementTags = ["c-e", "upgraded-ce"];
|
||||
|
||||
// Set the custom element values.
|
||||
for (const tags of elementTags) {
|
||||
[...frame.contentDocument.querySelectorAll(tags)]
|
||||
.forEach((e, i) => {
|
||||
e.set(states[i], values[i]);
|
||||
});
|
||||
}
|
||||
|
||||
await new Promise(resolve => {
|
||||
frame.addEventListener("load", resolve);
|
||||
frame.contentWindow.location.reload();
|
||||
});
|
||||
|
||||
for (const tag of elementTags) {
|
||||
// Retrieve the restored values.
|
||||
const ceStates =
|
||||
[...frame.contentDocument.querySelectorAll(tag)].map((e) => e.state);
|
||||
is(ceStates.length, 5, "Should have 5 custom element states");
|
||||
|
||||
const [restored, original] = [ceStates, states];
|
||||
is(restored[0], original[0], "Value should be restored");
|
||||
|
||||
const file = restored[1];
|
||||
isnot(file, original[1], "Restored file object differs from original object.");
|
||||
is(file.name, original[1].name, "File name should be restored");
|
||||
is(await file.text(), await original[1].text(), "File text should be restored");
|
||||
|
||||
const formData = restored[2];
|
||||
isnot(formData, original[2], "Restored formdata object differs from original object.");
|
||||
is(formData.get("1"), original[2].get("1"), "Form data string should be restored");
|
||||
is(await formData.get("2").text(), await original[2].get("2").text(), "Form data blob should be restored");
|
||||
|
||||
isnot(restored[3], original[3], "Null values don't get restored");
|
||||
is(restored[3], undefined, "Null values don't get restored");
|
||||
|
||||
is(restored[4], "both value and state", "Undefined state should be set to value");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,39 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include "mozilla/dom/IPCBlobUtils.h";
|
||||
|
||||
[RefCounted] using class mozilla::dom::BlobImpl from "mozilla/dom/BlobImpl.h";
|
||||
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Types used to store form-associated custom element state.
|
||||
union FormDataValue {
|
||||
BlobImpl;
|
||||
nsString;
|
||||
};
|
||||
|
||||
struct FormDataTuple {
|
||||
nsString name;
|
||||
FormDataValue value;
|
||||
};
|
||||
|
||||
union CustomElementFormValue {
|
||||
void_t;
|
||||
nullable BlobImpl;
|
||||
nsString;
|
||||
FormDataTuple[];
|
||||
};
|
||||
|
||||
struct CustomElementTuple {
|
||||
CustomElementFormValue value;
|
||||
CustomElementFormValue state;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -167,7 +167,6 @@ PREPROCESSED_IPDL_SOURCES += [
|
|||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
"CustomElementTypes.ipdlh",
|
||||
"DOMTypes.ipdlh",
|
||||
"IPCTransferable.ipdlh",
|
||||
"MemoryReportTypes.ipdlh",
|
||||
|
|
|
@ -11,8 +11,6 @@ using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
|||
using struct nsPoint from "nsPoint.h";
|
||||
[RefCounted] using class mozilla::dom::BlobImpl from "mozilla/dom/BlobImpl.h";
|
||||
|
||||
include CustomElementTypes;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct SelectContentData {
|
||||
|
@ -42,7 +40,6 @@ union PresContentData {
|
|||
// We can need to serialize blobs in order to transmit this type, so we need
|
||||
// to handle that in a custom handler.
|
||||
FileContentData[];
|
||||
CustomElementTuple;
|
||||
};
|
||||
|
||||
struct PresState {
|
||||
|
|
Загрузка…
Ссылка в новой задаче