Bug 1552313 - Implement element.attachInternals; r=smaug,edgar

ElementInternals class is empty-for-now.

Differential Revision: https://phabricator.services.mozilla.com/D52158

--HG--
extra : moz-landing-system : lando
This commit is contained in:
John Dai 2019-11-12 11:27:55 +00:00
parent 790ed5a490
commit de2c2a249a
18 changed files with 329 additions and 44 deletions

View File

@ -174,6 +174,12 @@ void CustomElementData::SetCustomElementDefinition(
mCustomElementDefinition = aDefinition;
}
void CustomElementData::AttachedInternals() {
MOZ_ASSERT(!mIsAttachedInternals);
mIsAttachedInternals = true;
}
CustomElementDefinition* CustomElementData::GetCustomElementDefinition() {
MOZ_ASSERT(mCustomElementDefinition ? mState == State::eCustom
: mState != State::eCustom);

View File

@ -105,6 +105,8 @@ struct CustomElementData {
void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
CustomElementDefinition* GetCustomElementDefinition();
nsAtom* GetCustomElementType() const { return mType; }
void AttachedInternals();
bool HasAttachedInternals() const { return mIsAttachedInternals; }
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
void Unlink();
@ -123,6 +125,7 @@ struct CustomElementData {
// this would be x-button.
RefPtr<nsAtom> mType;
RefPtr<CustomElementDefinition> mCustomElementDefinition;
bool mIsAttachedInternals = false;
};
#define ALREADY_CONSTRUCTED_MARKER nullptr

View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/ElementInternals.h"
#include "mozilla/dom/ElementInternalsBinding.h"
#include "nsGenericHTMLElement.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ElementInternals, mTarget)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ElementInternals)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ElementInternals)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ElementInternals)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ElementInternals::ElementInternals(nsGenericHTMLElement* aTarget)
: mTarget(aTarget) {}
nsISupports* ElementInternals::GetParentObject() { return ToSupports(mTarget); }
JSObject* ElementInternals::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return ElementInternals_Binding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,40 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef mozilla_dom_ElementInternals_h
#define mozilla_dom_ElementInternals_h
#include "js/TypeDecls.h"
#include "nsCycleCollectionParticipant.h"
#include "nsGenericHTMLElement.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class ElementInternals final : public nsISupports, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ElementInternals)
explicit ElementInternals(nsGenericHTMLElement* aTarget);
nsISupports* GetParentObject();
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
private:
~ElementInternals() = default;
// It's a target element which is a custom element.
RefPtr<nsGenericHTMLElement> mTarget;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ElementInternals_h

View File

@ -49,6 +49,7 @@ EXPORTS.mozilla += [
]
EXPORTS.mozilla.dom += [
'ElementInternals.h',
'HTMLAllCollection.h',
'HTMLAnchorElement.h',
'HTMLAreaElement.h',
@ -129,6 +130,7 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'ElementInternals.cpp',
'HTMLAllCollection.cpp',
'HTMLAnchorElement.cpp',
'HTMLAreaElement.cpp',

View File

@ -102,6 +102,8 @@
#include "nsComputedDOMStyle.h"
#include "mozilla/dom/HTMLLabelElement.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/ElementInternals.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -2796,3 +2798,77 @@ void nsGenericHTMLElement::SetInnerText(const nsAString& aValue) {
mb.NodesAdded();
}
// https://html.spec.whatwg.org/commit-snapshots/b48bb2238269d90ea4f455a52cdf29505aff3df0/#dom-attachinternals
already_AddRefed<ElementInternals> nsGenericHTMLElement::AttachInternals(
ErrorResult& aRv) {
CustomElementData* ceData = GetCustomElementData();
// 1. If element's is value is not null, then throw a "NotSupportedError"
// DOMException.
nsAtom* isAtom = ceData ? ceData->GetIs(this) : nullptr;
nsAtom* nameAtom = NodeInfo()->NameAtom();
if (isAtom) {
aRv.ThrowDOMException(
NS_ERROR_DOM_NOT_SUPPORTED_ERR,
nsPrintfCString(
"Cannot attach ElementInternals to a customized built-in element "
"'%s'",
NS_ConvertUTF16toUTF8(isAtom->GetUTF16String()).get()));
return nullptr;
}
// 2. Let definition be the result of looking up a custom element definition
// given element's node document, its namespace, its local name, and null
// as is value.
CustomElementDefinition* definition = nullptr;
if (ceData) {
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,
NodeInfo()->NamespaceID(), ceData->GetCustomElementType());
}
}
// 3. If definition is null, then throw an "NotSupportedError" DOMException.
if (!definition) {
aRv.ThrowDOMException(
NS_ERROR_DOM_NOT_SUPPORTED_ERR,
nsPrintfCString(
"Cannot attach ElementInternals to a non-custom element '%s'",
NS_ConvertUTF16toUTF8(nameAtom->GetUTF16String()).get()));
return nullptr;
}
// 4. If definition's disable internals is true, then throw a
// "NotSupportedError" DOMException.
if (definition->mDisableInternals) {
aRv.ThrowDOMException(
NS_ERROR_DOM_NOT_SUPPORTED_ERR,
nsPrintfCString(
"AttachInternal() to '%s' is disabled by disabledFeatures",
NS_ConvertUTF16toUTF8(nameAtom->GetUTF16String()).get()));
return nullptr;
}
// 5. If element's attached internals is true, then throw an
// "NotSupportedError" DOMException.
if (ceData->HasAttachedInternals()) {
aRv.ThrowDOMException(
NS_ERROR_DOM_NOT_SUPPORTED_ERR,
nsPrintfCString(
"AttachInternals() has already been called from '%s'",
NS_ConvertUTF16toUTF8(nameAtom->GetUTF16String()).get()));
return nullptr;
}
// 6. Set element's attached internals to true.
ceData->AttachedInternals();
// 7. Create a new ElementInternals instance targeting element, and return it.
return MakeAndAddRef<ElementInternals>(this);
}

View File

@ -15,9 +15,9 @@
#include "nsContentCreatorFunctions.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/ValidityState.h"
#include "mozilla/dom/Element.h"
class nsDOMTokenList;
class nsIFormControlFrame;
@ -35,6 +35,7 @@ class EventStates;
class TextEditor;
class PresState;
namespace dom {
class ElementInternals;
class HTMLFormElement;
class HTMLMenuElement;
} // namespace dom
@ -226,6 +227,10 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
return IsNodeInternal(aFirst, aArgs...);
}
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals
already_AddRefed<mozilla::dom::ElementInternals> AttachInternals(
ErrorResult& aRv);
protected:
virtual ~nsGenericHTMLElement() {}

View File

@ -350,6 +350,8 @@ var interfaceNamesInGlobalScope = [
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Element", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "ElementInternals", insecureContext: true, nightly: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "ErrorEvent", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Event", insecureContext: true },

View File

@ -0,0 +1,13 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* https://html.spec.whatwg.org/#elementinternals
*/
[Pref="dom.webcomponents.elementInternals.enabled", Exposed=Window]
interface ElementInternals {
};

View File

@ -58,6 +58,10 @@ interface HTMLElement : Element {
//readonly attribute boolean? commandHidden;
//readonly attribute boolean? commandDisabled;
//readonly attribute boolean? commandChecked;
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals
[Pref="dom.webcomponents.elementInternals.enabled", Throws]
ElementInternals attachInternals();
};
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface

View File

@ -484,6 +484,7 @@ WEBIDL_FILES = [
'DragEvent.webidl',
'DynamicsCompressorNode.webidl',
'Element.webidl',
'ElementInternals.webidl',
'Event.webidl',
'EventHandler.webidl',
'EventListener.webidl',

View File

@ -1,13 +0,0 @@
[HTMLElement-attachInternals.html]
[Successful attachInternals() and the second call.]
expected: FAIL
[attachInternals() throws a NotSupportedError if it is called for a customized built-in element]
expected: FAIL
[If a custom element definition for the local name of the element has disable internals flag, throw a NotSupportedError]
expected: FAIL
[If a custom element definition for the local name of the element doesn't exist, throw an NotSupportedError]
expected: FAIL

View File

@ -1,4 +1,136 @@
[ElementInternals-accessibility.html]
[ElementInternals-accessibility]
[role is defined in ElementInternals]
expected: FAIL
[ariaActiveDescendant is defined in ElementInternals]
expected: FAIL
[ariaAtomic is defined in ElementInternals]
expected: FAIL
[ariaAutoComplete is defined in ElementInternals]
expected: FAIL
[ariaBusy is defined in ElementInternals]
expected: FAIL
[ariaChecked is defined in ElementInternals]
expected: FAIL
[ariaColCount is defined in ElementInternals]
expected: FAIL
[ariaColIndex is defined in ElementInternals]
expected: FAIL
[ariaColSpan is defined in ElementInternals]
expected: FAIL
[ariaControls is defined in ElementInternals]
expected: FAIL
[ariaCurrent is defined in ElementInternals]
expected: FAIL
[ariaDescribedBy is defined in ElementInternals]
expected: FAIL
[ariaDetails is defined in ElementInternals]
expected: FAIL
[ariaDisabled is defined in ElementInternals]
expected: FAIL
[ariaErrorMessage is defined in ElementInternals]
expected: FAIL
[ariaExpanded is defined in ElementInternals]
expected: FAIL
[ariaFlowTo is defined in ElementInternals]
expected: FAIL
[ariaHasPopup is defined in ElementInternals]
expected: FAIL
[ariaHidden is defined in ElementInternals]
expected: FAIL
[ariaKeyShortcuts is defined in ElementInternals]
expected: FAIL
[ariaLabel is defined in ElementInternals]
expected: FAIL
[ariaLabelledBy is defined in ElementInternals]
expected: FAIL
[ariaLevel is defined in ElementInternals]
expected: FAIL
[ariaLive is defined in ElementInternals]
expected: FAIL
[ariaModal is defined in ElementInternals]
expected: FAIL
[ariaMultiLine is defined in ElementInternals]
expected: FAIL
[ariaMultiSelectable is defined in ElementInternals]
expected: FAIL
[ariaOrientation is defined in ElementInternals]
expected: FAIL
[ariaOwns is defined in ElementInternals]
expected: FAIL
[ariaPlaceholder is defined in ElementInternals]
expected: FAIL
[ariaPosInSet is defined in ElementInternals]
expected: FAIL
[ariaPressed is defined in ElementInternals]
expected: FAIL
[ariaReadOnly is defined in ElementInternals]
expected: FAIL
[ariaRelevant is defined in ElementInternals]
expected: FAIL
[ariaRequired is defined in ElementInternals]
expected: FAIL
[ariaRoleDescription is defined in ElementInternals]
expected: FAIL
[ariaRowCount is defined in ElementInternals]
expected: FAIL
[ariaRowIndex is defined in ElementInternals]
expected: FAIL
[ariaRowSpan is defined in ElementInternals]
expected: FAIL
[ariaSelected is defined in ElementInternals]
expected: FAIL
[ariaSort is defined in ElementInternals]
expected: FAIL
[ariaValueMax is defined in ElementInternals]
expected: FAIL
[ariaValueMin is defined in ElementInternals]
expected: FAIL
[ariaValueNow is defined in ElementInternals]
expected: FAIL
[ariaValueText is defined in ElementInternals]
expected: FAIL

View File

@ -1,5 +1,4 @@
[ElementInternals-labels.html]
expected: ERROR
[LABEL click]
expected: FAIL

View File

@ -1,5 +1,4 @@
[ElementInternals-setFormValue.html]
expected: ERROR
[Single value - Non-empty name exists]
expected: FAIL

View File

@ -1,5 +1,4 @@
[ElementInternals-validation.html]
expected: ERROR
[validity and setValidity()]
expected: FAIL

View File

@ -1,4 +1,12 @@
[form-associated-callback.html]
[formAssociatedCallback, and form IDL attribute of ElementInternals]
[Associate by parser, customized at element creation]
expected: FAIL
[Parsed, connected, then upgraded]
expected: FAIL
[Disassociation]
expected: FAIL
[Updating "form" content attribute]
expected: FAIL

View File

@ -1,4 +1,4 @@
prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true]
prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true, dom.webcomponents.elementInternals.enabled:true]
[idlharness.https.html?exclude=(Document|Window|HTML.*)]
[ElementInternals interface: operation setValidity(ValidityStateFlags, DOMString, HTMLElement)]
expected: FAIL
@ -27,9 +27,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[OffscreenCanvasRenderingContext2D interface: operation measureText(DOMString)]
expected: FAIL
[ElementInternals interface: existence and properties of interface object]
expected: FAIL
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "imageSmoothingQuality" with the proper type]
expected: FAIL
@ -114,9 +111,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[OffscreenCanvasRenderingContext2D interface: operation beginPath()]
expected: FAIL
[ElementInternals interface object length]
expected: FAIL
[OffscreenCanvasRenderingContext2D interface: operation bezierCurveTo(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
expected: FAIL
@ -387,9 +381,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[OffscreenCanvasRenderingContext2D interface object name]
expected: FAIL
[ElementInternals interface object name]
expected: FAIL
[ElementInternals interface: attribute labels]
expected: FAIL
@ -417,9 +408,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[ApplicationCache interface: attribute oncached]
expected: FAIL
[ElementInternals interface: existence and properties of interface prototype object]
expected: FAIL
[OffscreenCanvasRenderingContext2D interface: operation commit()]
expected: FAIL
@ -483,15 +471,9 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[OffscreenCanvasRenderingContext2D interface: operation putImageData(ImageData, long, long, long, long, long, long)]
expected: FAIL
[ElementInternals interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[AudioTrack interface object name]
expected: FAIL
[ElementInternals interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[AudioTrack interface: attribute kind]
expected: FAIL
@ -861,9 +843,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[HTMLInputElement interface: attribute dirName]
expected: FAIL
[HTMLElement interface: operation attachInternals()]
expected: FAIL
[HTMLVideoElement interface: attribute playsInline]
expected: FAIL
@ -1026,9 +1005,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.head
[HTMLElement interface: document.createElement("noscript") must inherit property "enterKeyHint" with the proper type]
expected: FAIL
[HTMLElement interface: document.createElement("noscript") must inherit property "attachInternals()" with the proper type]
expected: FAIL
[HTMLFormElement interface: document.createElement("form") must inherit property "requestSubmit(HTMLElement)" with the proper type]
expected: FAIL