Bug 1757923 - Make ElementInternals keeping the target element alive; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D140310
This commit is contained in:
Edgar Chen 2022-03-11 13:29:02 +00:00
Родитель cab117c6f9
Коммит 95e0e6704c
4 изменённых файлов: 70 добавлений и 16 удалений

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<script>
class CustomElement extends HTMLElement {
constructor () {
super();
}
}
let element = document.createElement("custom-element");
customElements.define("custom-element", CustomElement);
customElements.upgrade(element);
const internals = element.attachInternals();
element = undefined;
SpecialPowers.forceGC();
SpecialPowers.forceCC();
internals.shadowRoot;
</script>
</head>
</html>

Просмотреть файл

@ -265,3 +265,4 @@ skip-if(winWidget||Android) pref(print.always_print_silent,true) pref(print.prin
skip-if(ThreadSanitizer||Android) load 1697525.html
skip-if(ThreadSanitizer||Android) load 1712198.html # Mysterious failure that should be investigated (bug 1712866).
skip-if(Android) HTTP load 1728670-1.html
load 1757923.html

Просмотреть файл

@ -19,8 +19,22 @@
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ElementInternals, mSubmissionValue,
mState, mValidity, mValidationAnchor)
NS_IMPL_CYCLE_COLLECTION_CLASS(ElementInternals)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ElementInternals)
tmp->Unlink();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTarget, mSubmissionValue, mState, mValidity,
mValidationAnchor);
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ElementInternals)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTarget, mSubmissionValue, mState,
mValidity, mValidationAnchor);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(ElementInternals)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ElementInternals)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ElementInternals)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ElementInternals)
@ -59,12 +73,14 @@ void ElementInternals::SetFormValue(
const Nullable<FileOrUSVStringOrFormData>& aValue,
const Optional<Nullable<FileOrUSVStringOrFormData>>& aState,
ErrorResult& aRv) {
MOZ_ASSERT(mTarget);
/**
* 1. Let element be this's target element.
* 2. If element is not a form-associated custom element, then throw a
* "NotSupportedError" DOMException.
*/
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return;
@ -118,7 +134,9 @@ void ElementInternals::SetFormValue(
// https://html.spec.whatwg.org/#dom-elementinternals-form
HTMLFormElement* ElementInternals::GetForm(ErrorResult& aRv) const {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return nullptr;
@ -130,12 +148,14 @@ HTMLFormElement* ElementInternals::GetForm(ErrorResult& aRv) const {
void ElementInternals::SetValidity(
const ValidityStateFlags& aFlags, const Optional<nsAString>& aMessage,
const Optional<NonNull<nsGenericHTMLElement>>& aAnchor, ErrorResult& aRv) {
MOZ_ASSERT(mTarget);
/**
* 1. Let element be this's target element.
* 2. If element is not a form-associated custom element, then throw a
* "NotSupportedError" DOMException.
*/
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return;
@ -204,7 +224,9 @@ void ElementInternals::SetValidity(
// https://html.spec.whatwg.org/#dom-elementinternals-willvalidate
bool ElementInternals::GetWillValidate(ErrorResult& aRv) const {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return false;
@ -214,7 +236,9 @@ bool ElementInternals::GetWillValidate(ErrorResult& aRv) const {
// https://html.spec.whatwg.org/#dom-elementinternals-validity
ValidityState* ElementInternals::GetValidity(ErrorResult& aRv) {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return nullptr;
@ -225,7 +249,9 @@ ValidityState* ElementInternals::GetValidity(ErrorResult& aRv) {
// https://html.spec.whatwg.org/#dom-elementinternals-validationmessage
void ElementInternals::GetValidationMessage(nsAString& aValidationMessage,
ErrorResult& aRv) const {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return;
@ -235,7 +261,9 @@ void ElementInternals::GetValidationMessage(nsAString& aValidationMessage,
// https://html.spec.whatwg.org/#dom-elementinternals-checkvalidity
bool ElementInternals::CheckValidity(ErrorResult& aRv) {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return false;
@ -245,7 +273,9 @@ bool ElementInternals::CheckValidity(ErrorResult& aRv) {
// https://html.spec.whatwg.org/#dom-elementinternals-reportvalidity
bool ElementInternals::ReportValidity(ErrorResult& aRv) {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return false;
@ -289,7 +319,9 @@ bool ElementInternals::ReportValidity(ErrorResult& aRv) {
// https://html.spec.whatwg.org/#dom-elementinternals-labels
already_AddRefed<nsINodeList> ElementInternals::GetLabels(
ErrorResult& aRv) const {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return nullptr;
@ -299,7 +331,9 @@ already_AddRefed<nsINodeList> ElementInternals::GetLabels(
nsGenericHTMLElement* ElementInternals::GetValidationAnchor(
ErrorResult& aRv) const {
if (!mTarget || !mTarget->IsFormAssociatedElement()) {
MOZ_ASSERT(mTarget);
if (!mTarget->IsFormAssociatedElement()) {
aRv.ThrowNotSupportedError(
"Target element is not a form-associated custom element");
return nullptr;
@ -379,7 +413,6 @@ void ElementInternals::Unlink() {
if (mFieldSet) {
mFieldSet->RemoveElement(mTarget);
}
mTarget = nullptr;
}
} // namespace mozilla::dom

Просмотреть файл

@ -87,9 +87,7 @@ class ElementInternals final : public nsIFormControl,
~ElementInternals() = default;
// It's a target element which is a custom element.
// It's safe to use raw pointer because it will be reset via
// CustomElementData::Unlink when mTarget is released or unlinked.
HTMLElement* mTarget;
RefPtr<HTMLElement> mTarget;
// The form that contains the target element.
// It's safe to use raw pointer because it will be reset via