summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
authorathenian200 <athenian200@outlook.com>2020-01-27 22:59:08 -0600
committerathenian200 <athenian200@outlook.com>2020-01-27 22:59:08 -0600
commit3c4f414db74b84f7d2a6fb13fd888a47a153699b (patch)
treeea81fca559849967a79d598a6f460830762ec9ea /dom
parent1f8d508258ac5d7d57fc4eb35cac90f28bc8ca03 (diff)
parentc4b0715baaffc541670fd1158557aa7e61e521d3 (diff)
downloadUXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar
UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.gz
UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.lz
UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.xz
UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.zip
Merge branch 'master' of https://github.com/MoonchildProductions/UXP into form-disabled-issue
Diffstat (limited to 'dom')
-rw-r--r--dom/base/CustomElementRegistry.cpp996
-rw-r--r--dom/base/CustomElementRegistry.h425
-rw-r--r--dom/base/DocGroup.cpp3
-rw-r--r--dom/base/DocGroup.h10
-rw-r--r--dom/base/Element.cpp162
-rw-r--r--dom/base/Element.h41
-rw-r--r--dom/base/FragmentOrElement.cpp165
-rw-r--r--dom/base/FragmentOrElement.h132
-rw-r--r--dom/base/ShadowRoot.cpp4
-rw-r--r--dom/base/crashtests/1341693.html13
-rw-r--r--dom/base/crashtests/crashtests.list1
-rw-r--r--dom/base/nsContentCreatorFunctions.h4
-rw-r--r--dom/base/nsContentUtils.cpp172
-rw-r--r--dom/base/nsContentUtils.h60
-rw-r--r--dom/base/nsDOMMutationObserver.cpp67
-rw-r--r--dom/base/nsDOMMutationObserver.h23
-rw-r--r--dom/base/nsDeprecatedOperationList.h1
-rw-r--r--dom/base/nsDocument.cpp179
-rw-r--r--dom/base/nsDocument.h14
-rw-r--r--dom/base/nsGenericDOMDataNode.cpp11
-rw-r--r--dom/base/nsGenericDOMDataNode.h3
-rw-r--r--dom/base/nsGlobalWindow.cpp322
-rw-r--r--dom/base/nsGlobalWindow.h61
-rw-r--r--dom/base/nsIContent.h17
-rw-r--r--dom/base/nsIDocument.h50
-rw-r--r--dom/base/nsJSUtils.cpp11
-rw-r--r--dom/base/nsNodeUtils.cpp64
-rw-r--r--dom/base/nsPIDOMWindow.h10
-rw-r--r--dom/base/nsSandboxFlags.h3
-rw-r--r--dom/base/test/chrome/registerElement_ep.js4
-rw-r--r--dom/base/test/chrome/test_registerElement_content.xul23
-rw-r--r--dom/base/test/chrome/test_registerElement_ep.xul4
-rw-r--r--dom/base/test/mochitest.ini4
-rw-r--r--dom/base/test/mutationobserver_dialog.html62
-rw-r--r--dom/base/test/test_dialogArguments.html31
-rw-r--r--dom/base/test/test_mutationobservers.html55
-rw-r--r--dom/bindings/BindingUtils.cpp212
-rw-r--r--dom/bindings/BindingUtils.h15
-rw-r--r--dom/bindings/Bindings.conf9
-rw-r--r--dom/bindings/CallbackObject.cpp11
-rw-r--r--dom/bindings/Codegen.py154
-rw-r--r--dom/bindings/parser/WebIDL.py47
-rw-r--r--dom/bindings/parser/tests/test_cereactions.py162
-rw-r--r--dom/bindings/parser/tests/test_constructor.py166
-rw-r--r--dom/bindings/parser/tests/test_constructor_no_interface_object.py33
-rw-r--r--dom/bindings/test/TestBindingHeader.h30
-rw-r--r--dom/bindings/test/TestCodeGen.webidl17
-rw-r--r--dom/bindings/test/TestExampleGen.webidl4
-rw-r--r--dom/bindings/test/TestJSImplGen.webidl4
-rw-r--r--dom/bindings/test/test_bug560072.html5
-rw-r--r--dom/canvas/WebGLContextValidate.cpp7
-rw-r--r--dom/events/EventListenerManager.cpp10
-rw-r--r--dom/flyweb/FlyWebDiscoveryManager.cpp1
-rw-r--r--dom/html/HTMLDetailsElement.cpp30
-rw-r--r--dom/html/HTMLDetailsElement.h2
-rw-r--r--dom/html/HTMLElement.cpp9
-rw-r--r--dom/html/HTMLSummaryElement.cpp12
-rw-r--r--dom/html/nsGenericHTMLElement.cpp6
-rw-r--r--dom/html/nsGenericHTMLElement.h16
-rw-r--r--dom/html/nsHTMLContentSink.cpp141
-rw-r--r--dom/html/nsHTMLDocument.cpp59
-rw-r--r--dom/html/nsHTMLDocument.h4
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if4.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if1.html30
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if2.html28
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if3.html27
-rw-r--r--dom/html/test/mochitest.ini10
-rw-r--r--dom/html/test/test_bug391777.html25
-rw-r--r--dom/html/test/test_iframe_sandbox_general.html2
-rw-r--r--dom/html/test/test_iframe_sandbox_modal.html122
-rw-r--r--dom/jsurl/nsJSProtocolHandler.cpp3
-rw-r--r--dom/locales/en-US/chrome/dom/dom.properties2
-rw-r--r--dom/media/webspeech/recognition/test/test_nested_eventloop.html4
-rw-r--r--dom/svg/SVGElementFactory.cpp56
-rw-r--r--dom/svg/SVGElementFactory.h25
-rw-r--r--dom/svg/SVGTagList.h9
-rw-r--r--dom/svg/moz.build2
-rw-r--r--dom/tests/mochitest/bugs/file_bug291653.html28
-rw-r--r--dom/tests/mochitest/bugs/file_bug504862.html22
-rw-r--r--dom/tests/mochitest/bugs/mochitest.ini12
-rw-r--r--dom/tests/mochitest/bugs/test_bug291653.html56
-rw-r--r--dom/tests/mochitest/bugs/test_bug406375.html37
-rw-r--r--dom/tests/mochitest/bugs/test_bug414291.html6
-rw-r--r--dom/tests/mochitest/bugs/test_bug437361.html72
-rw-r--r--dom/tests/mochitest/bugs/test_bug479143.html44
-rw-r--r--dom/tests/mochitest/bugs/test_bug504862.html45
-rw-r--r--dom/tests/mochitest/bugs/test_bug61098.html22
-rw-r--r--dom/tests/mochitest/bugs/test_bug735237.html38
-rw-r--r--dom/tests/mochitest/general/file_showModalDialog.html35
-rwxr-xr-xdom/tests/mochitest/general/mochitest.ini3
-rw-r--r--dom/tests/mochitest/general/test_showModalDialog.html60
-rw-r--r--dom/tests/mochitest/webcomponents/chrome.ini9
-rw-r--r--dom/tests/mochitest/webcomponents/dummy_page.html10
-rw-r--r--dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js81
-rw-r--r--dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js247
-rw-r--r--dom/tests/mochitest/webcomponents/mochitest.ini18
-rw-r--r--dom/tests/mochitest/webcomponents/test_bug1276240.html2
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_adopt_callbacks.html29
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html12
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks.html54
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks_extended.html40
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html42
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html41
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_import_node_created_callback.html34
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_register_invalid_callbacks.html3
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_throw_on_dynamic_markup_insertion.html66
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_uncatchable_exception.html37
-rw-r--r--dom/tests/mochitest/webcomponents/test_document_register.html40
-rw-r--r--dom/tests/mochitest/webcomponents/test_document_register_base_queue.html48
-rw-r--r--dom/tests/mochitest/webcomponents/test_document_register_parser.html4
-rw-r--r--dom/tests/mochitest/webcomponents/test_document_register_stack.html4
-rw-r--r--dom/tests/mochitest/webcomponents/test_document_shared_registry.html33
-rw-r--r--dom/tests/moz.build1
-rw-r--r--dom/webidl/Attr.webidl2
-rw-r--r--dom/webidl/CSSStyleDeclaration.webidl6
-rw-r--r--dom/webidl/ChildNode.webidl8
-rw-r--r--dom/webidl/CustomElementRegistry.webidl2
-rw-r--r--dom/webidl/DOMStringMap.webidl3
-rw-r--r--dom/webidl/DOMTokenList.webidl12
-rw-r--r--dom/webidl/Document.webidl8
-rw-r--r--dom/webidl/Element.webidl28
-rw-r--r--dom/webidl/EventHandler.webidl1
-rw-r--r--dom/webidl/HTMLAnchorElement.webidl27
-rw-r--r--dom/webidl/HTMLAreaElement.webidl17
-rw-r--r--dom/webidl/HTMLAudioElement.webidl2
-rw-r--r--dom/webidl/HTMLBRElement.webidl3
-rw-r--r--dom/webidl/HTMLBaseElement.webidl5
-rw-r--r--dom/webidl/HTMLBodyElement.webidl19
-rw-r--r--dom/webidl/HTMLButtonElement.webidl21
-rw-r--r--dom/webidl/HTMLCanvasElement.webidl5
-rw-r--r--dom/webidl/HTMLDListElement.webidl3
-rw-r--r--dom/webidl/HTMLDataElement.webidl3
-rw-r--r--dom/webidl/HTMLDataListElement.webidl1
-rw-r--r--dom/webidl/HTMLDetailsElement.webidl4
-rw-r--r--dom/webidl/HTMLDialogElement.webidl10
-rw-r--r--dom/webidl/HTMLDirectoryElement.webidl3
-rw-r--r--dom/webidl/HTMLDivElement.webidl3
-rw-r--r--dom/webidl/HTMLDocument.webidl26
-rw-r--r--dom/webidl/HTMLElement.webidl17
-rw-r--r--dom/webidl/HTMLEmbedElement.webidl14
-rw-r--r--dom/webidl/HTMLFieldSetElement.webidl5
-rw-r--r--dom/webidl/HTMLFontElement.webidl7
-rw-r--r--dom/webidl/HTMLFormElement.webidl21
-rw-r--r--dom/webidl/HTMLFrameElement.webidl19
-rw-r--r--dom/webidl/HTMLFrameSetElement.webidl5
-rw-r--r--dom/webidl/HTMLHRElement.webidl11
-rw-r--r--dom/webidl/HTMLHeadElement.webidl1
-rw-r--r--dom/webidl/HTMLHeadingElement.webidl3
-rw-r--r--dom/webidl/HTMLHtmlElement.webidl3
-rw-r--r--dom/webidl/HTMLHyperlinkElementUtils.webidl11
-rw-r--r--dom/webidl/HTMLIFrameElement.webidl29
-rw-r--r--dom/webidl/HTMLImageElement.webidl36
-rw-r--r--dom/webidl/HTMLInputElement.webidl64
-rw-r--r--dom/webidl/HTMLLIElement.webidl5
-rw-r--r--dom/webidl/HTMLLabelElement.webidl2
-rw-r--r--dom/webidl/HTMLLegendElement.webidl3
-rw-r--r--dom/webidl/HTMLLinkElement.webidl23
-rw-r--r--dom/webidl/HTMLMapElement.webidl3
-rw-r--r--dom/webidl/HTMLMediaElement.webidl14
-rw-r--r--dom/webidl/HTMLMenuElement.webidl7
-rw-r--r--dom/webidl/HTMLMenuItemElement.webidl15
-rw-r--r--dom/webidl/HTMLMetaElement.webidl9
-rw-r--r--dom/webidl/HTMLMeterElement.webidl13
-rw-r--r--dom/webidl/HTMLModElement.webidl5
-rw-r--r--dom/webidl/HTMLOListElement.webidl9
-rw-r--r--dom/webidl/HTMLObjectElement.webidl36
-rw-r--r--dom/webidl/HTMLOptGroupElement.webidl5
-rw-r--r--dom/webidl/HTMLOptionElement.webidl14
-rw-r--r--dom/webidl/HTMLOptionsCollection.webidl9
-rw-r--r--dom/webidl/HTMLOutputElement.webidl7
-rw-r--r--dom/webidl/HTMLParagraphElement.webidl3
-rw-r--r--dom/webidl/HTMLParamElement.webidl9
-rw-r--r--dom/webidl/HTMLPictureElement.webidl1
-rw-r--r--dom/webidl/HTMLPreElement.webidl3
-rw-r--r--dom/webidl/HTMLProgressElement.webidl5
-rw-r--r--dom/webidl/HTMLQuoteElement.webidl3
-rw-r--r--dom/webidl/HTMLScriptElement.webidl23
-rw-r--r--dom/webidl/HTMLSelectElement.webidl23
-rw-r--r--dom/webidl/HTMLSourceElement.webidl11
-rw-r--r--dom/webidl/HTMLSpanElement.webidl1
-rw-r--r--dom/webidl/HTMLStyleElement.webidl5
-rw-r--r--dom/webidl/HTMLTableCaptionElement.webidl3
-rw-r--r--dom/webidl/HTMLTableCellElement.webidl30
-rw-r--r--dom/webidl/HTMLTableColElement.webidl13
-rw-r--r--dom/webidl/HTMLTableElement.webidl33
-rw-r--r--dom/webidl/HTMLTableRowElement.webidl14
-rw-r--r--dom/webidl/HTMLTableSectionElement.webidl11
-rw-r--r--dom/webidl/HTMLTemplateElement.webidl1
-rw-r--r--dom/webidl/HTMLTextAreaElement.webidl27
-rw-r--r--dom/webidl/HTMLTimeElement.webidl3
-rw-r--r--dom/webidl/HTMLTitleElement.webidl3
-rw-r--r--dom/webidl/HTMLTrackElement.webidl11
-rw-r--r--dom/webidl/HTMLUListElement.webidl5
-rw-r--r--dom/webidl/HTMLVideoElement.webidl7
-rw-r--r--dom/webidl/NamedNodeMap.webidl8
-rw-r--r--dom/webidl/Node.webidl14
-rw-r--r--dom/webidl/ParentNode.webidl4
-rw-r--r--dom/webidl/Range.webidl12
-rw-r--r--dom/webidl/ShadowRoot.webidl2
-rw-r--r--dom/webidl/WebComponents.webidl18
-rw-r--r--dom/webidl/Window.webidl14
-rw-r--r--dom/webidl/XSLTProcessor.webidl4
-rw-r--r--dom/xul/nsXULElement.cpp52
-rw-r--r--dom/xul/nsXULElement.h17
204 files changed, 4036 insertions, 3068 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index 3f202d33b..99452df65 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -6,9 +6,11 @@
#include "mozilla/dom/CustomElementRegistry.h"
+#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/WebComponentsBinding.h"
+#include "mozilla/dom/DocGroup.h"
#include "nsIParserService.h"
#include "jsapi.h"
@@ -18,40 +20,21 @@ namespace dom {
void
CustomElementCallback::Call()
{
- ErrorResult rv;
+ IgnoredErrorResult rv;
switch (mType) {
- case nsIDocument::eCreated:
- {
- // For the duration of this callback invocation, the element is being created
- // flag must be set to true.
- mOwnerData->mElementIsBeingCreated = true;
-
- // The callback hasn't actually been invoked yet, but we need to flip
- // 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()) {
- nsContentUtils::EnqueueLifecycleCallback(
- document, nsIDocument::eAttached, mThisObject);
- }
-
- static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv);
- mOwnerData->mElementIsBeingCreated = false;
+ case nsIDocument::eConnected:
+ static_cast<LifecycleConnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
break;
- }
- case nsIDocument::eAttached:
- static_cast<LifecycleAttachedCallback *>(mCallback.get())->Call(mThisObject, rv);
+ case nsIDocument::eDisconnected:
+ static_cast<LifecycleDisconnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
break;
- case nsIDocument::eDetached:
- static_cast<LifecycleDetachedCallback *>(mCallback.get())->Call(mThisObject, rv);
+ case nsIDocument::eAdopted:
+ static_cast<LifecycleAdoptedCallback *>(mCallback.get())->Call(mThisObject,
+ mAdoptedCallbackArgs.mOldDocument, mAdoptedCallbackArgs.mNewDocument, rv);
break;
case nsIDocument::eAttributeChanged:
static_cast<LifecycleAttributeChangedCallback *>(mCallback.get())->Call(mThisObject,
- mArgs.name, mArgs.oldValue, mArgs.newValue, rv);
+ mArgs.name, mArgs.oldValue, mArgs.newValue, mArgs.namespaceURI, rv);
break;
}
}
@@ -68,87 +51,164 @@ CustomElementCallback::Traverse(nsCycleCollectionTraversalCallback& aCb) const
CustomElementCallback::CustomElementCallback(Element* aThisObject,
nsIDocument::ElementCallbackType aCallbackType,
- mozilla::dom::CallbackFunction* aCallback,
- CustomElementData* aOwnerData)
+ mozilla::dom::CallbackFunction* aCallback)
: mThisObject(aThisObject),
mCallback(aCallback),
- mType(aCallbackType),
- mOwnerData(aOwnerData)
+ mType(aCallbackType)
+{
+}
+
+//-----------------------------------------------------
+// CustomElementConstructor
+
+already_AddRefed<Element>
+CustomElementConstructor::Construct(const char* aExecutionReason,
+ ErrorResult& aRv)
{
+ CallSetup s(this, aRv, aExecutionReason,
+ CallbackFunction::eRethrowExceptions);
+
+ JSContext* cx = s.GetContext();
+ if (!cx) {
+ MOZ_ASSERT(aRv.Failed());
+ return nullptr;
+ }
+
+ JS::Rooted<JSObject*> result(cx);
+ JS::Rooted<JS::Value> constructor(cx, JS::ObjectValue(*mCallback));
+ if (!JS::Construct(cx, constructor, JS::HandleValueArray::empty(), &result)) {
+ aRv.NoteJSContextException(cx);
+ return nullptr;
+ }
+
+ RefPtr<Element> element;
+ if (NS_FAILED(UNWRAP_OBJECT(Element, &result, element))) {
+ return nullptr;
+ }
+
+ return element.forget();
}
+//-----------------------------------------------------
+// CustomElementData
+
CustomElementData::CustomElementData(nsIAtom* aType)
- : mType(aType),
- mCurrentCallback(-1),
- mElementIsBeingCreated(false),
- mCreatedCallbackInvoked(true),
- mAssociatedMicroTask(-1)
+ : CustomElementData(aType, CustomElementData::State::eUndefined)
+{
+}
+
+CustomElementData::CustomElementData(nsIAtom* aType, State aState)
+ : mState(aState)
+ , mType(aType)
{
}
void
-CustomElementData::RunCallbackQueue()
+CustomElementData::SetCustomElementDefinition(CustomElementDefinition* aDefinition)
{
- // Note: It's possible to re-enter this method.
- while (static_cast<uint32_t>(++mCurrentCallback) < mCallbackQueue.Length()) {
- mCallbackQueue[mCurrentCallback]->Call();
+ MOZ_ASSERT(mState == State::eCustom);
+ MOZ_ASSERT(!mCustomElementDefinition);
+ MOZ_ASSERT(aDefinition->mType == mType);
+
+ mCustomElementDefinition = aDefinition;
+}
+
+CustomElementDefinition*
+CustomElementData::GetCustomElementDefinition()
+{
+ MOZ_ASSERT(mCustomElementDefinition ? mState == State::eCustom
+ : mState != State::eCustom);
+
+ return mCustomElementDefinition;
+}
+
+nsIAtom*
+CustomElementData::GetCustomElementType()
+{
+ return mType;
+}
+
+void
+CustomElementData::Traverse(nsCycleCollectionTraversalCallback& aCb) const
+{
+ for (uint32_t i = 0; i < mReactionQueue.Length(); i++) {
+ if (mReactionQueue[i]) {
+ mReactionQueue[i]->Traverse(aCb);
+ }
}
- mCallbackQueue.Clear();
- mCurrentCallback = -1;
+ if (mCustomElementDefinition) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mCustomElementDefinition");
+ aCb.NoteNativeChild(mCustomElementDefinition,
+ NS_CYCLE_COLLECTION_PARTICIPANT(CustomElementDefinition));
+ }
}
+void
+CustomElementData::Unlink()
+{
+ mReactionQueue.Clear();
+ mCustomElementDefinition = nullptr;
+}
+
+//-----------------------------------------------------
+// CustomElementRegistry
+
+namespace {
+
+class MOZ_RAII AutoConstructionStackEntry final
+{
+public:
+ AutoConstructionStackEntry(nsTArray<RefPtr<nsGenericHTMLElement>>& aStack,
+ nsGenericHTMLElement* aElement)
+ : mStack(aStack)
+ {
+ mIndex = mStack.Length();
+ mStack.AppendElement(aElement);
+ }
+
+ ~AutoConstructionStackEntry()
+ {
+ MOZ_ASSERT(mIndex == mStack.Length() - 1,
+ "Removed element should be the last element");
+ mStack.RemoveElementAt(mIndex);
+ }
+
+private:
+ nsTArray<RefPtr<nsGenericHTMLElement>>& mStack;
+ uint32_t mIndex;
+};
+
+} // namespace anonymous
+
// Only needed for refcounted objects.
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementRegistry)
- tmp->mCustomDefinitions.Clear();
+ tmp->mConstructors.clear();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomDefinitions)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
- for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
- nsAutoPtr<LifecycleCallbacks>& callbacks = iter.UserData()->mCallbacks;
-
- if (callbacks->mAttributeChangedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
- cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
- }
-
- if (callbacks->mCreatedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mCreatedCallback");
- cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
- }
-
- if (callbacks->mAttachedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mAttachedCallback");
- cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
- }
-
- if (callbacks->mDetachedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mDetachedCallback");
- cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
- }
- }
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomDefinitions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementRegistry)
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
- aCallbacks.Trace(&iter.UserData()->mConstructor,
- "mCustomDefinitions constructor",
- aClosure);
aCallbacks.Trace(&iter.UserData()->mPrototype,
"mCustomDefinitions prototype",
aClosure);
}
+ for (ConstructorMap::Enum iter(tmp->mConstructors); !iter.empty(); iter.popFront()) {
+ aCallbacks.Trace(&iter.front().mutableKey(),
+ "mConstructors key",
+ aClosure);
+ }
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
@@ -163,97 +223,52 @@ NS_INTERFACE_MAP_END
/* static */ bool
CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
{
- return Preferences::GetBool("dom.webcomponents.customelements.enabled") ||
- Preferences::GetBool("dom.webcomponents.enabled");
+ return nsContentUtils::IsCustomElementsEnabled();
}
-/* static */ already_AddRefed<CustomElementRegistry>
-CustomElementRegistry::Create(nsPIDOMWindowInner* aWindow)
+CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
+ : mWindow(aWindow)
+ , mIsCustomDefinitionRunning(false)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsInnerWindow());
+ MOZ_ALWAYS_TRUE(mConstructors.init());
- if (!aWindow->GetDocShell()) {
- return nullptr;
- }
-
- if (!IsCustomElementEnabled()) {
- return nullptr;
- }
-
- RefPtr<CustomElementRegistry> customElementRegistry =
- new CustomElementRegistry(aWindow);
- return customElementRegistry.forget();
-}
-
-/* static */ void
-CustomElementRegistry::ProcessTopElementQueue()
-{
- MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
-
- nsTArray<RefPtr<CustomElementData>>& stack = *sProcessingStack;
- uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
-
- for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
- // Callback queue may have already been processed in an earlier
- // element queue or in an element queue that was popped
- // off more recently.
- if (stack[i]->mAssociatedMicroTask != -1) {
- stack[i]->RunCallbackQueue();
- stack[i]->mAssociatedMicroTask = -1;
- }
- }
-
- // If this was actually the base element queue, don't bother trying to pop
- // the first "queue" marker (sentinel).
- if (firstQueue != 0) {
- stack.SetLength(firstQueue);
- } else {
- // Don't pop sentinel for base element queue.
- stack.SetLength(1);
- }
+ mozilla::HoldJSObjects(this);
}
-/* static */ void
-CustomElementRegistry::XPCOMShutdown()
+CustomElementRegistry::~CustomElementRegistry()
{
- sProcessingStack.reset();
+ mozilla::DropJSObjects(this);
}
-/* static */ Maybe<nsTArray<RefPtr<CustomElementData>>>
-CustomElementRegistry::sProcessingStack;
-
-CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
- : mWindow(aWindow)
- , mIsCustomDefinitionRunning(false)
+CustomElementDefinition*
+CustomElementRegistry::LookupCustomElementDefinition(nsIAtom* aNameAtom,
+ nsIAtom* aTypeAtom) const
{
- mozilla::HoldJSObjects(this);
-
- if (!sProcessingStack) {
- sProcessingStack.emplace();
- // Add the base queue sentinel to the processing stack.
- sProcessingStack->AppendElement((CustomElementData*) nullptr);
+ CustomElementDefinition* data = mCustomDefinitions.GetWeak(aTypeAtom);
+ if (data && data->mLocalName == aNameAtom) {
+ return data;
}
-}
-CustomElementRegistry::~CustomElementRegistry()
-{
- mozilla::DropJSObjects(this);
+ return nullptr;
}
CustomElementDefinition*
-CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
- const nsAString* aIs) const
+CustomElementRegistry::LookupCustomElementDefinition(JSContext* aCx,
+ JSObject* aConstructor) const
{
- nsCOMPtr<nsIAtom> localNameAtom = NS_Atomize(aLocalName);
- nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
+ JS::Rooted<JSObject*> constructor(aCx, js::CheckedUnwrap(aConstructor));
- CustomElementDefinition* data = mCustomDefinitions.Get(typeAtom);
- if (data && data->mLocalName == localNameAtom) {
- return data;
+ const auto& ptr = mConstructors.lookup(constructor);
+ if (!ptr) {
+ return nullptr;
}
- return nullptr;
+ CustomElementDefinition* definition = mCustomDefinitions.GetWeak(ptr->value());
+ MOZ_ASSERT(definition, "Definition must be found in mCustomDefinitions");
+
+ return definition;
}
void
@@ -269,7 +284,7 @@ CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTy
typeName = info->NameAtom();
}
- if (mCustomDefinitions.Get(typeName)) {
+ if (mCustomDefinitions.GetWeak(typeName)) {
return;
}
@@ -282,171 +297,129 @@ CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTy
}
void
-CustomElementRegistry::SetupCustomElement(Element* aElement,
- const nsAString* aTypeExtension)
+CustomElementRegistry::UnregisterUnresolvedElement(Element* aElement,
+ nsIAtom* aTypeName)
{
- nsCOMPtr<nsIAtom> tagAtom = aElement->NodeInfo()->NameAtom();
- nsCOMPtr<nsIAtom> typeAtom = aTypeExtension ?
- NS_Atomize(*aTypeExtension) : tagAtom;
-
- if (aTypeExtension && !aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::is)) {
- // Custom element setup in the parser happens after the "is"
- // attribute is added.
- aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *aTypeExtension, true);
- }
-
- CustomElementDefinition* data = LookupCustomElementDefinition(
- aElement->NodeInfo()->LocalName(), aTypeExtension);
-
- if (!data) {
- // The type extension doesn't exist in the registry,
- // thus we don't need to enqueue callback or adjust
- // the "is" attribute, but it is possibly an upgrade candidate.
- RegisterUnresolvedElement(aElement, typeAtom);
- return;
- }
-
- if (data->mLocalName != tagAtom) {
- // The element doesn't match the local name for the
- // definition, thus the element isn't a custom element
- // and we don't need to do anything more.
- return;
+ nsTArray<nsWeakPtr>* candidates;
+ if (mCandidatesMap.Get(aTypeName, &candidates)) {
+ MOZ_ASSERT(candidates);
+ // We don't need to iterate the candidates array and remove the element from
+ // the array for performance reason. It'll be handled by bug 1396620.
+ for (size_t i = 0; i < candidates->Length(); ++i) {
+ nsCOMPtr<Element> elem = do_QueryReferent(candidates->ElementAt(i));
+ if (elem && elem.get() == aElement) {
+ candidates->RemoveElementAt(i);
+ }
+ }
}
-
- // Enqueuing the created callback will set the CustomElementData on the
- // element, causing prototype swizzling to occur in Element::WrapObject.
- EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, data);
}
-void
-CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
- Element* aCustomElement,
- LifecycleCallbackArgs* aArgs,
- CustomElementDefinition* aDefinition)
+/* static */ UniquePtr<CustomElementCallback>
+CustomElementRegistry::CreateCustomElementCallback(
+ nsIDocument::ElementCallbackType aType, Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition)
{
- CustomElementData* elementData = aCustomElement->GetCustomElementData();
-
- // Let DEFINITION be ELEMENT's definition
- CustomElementDefinition* definition = aDefinition;
- if (!definition) {
- mozilla::dom::NodeInfo* info = aCustomElement->NodeInfo();
-
- // Make sure we get the correct definition in case the element
- // is a extended custom element e.g. <button is="x-button">.
- nsCOMPtr<nsIAtom> typeAtom = elementData ?
- elementData->mType.get() : info->NameAtom();
+ MOZ_ASSERT(aDefinition, "CustomElementDefinition should not be null");
- definition = mCustomDefinitions.Get(typeAtom);
- if (!definition || definition->mLocalName != info->NameAtom()) {
- // Trying to enqueue a callback for an element that is not
- // a custom element. We are done, nothing to do.
- return;
- }
- }
-
- if (!elementData) {
- // Create the custom element data the first time
- // that we try to enqueue a callback.
- elementData = new CustomElementData(definition->mType);
- // aCustomElement takes ownership of elementData
- aCustomElement->SetCustomElementData(elementData);
- MOZ_ASSERT(aType == nsIDocument::eCreated,
- "First callback should be the created callback");
- }
+ MOZ_ASSERT(aCustomElement->GetCustomElementData(),
+ "CustomElementData should exist");
// Let CALLBACK be the callback associated with the key NAME in CALLBACKS.
CallbackFunction* func = nullptr;
switch (aType) {
- case nsIDocument::eCreated:
- if (definition->mCallbacks->mCreatedCallback.WasPassed()) {
- func = definition->mCallbacks->mCreatedCallback.Value();
+ case nsIDocument::eConnected:
+ if (aDefinition->mCallbacks->mConnectedCallback.WasPassed()) {
+ func = aDefinition->mCallbacks->mConnectedCallback.Value();
}
break;
- case nsIDocument::eAttached:
- if (definition->mCallbacks->mAttachedCallback.WasPassed()) {
- func = definition->mCallbacks->mAttachedCallback.Value();
+ case nsIDocument::eDisconnected:
+ if (aDefinition->mCallbacks->mDisconnectedCallback.WasPassed()) {
+ func = aDefinition->mCallbacks->mDisconnectedCallback.Value();
}
break;
- case nsIDocument::eDetached:
- if (definition->mCallbacks->mDetachedCallback.WasPassed()) {
- func = definition->mCallbacks->mDetachedCallback.Value();
+ case nsIDocument::eAdopted:
+ if (aDefinition->mCallbacks->mAdoptedCallback.WasPassed()) {
+ func = aDefinition->mCallbacks->mAdoptedCallback.Value();
}
break;
case nsIDocument::eAttributeChanged:
- if (definition->mCallbacks->mAttributeChangedCallback.WasPassed()) {
- func = definition->mCallbacks->mAttributeChangedCallback.Value();
+ if (aDefinition->mCallbacks->mAttributeChangedCallback.WasPassed()) {
+ func = aDefinition->mCallbacks->mAttributeChangedCallback.Value();
}
break;
}
// If there is no such callback, stop.
if (!func) {
- return;
- }
-
- if (aType == nsIDocument::eCreated) {
- elementData->mCreatedCallbackInvoked = false;
- } else if (!elementData->mCreatedCallbackInvoked) {
- // Callbacks other than created callback must not be enqueued
- // until after the created callback has been invoked.
- return;
+ return nullptr;
}
// Add CALLBACK to ELEMENT's callback queue.
- CustomElementCallback* callback = new CustomElementCallback(aCustomElement,
- aType,
- func,
- elementData);
- // Ownership of callback is taken by mCallbackQueue.
- elementData->mCallbackQueue.AppendElement(callback);
+ auto callback =
+ MakeUnique<CustomElementCallback>(aCustomElement, aType, func);
+
if (aArgs) {
callback->SetArgs(*aArgs);
}
- if (!elementData->mElementIsBeingCreated) {
- CustomElementData* lastData =
- sProcessingStack->SafeLastElement(nullptr);
-
- // A new element queue needs to be pushed if the queue at the
- // top of the stack is associated with another microtask level.
- bool shouldPushElementQueue =
- (!lastData || lastData->mAssociatedMicroTask <
- static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
+ if (aAdoptedCallbackArgs) {
+ callback->SetAdoptedCallbackArgs(*aAdoptedCallbackArgs);
+ }
+ return Move(callback);
+}
- // Push a new element queue onto the processing stack when appropriate
- // (when we enter a new microtask).
- if (shouldPushElementQueue) {
- // Push a sentinel value on the processing stack to mark the
- // boundary between the element queues.
- sProcessingStack->AppendElement((CustomElementData*) nullptr);
+/* static */ void
+CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
+ Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition)
+{
+ CustomElementDefinition* definition = aDefinition;
+ if (!definition) {
+ definition = aCustomElement->GetCustomElementDefinition();
+ if (!definition ||
+ definition->mLocalName != aCustomElement->NodeInfo()->NameAtom()) {
+ return;
}
+ }
- sProcessingStack->AppendElement(elementData);
- elementData->mAssociatedMicroTask =
- static_cast<int32_t>(nsContentUtils::MicroTaskLevel());
-
- // Add a script runner to pop and process the element queue at
- // the top of the processing stack.
- if (shouldPushElementQueue) {
- // Lifecycle callbacks enqueued by user agent implementation
- // should be invoked prior to returning control back to script.
- // Create a script runner to process the top of the processing
- // stack as soon as it is safe to run script.
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction(&CustomElementRegistry::ProcessTopElementQueue);
- nsContentUtils::AddScriptRunner(runnable);
+ auto callback =
+ CreateCustomElementCallback(aType, aCustomElement, aArgs,
+ aAdoptedCallbackArgs, definition);
+ if (!callback) {
+ return;
+ }
+
+ DocGroup* docGroup = aCustomElement->OwnerDoc()->GetDocGroup();
+ if (!docGroup) {
+ return;
+ }
+
+ if (aType == nsIDocument::eAttributeChanged) {
+ nsCOMPtr<nsIAtom> attrName = NS_Atomize(aArgs->name);
+ if (definition->mObservedAttributes.IsEmpty() ||
+ !definition->mObservedAttributes.Contains(attrName)) {
+ return;
}
}
+
+ CustomElementReactionsStack* reactionsStack =
+ docGroup->CustomElementReactionsStack();
+ reactionsStack->EnqueueCallbackReaction(aCustomElement, Move(callback));
}
void
CustomElementRegistry::GetCustomPrototype(nsIAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype)
{
- mozilla::dom::CustomElementDefinition* definition = mCustomDefinitions.Get(aAtom);
+ mozilla::dom::CustomElementDefinition* definition =
+ mCustomDefinitions.GetWeak(aAtom);
if (definition) {
aPrototype.set(definition->mPrototype);
} else {
@@ -455,48 +428,29 @@ CustomElementRegistry::GetCustomPrototype(nsIAtom* aAtom,
}
void
-CustomElementRegistry::UpgradeCandidates(JSContext* aCx,
- nsIAtom* aKey,
- CustomElementDefinition* aDefinition)
+CustomElementRegistry::UpgradeCandidates(nsIAtom* aKey,
+ CustomElementDefinition* aDefinition,
+ ErrorResult& aRv)
{
+ DocGroup* docGroup = mWindow->GetDocGroup();
+ if (!docGroup) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return;
+ }
+
+ // TODO: Bug 1326028 - Upgrade custom element in shadow-including tree order
nsAutoPtr<nsTArray<nsWeakPtr>> candidates;
mCandidatesMap.RemoveAndForget(aKey, candidates);
if (candidates) {
+ CustomElementReactionsStack* reactionsStack =
+ docGroup->CustomElementReactionsStack();
for (size_t i = 0; i < candidates->Length(); ++i) {
nsCOMPtr<Element> elem = do_QueryReferent(candidates->ElementAt(i));
if (!elem) {
continue;
}
- elem->RemoveStates(NS_EVENT_STATE_UNRESOLVED);
-
- // Make sure that the element name matches the name in the definition.
- // (e.g. a definition for x-button extending button should match
- // <button is="x-button"> but not <x-button>.
- if (elem->NodeInfo()->NameAtom() != aDefinition->mLocalName) {
- //Skip over this element because definition does not apply.
- continue;
- }
-
- MOZ_ASSERT(elem->IsHTMLElement(aDefinition->mLocalName));
- nsWrapperCache* cache;
- CallQueryInterface(elem, &cache);
- MOZ_ASSERT(cache, "Element doesn't support wrapper cache?");
-
- // We want to set the custom prototype in the caller's comparment.
- // In the case that element is in a different compartment,
- // this will set the prototype on the element's wrapper and
- // thus only visible in the wrapper's compartment.
- JS::RootedObject wrapper(aCx);
- JS::Rooted<JSObject*> prototype(aCx, aDefinition->mPrototype);
- if ((wrapper = cache->GetWrapper()) && JS_WrapObject(aCx, &wrapper)) {
- if (!JS_SetPrototype(aCx, wrapper, prototype)) {
- continue;
- }
- }
-
- nsContentUtils::EnqueueLifecycleCallback(
- elem->OwnerDoc(), nsIDocument::eCreated, elem, nullptr, aDefinition);
+ reactionsStack->EnqueueUpgradeReaction(elem, aDefinition);
}
}
}
@@ -516,11 +470,7 @@ static const char* kLifeCycleCallbackNames[] = {
"connectedCallback",
"disconnectedCallback",
"adoptedCallback",
- "attributeChangedCallback",
- // The life cycle callbacks from v0 spec.
- "createdCallback",
- "attachedCallback",
- "detachedCallback"
+ "attributeChangedCallback"
};
static void
@@ -600,7 +550,7 @@ CustomElementRegistry::Define(const nsAString& aName,
* 3. If this CustomElementRegistry contains an entry with name name, then
* throw a "NotSupportedError" DOMException and abort these steps.
*/
- if (mCustomDefinitions.Get(nameAtom)) {
+ if (mCustomDefinitions.GetWeak(nameAtom)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
@@ -609,9 +559,13 @@ CustomElementRegistry::Define(const nsAString& aName,
* 4. If this CustomElementRegistry contains an entry with constructor constructor,
* then throw a "NotSupportedError" DOMException and abort these steps.
*/
- // TODO: Step 3 of HTMLConstructor also needs a way to look up definition by
- // using constructor. So I plans to figure out a solution to support both of
- // them in bug 1274159.
+ const auto& ptr = mConstructors.lookup(constructorUnwrapped);
+ if (ptr) {
+ MOZ_ASSERT(mCustomDefinitions.GetWeak(ptr->value()),
+ "Definition must be found in mCustomDefinitions");
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return;
+ }
/**
* 5. Let localName be name.
@@ -663,6 +617,7 @@ CustomElementRegistry::Define(const nsAString& aName,
JS::Rooted<JSObject*> constructorPrototype(cx);
nsAutoPtr<LifecycleCallbacks> callbacksHolder(new LifecycleCallbacks());
+ nsCOMArray<nsIAtom> observedAttributes;
{ // Set mIsCustomDefinitionRunning.
/**
* 9. Set this CustomElementRegistry's element definition is running flag.
@@ -724,6 +679,14 @@ CustomElementRegistry::Define(const nsAString& aName,
return;
}
+ // Note: We call the init from the constructorProtoUnwrapped's compartment
+ // here.
+ JS::RootedValue rootedv(cx, JS::ObjectValue(*constructorProtoUnwrapped));
+ if (!JS_WrapValue(cx, &rootedv) || !callbacksHolder->Init(cx, rootedv)) {
+ aRv.StealExceptionFromJSContext(cx);
+ return;
+ }
+
/**
* 10.5. Let observedAttributes be an empty sequence<DOMString>.
* 10.6. If the value of the entry in lifecycleCallbacks with key
@@ -735,15 +698,54 @@ CustomElementRegistry::Define(const nsAString& aName,
* observedAttributesIterable to a sequence<DOMString>. Rethrow
* any exceptions from the conversion.
*/
- // TODO: Bug 1293921 - Implement connected/disconnected/adopted/attributeChanged lifecycle callbacks for custom elements
+ if (callbacksHolder->mAttributeChangedCallback.WasPassed()) {
+ // Enter constructor's compartment.
+ JSAutoCompartment ac(cx, constructor);
+ JS::Rooted<JS::Value> observedAttributesIterable(cx);
+
+ if (!JS_GetProperty(cx, constructor, "observedAttributes",
+ &observedAttributesIterable)) {
+ aRv.StealExceptionFromJSContext(cx);
+ return;
+ }
- // Note: We call the init from the constructorProtoUnwrapped's compartment
- // here.
- JS::RootedValue rootedv(cx, JS::ObjectValue(*constructorProtoUnwrapped));
- if (!JS_WrapValue(cx, &rootedv) || !callbacksHolder->Init(cx, rootedv)) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
+ if (!observedAttributesIterable.isUndefined()) {
+ if (!observedAttributesIterable.isObject()) {
+ aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(NS_LITERAL_STRING("observedAttributes"));
+ return;
+ }
+
+ JS::ForOfIterator iter(cx);
+ if (!iter.init(observedAttributesIterable, JS::ForOfIterator::AllowNonIterable)) {
+ aRv.StealExceptionFromJSContext(cx);
+ return;
+ }
+
+ if (!iter.valueIsIterable()) {
+ aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(NS_LITERAL_STRING("observedAttributes"));
+ return;
+ }
+
+ JS::Rooted<JS::Value> attribute(cx);
+ while (true) {
+ bool done;
+ if (!iter.next(&attribute, &done)) {
+ aRv.StealExceptionFromJSContext(cx);
+ return;
+ }
+ if (done) {
+ break;
+ }
+
+ nsAutoString attrStr;
+ if (!ConvertJSValueToString(cx, attribute, eStringify, eStringify, attrStr)) {
+ aRv.StealExceptionFromJSContext(cx);
+ return;
+ }
+ observedAttributes.AppendElement(NS_Atomize(attrStr));
+ }
+ }
+ } // Leave constructor's compartment.
} // Leave constructorProtoUnwrapped's compartment.
} // Unset mIsCustomDefinitionRunning
@@ -756,24 +758,34 @@ CustomElementRegistry::Define(const nsAString& aName,
// Associate the definition with the custom element.
nsCOMPtr<nsIAtom> localNameAtom(NS_Atomize(localName));
LifecycleCallbacks* callbacks = callbacksHolder.forget();
- CustomElementDefinition* definition =
+
+ /**
+ * 12. Add definition to this CustomElementRegistry.
+ */
+ if (!mConstructors.put(constructorUnwrapped, nameAtom)) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
+
+ RefPtr<CustomElementDefinition> definition =
new CustomElementDefinition(nameAtom,
localNameAtom,
- constructor,
+ &aFunctionConstructor,
+ Move(observedAttributes),
constructorPrototype,
callbacks,
0 /* TODO dependent on HTML imports. Bug 877072 */);
- /**
- * 12. Add definition to this CustomElementRegistry.
- */
- mCustomDefinitions.Put(nameAtom, definition);
+ CustomElementDefinition* def = definition.get();
+ mCustomDefinitions.Put(nameAtom, definition.forget());
+
+ MOZ_ASSERT(mCustomDefinitions.Count() == mConstructors.count(),
+ "Number of entries should be the same");
/**
* 13. 14. 15. Upgrade candidates
*/
- // TODO: Bug 1299363 - Implement custom element v1 upgrade algorithm
- UpgradeCandidates(cx, nameAtom, definition);
+ UpgradeCandidates(nameAtom, def, aRv);
/**
* 16. If this CustomElementRegistry's when-defined promise map contains an
@@ -796,14 +808,14 @@ CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
JS::MutableHandle<JS::Value> aRetVal)
{
nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
- CustomElementDefinition* data = mCustomDefinitions.Get(nameAtom);
+ CustomElementDefinition* data = mCustomDefinitions.GetWeak(nameAtom);
if (!data) {
aRetVal.setUndefined();
return;
}
- aRetVal.setObject(*data->mConstructor);
+ aRetVal.setObjectOrNull(data->mConstructor->Callable());
return;
}
@@ -823,7 +835,7 @@ CustomElementRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
return promise.forget();
}
- if (mCustomDefinitions.Get(nameAtom)) {
+ if (mCustomDefinitions.GetWeak(nameAtom)) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
@@ -837,20 +849,346 @@ CustomElementRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
return promise.forget();
}
+namespace {
+
+static void
+DoUpgrade(Element* aElement,
+ CustomElementConstructor* aConstructor,
+ ErrorResult& aRv)
+{
+ // Rethrow the exception since it might actually throw the exception from the
+ // upgrade steps back out to the caller of document.createElement.
+ RefPtr<Element> constructResult =
+ aConstructor->Construct("Custom Element Upgrade", aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ if (!constructResult || constructResult.get() != aElement) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+}
+
+} // anonymous namespace
+
+// https://html.spec.whatwg.org/multipage/scripting.html#upgrades
+/* static */ void
+CustomElementRegistry::Upgrade(Element* aElement,
+ CustomElementDefinition* aDefinition,
+ ErrorResult& aRv)
+{
+ aElement->RemoveStates(NS_EVENT_STATE_UNRESOLVED);
+
+ RefPtr<CustomElementData> data = aElement->GetCustomElementData();
+ MOZ_ASSERT(data, "CustomElementData should exist");
+
+ // Step 1 and step 2.
+ if (data->mState == CustomElementData::State::eCustom ||
+ data->mState == CustomElementData::State::eFailed) {
+ return;
+ }
+
+ // Step 3.
+ if (!aDefinition->mObservedAttributes.IsEmpty()) {
+ uint32_t count = aElement->GetAttrCount();
+ for (uint32_t i = 0; i < count; i++) {
+ mozilla::dom::BorrowedAttrInfo info = aElement->GetAttrInfoAt(i);
+
+ const nsAttrName* name = info.mName;
+ nsIAtom* attrName = name->LocalName();
+
+ if (aDefinition->IsInObservedAttributeList(attrName)) {
+ int32_t namespaceID = name->NamespaceID();
+ nsAutoString attrValue, namespaceURI;
+ info.mValue->ToString(attrValue);
+ nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID,
+ namespaceURI);
+
+ LifecycleCallbackArgs args = {
+ nsDependentAtomString(attrName),
+ NullString(),
+ attrValue,
+ (namespaceURI.IsEmpty() ? NullString() : namespaceURI)
+ };
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
+ aElement,
+ &args, nullptr, aDefinition);
+ }
+ }
+ }
+
+ // Step 4.
+ if (aElement->IsInComposedDoc()) {
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, aElement,
+ nullptr, nullptr, aDefinition);
+ }
+
+ // Step 5.
+ AutoConstructionStackEntry acs(aDefinition->mConstructionStack,
+ nsGenericHTMLElement::FromContent(aElement));
+
+ // Step 6 and step 7.
+ DoUpgrade(aElement, aDefinition->mConstructor, aRv);
+ if (aRv.Failed()) {
+ data->mState = CustomElementData::State::eFailed;
+ // Empty element's custom element reaction queue.
+ data->mReactionQueue.Clear();
+ return;
+ }
+
+ // Step 8.
+ data->mState = CustomElementData::State::eCustom;
+
+ // Step 9.
+ aElement->SetCustomElementDefinition(aDefinition);
+}
+
+//-----------------------------------------------------
+// CustomElementReactionsStack
+
+void
+CustomElementReactionsStack::CreateAndPushElementQueue()
+{
+ MOZ_ASSERT(mRecursionDepth);
+ MOZ_ASSERT(!mIsElementQueuePushedForCurrentRecursionDepth);
+
+ // Push a new element queue onto the custom element reactions stack.
+ mReactionsStack.AppendElement(MakeUnique<ElementQueue>());
+ mIsElementQueuePushedForCurrentRecursionDepth = true;
+}
+
+void
+CustomElementReactionsStack::PopAndInvokeElementQueue()
+{
+ MOZ_ASSERT(mRecursionDepth);
+ MOZ_ASSERT(mIsElementQueuePushedForCurrentRecursionDepth);
+ MOZ_ASSERT(!mReactionsStack.IsEmpty(),
+ "Reaction stack shouldn't be empty");
+
+ // Pop the element queue from the custom element reactions stack,
+ // and invoke custom element reactions in that queue.
+ const uint32_t lastIndex = mReactionsStack.Length() - 1;
+ ElementQueue* elementQueue = mReactionsStack.ElementAt(lastIndex).get();
+ // Check element queue size in order to reduce function call overhead.
+ if (!elementQueue->IsEmpty()) {
+ // It is still not clear what error reporting will look like in custom
+ // element, see https://github.com/w3c/webcomponents/issues/635.
+ // We usually report the error to entry global in gecko, so just follow the
+ // same behavior here.
+ // This may be null if it's called from parser, see the case of
+ // attributeChangedCallback in
+ // https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
+ // In that case, the exception of callback reactions will be automatically
+ // reported in CallSetup.
+ nsIGlobalObject* global = GetEntryGlobal();
+ InvokeReactions(elementQueue, global);
+ }
+
+ // InvokeReactions() might create other custom element reactions, but those
+ // new reactions should be already consumed and removed at this point.
+ MOZ_ASSERT(lastIndex == mReactionsStack.Length() - 1,
+ "reactions created by InvokeReactions() should be consumed and removed");
+
+ mReactionsStack.RemoveElementAt(lastIndex);
+ mIsElementQueuePushedForCurrentRecursionDepth = false;
+}
+
+void
+CustomElementReactionsStack::EnqueueUpgradeReaction(Element* aElement,
+ CustomElementDefinition* aDefinition)
+{
+ Enqueue(aElement, new CustomElementUpgradeReaction(aDefinition));
+}
+
+void
+CustomElementReactionsStack::EnqueueCallbackReaction(Element* aElement,
+ UniquePtr<CustomElementCallback> aCustomElementCallback)
+{
+ Enqueue(aElement, new CustomElementCallbackReaction(Move(aCustomElementCallback)));
+}
+
+void
+CustomElementReactionsStack::Enqueue(Element* aElement,
+ CustomElementReaction* aReaction)
+{
+ RefPtr<CustomElementData> elementData = aElement->GetCustomElementData();
+ MOZ_ASSERT(elementData, "CustomElementData should exist");
+
+ if (mRecursionDepth) {
+ // If the element queue is not created for current recursion depth, create
+ // and push an element queue to reactions stack first.
+ if (!mIsElementQueuePushedForCurrentRecursionDepth) {
+ CreateAndPushElementQueue();
+ }
+
+ MOZ_ASSERT(!mReactionsStack.IsEmpty());
+ // Add element to the current element queue.
+ mReactionsStack.LastElement()->AppendElement(aElement);
+ elementData->mReactionQueue.AppendElement(aReaction);
+ return;
+ }
+
+ // If the custom element reactions stack is empty, then:
+ // Add element to the backup element queue.
+ MOZ_ASSERT(mReactionsStack.IsEmpty(),
+ "custom element reactions stack should be empty");
+ MOZ_ASSERT(!aReaction->IsUpgradeReaction(),
+ "Upgrade reaction should not be scheduled to backup queue");
+ mBackupQueue.AppendElement(aElement);
+ elementData->mReactionQueue.AppendElement(aReaction);
+
+ if (mIsBackupQueueProcessing) {
+ return;
+ }
+
+ CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
+ RefPtr<BackupQueueMicroTask> bqmt = new BackupQueueMicroTask(this);
+ context->DispatchMicroTaskRunnable(bqmt.forget());
+}
+
+void
+CustomElementReactionsStack::InvokeBackupQueue()
+{
+ // Check backup queue size in order to reduce function call overhead.
+ if (!mBackupQueue.IsEmpty()) {
+ // Upgrade reactions won't be scheduled in backup queue and the exception of
+ // callback reactions will be automatically reported in CallSetup.
+ // If the reactions are invoked from backup queue (in microtask check point),
+ // we don't need to pass global object for error reporting.
+ InvokeReactions(&mBackupQueue, nullptr);
+ }
+ MOZ_ASSERT(mBackupQueue.IsEmpty(),
+ "There are still some reactions in BackupQueue not being consumed!?!");
+}
+
+void
+CustomElementReactionsStack::InvokeReactions(ElementQueue* aElementQueue,
+ nsIGlobalObject* aGlobal)
+{
+ // This is used for error reporting.
+ Maybe<AutoEntryScript> aes;
+ if (aGlobal) {
+ aes.emplace(aGlobal, "custom elements reaction invocation");
+ }
+
+ // Note: It's possible to re-enter this method.
+ for (uint32_t i = 0; i < aElementQueue->Length(); ++i) {
+ Element* element = aElementQueue->ElementAt(i);
+
+ // ElementQueue hold a element's strong reference, it should not be a nullptr.
+ MOZ_ASSERT(element);
+
+ RefPtr<CustomElementData> elementData = element->GetCustomElementData();
+ if (!elementData) {
+ // This happens when the document is destroyed and the element is already
+ // unlinked, no need to fire the callbacks in this case.
+ continue;
+ }
+
+ auto& reactions = elementData->mReactionQueue;
+ for (uint32_t j = 0; j < reactions.Length(); ++j) {
+ // Transfer the ownership of the entry due to reentrant invocation of
+ // this funciton. The entry will be removed when bug 1379573 is landed.
+ auto reaction(Move(reactions.ElementAt(j)));
+ if (reaction) {
+ ErrorResult rv;
+ reaction->Invoke(element, rv);
+ if (aes) {
+ JSContext* cx = aes->cx();
+ if (rv.MaybeSetPendingException(cx)) {
+ aes->ReportException();
+ }
+ MOZ_ASSERT(!JS_IsExceptionPending(cx));
+ }
+ MOZ_ASSERT(!rv.Failed());
+ }
+ }
+ reactions.Clear();
+ }
+ aElementQueue->Clear();
+}
+
+//-----------------------------------------------------
+// CustomElementDefinition
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementDefinition)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementDefinition)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mConstructor)
+ tmp->mPrototype = nullptr;
+ tmp->mCallbacks = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition)
+ mozilla::dom::LifecycleCallbacks* callbacks = tmp->mCallbacks.get();
+
+ if (callbacks->mAttributeChangedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+ "mCallbacks->mAttributeChangedCallback");
+ cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
+ }
+
+ if (callbacks->mConnectedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mConnectedCallback");
+ cb.NoteXPCOMChild(callbacks->mConnectedCallback.Value());
+ }
+
+ if (callbacks->mDisconnectedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mDisconnectedCallback");
+ cb.NoteXPCOMChild(callbacks->mDisconnectedCallback.Value());
+ }
+
+ if (callbacks->mAdoptedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mAdoptedCallback");
+ cb.NoteXPCOMChild(callbacks->mAdoptedCallback.Value());
+ }
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mConstructor");
+ cb.NoteXPCOMChild(tmp->mConstructor);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementDefinition)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPrototype)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CustomElementDefinition, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CustomElementDefinition, Release)
+
CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,
nsIAtom* aLocalName,
- JSObject* aConstructor,
+ Function* aConstructor,
+ nsCOMArray<nsIAtom>&& aObservedAttributes,
JSObject* aPrototype,
LifecycleCallbacks* aCallbacks,
uint32_t aDocOrder)
: mType(aType),
mLocalName(aLocalName),
- mConstructor(aConstructor),
+ mConstructor(new CustomElementConstructor(aConstructor)),
+ mObservedAttributes(Move(aObservedAttributes)),
mPrototype(aPrototype),
mCallbacks(aCallbacks),
mDocOrder(aDocOrder)
{
}
+//-----------------------------------------------------
+// CustomElementUpgradeReaction
+
+/* virtual */ void
+CustomElementUpgradeReaction::Invoke(Element* aElement, ErrorResult& aRv)
+{
+ CustomElementRegistry::Upgrade(aElement, mDefinition, aRv);
+}
+
+//-----------------------------------------------------
+// CustomElementCallbackReaction
+
+/* virtual */ void
+CustomElementCallbackReaction::Invoke(Element* aElement, ErrorResult& aRv)
+{
+ mCustomElementCallback->Call();
+}
+
} // namespace dom
-} // namespace mozilla \ No newline at end of file
+} // namespace mozilla
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index ff803a054..c416e5043 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -7,13 +7,16 @@
#ifndef mozilla_dom_CustomElementRegistry_h
#define mozilla_dom_CustomElementRegistry_h
+#include "js/GCHashTable.h"
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/FunctionBinding.h"
+#include "mozilla/dom/WebComponentsBinding.h"
#include "nsCycleCollectionParticipant.h"
+#include "nsGenericHTMLElement.h"
#include "nsWrapperCache.h"
-#include "mozilla/dom/FunctionBinding.h"
class nsDocument;
@@ -22,8 +25,8 @@ namespace dom {
struct CustomElementData;
struct ElementDefinitionOptions;
-struct LifecycleCallbacks;
class CallbackFunction;
+class CustomElementReaction;
class Function;
class Promise;
@@ -32,6 +35,13 @@ struct LifecycleCallbackArgs
nsString name;
nsString oldValue;
nsString newValue;
+ nsString namespaceURI;
+};
+
+struct LifecycleAdoptedCallbackArgs
+{
+ nsCOMPtr<nsIDocument> mOldDocument;
+ nsCOMPtr<nsIDocument> mNewDocument;
};
class CustomElementCallback
@@ -39,8 +49,7 @@ class CustomElementCallback
public:
CustomElementCallback(Element* aThisObject,
nsIDocument::ElementCallbackType aCallbackType,
- CallbackFunction* aCallback,
- CustomElementData* aOwnerData);
+ CallbackFunction* aCallback);
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
void Call();
void SetArgs(LifecycleCallbackArgs& aArgs)
@@ -50,6 +59,13 @@ public:
mArgs = aArgs;
}
+ void SetAdoptedCallbackArgs(LifecycleAdoptedCallbackArgs& aAdoptedCallbackArgs)
+ {
+ MOZ_ASSERT(mType == nsIDocument::eAdopted,
+ "Arguments are only used by adopted callback.");
+ mAdoptedCallbackArgs = aAdoptedCallbackArgs;
+ }
+
private:
// The this value to use for invocation of the callback.
RefPtr<Element> mThisObject;
@@ -59,9 +75,19 @@ private:
// Arguments to be passed to the callback,
// used by the attribute changed callback.
LifecycleCallbackArgs mArgs;
- // CustomElementData that contains this callback in the
- // callback queue.
- CustomElementData* mOwnerData;
+ LifecycleAdoptedCallbackArgs mAdoptedCallbackArgs;
+};
+
+class CustomElementConstructor final : public CallbackFunction
+{
+public:
+ explicit CustomElementConstructor(CallbackFunction* aOther)
+ : CallbackFunction(aOther)
+ {
+ MOZ_ASSERT(JS::IsConstructor(mCallback));
+ }
+
+ already_AddRefed<Element> Construct(const char* aExecutionReason, ErrorResult& aRv);
};
// Each custom element has an associated callback queue and an element is
@@ -70,63 +96,299 @@ struct CustomElementData
{
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
+ // https://dom.spec.whatwg.org/#concept-element-custom-element-state
+ // CustomElementData is only created on the element which is a custom element
+ // or an upgrade candidate, so the state of an element without
+ // CustomElementData is "uncustomized".
+ enum class State {
+ eUndefined,
+ eFailed,
+ eCustom
+ };
+
explicit CustomElementData(nsIAtom* aType);
- // Objects in this array are transient and empty after each microtask
- // checkpoint.
- nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
- // Custom element type, for <button is="x-button"> or <x-button>
- // this would be x-button.
- nsCOMPtr<nsIAtom> mType;
- // The callback that is next to be processed upon calling RunCallbackQueue.
- int32_t mCurrentCallback;
- // Element is being created flag as described in the custom elements spec.
- bool mElementIsBeingCreated;
- // Flag to determine if the created callback has been invoked, thus it
- // determines if other callbacks can be enqueued.
- bool mCreatedCallbackInvoked;
- // The microtask level associated with the callbacks in the callback queue,
- // it is used to determine if a new queue needs to be pushed onto the
- // processing stack.
- int32_t mAssociatedMicroTask;
-
- // Empties the callback queue.
- void RunCallbackQueue();
+ CustomElementData(nsIAtom* aType, State aState);
+
+ // Custom element state as described in the custom element spec.
+ State mState;
+ // custom element reaction queue as described in the custom element spec.
+ // There is 1 reaction in reaction queue, when 1) it becomes disconnected,
+ // 2) it’s adopted into a new document, 3) its attributes are changed,
+ // appended, removed, or replaced.
+ // There are 3 reactions in reaction queue when doing upgrade operation,
+ // e.g., create an element, insert a node.
+ AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
+
+ void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
+ CustomElementDefinition* GetCustomElementDefinition();
+ nsIAtom* GetCustomElementType();
+
+ void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
+ void Unlink();
private:
virtual ~CustomElementData() {}
+
+ // Custom element type, for <button is="x-button"> or <x-button>
+ // this would be x-button.
+ RefPtr<nsIAtom> mType;
+ RefPtr<CustomElementDefinition> mCustomElementDefinition;
};
+#define ALEADY_CONSTRUCTED_MARKER nullptr
+
// The required information for a custom element as defined in:
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-definition
struct CustomElementDefinition
{
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
+ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
+
CustomElementDefinition(nsIAtom* aType,
nsIAtom* aLocalName,
- JSObject* aConstructor,
+ Function* aConstructor,
+ nsCOMArray<nsIAtom>&& aObservedAttributes,
JSObject* aPrototype,
mozilla::dom::LifecycleCallbacks* aCallbacks,
uint32_t aDocOrder);
- // The type (name) for this custom element.
+ // The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
+ // this would be x-foo.
nsCOMPtr<nsIAtom> mType;
// The localname to (e.g. <button is=type> -- this would be button).
nsCOMPtr<nsIAtom> mLocalName;
// The custom element constructor.
- JS::Heap<JSObject *> mConstructor;
+ RefPtr<CustomElementConstructor> mConstructor;
+
+ // The list of attributes that this custom element observes.
+ nsCOMArray<nsIAtom> mObservedAttributes;
// The prototype to use for new custom elements of this type.
JS::Heap<JSObject *> mPrototype;
// The lifecycle callbacks to call for this custom element.
- nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
+ UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
- // A construction stack.
- // TODO: Bug 1287348 - Implement construction stack for upgrading an element
+ // A construction stack. Use nullptr to represent an "already constructed marker".
+ nsTArray<RefPtr<nsGenericHTMLElement>> mConstructionStack;
// The document custom element order.
uint32_t mDocOrder;
+
+ bool IsCustomBuiltIn()
+ {
+ return mType != mLocalName;
+ }
+
+ bool IsInObservedAttributeList(nsIAtom* aName)
+ {
+ if (mObservedAttributes.IsEmpty()) {
+ return false;
+ }
+
+ return mObservedAttributes.Contains(aName);
+ }
+
+private:
+ ~CustomElementDefinition() {}
+};
+
+class CustomElementReaction
+{
+public:
+ virtual ~CustomElementReaction() = default;
+ virtual void Invoke(Element* aElement, ErrorResult& aRv) = 0;
+ virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const
+ {
+ }
+
+#if DEBUG
+ bool IsUpgradeReaction()
+ {
+ return mIsUpgradeReaction;
+ }
+
+protected:
+ bool mIsUpgradeReaction = false;
+#endif
+};
+
+class CustomElementUpgradeReaction final : public CustomElementReaction
+{
+public:
+ explicit CustomElementUpgradeReaction(CustomElementDefinition* aDefinition)
+ : mDefinition(aDefinition)
+ {
+#if DEBUG
+ mIsUpgradeReaction = true;
+#endif
+ }
+
+private:
+ virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
+
+ CustomElementDefinition* mDefinition;
+};
+
+class CustomElementCallbackReaction final : public CustomElementReaction
+{
+ public:
+ explicit CustomElementCallbackReaction(UniquePtr<CustomElementCallback> aCustomElementCallback)
+ : mCustomElementCallback(Move(aCustomElementCallback))
+ {
+ }
+
+ virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
+ {
+ mCustomElementCallback->Traverse(aCb);
+ }
+
+ private:
+ virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
+ UniquePtr<CustomElementCallback> mCustomElementCallback;
+};
+
+// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
+class CustomElementReactionsStack
+{
+public:
+ NS_INLINE_DECL_REFCOUNTING(CustomElementReactionsStack)
+
+ CustomElementReactionsStack()
+ : mIsBackupQueueProcessing(false)
+ , mRecursionDepth(0)
+ , mIsElementQueuePushedForCurrentRecursionDepth(false)
+ {
+ }
+
+ // Hold a strong reference of Element so that it does not get cycle collected
+ // before the reactions in its reaction queue are invoked.
+ // The element reaction queues are stored in CustomElementData.
+ // We need to lookup ElementReactionQueueMap again to get relevant reaction queue.
+ // The choice of 1 for the auto size here is based on gut feeling.
+ typedef AutoTArray<RefPtr<Element>, 1> ElementQueue;
+
+ /**
+ * Enqueue a custom element upgrade reaction
+ * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction
+ */
+ void EnqueueUpgradeReaction(Element* aElement,
+ CustomElementDefinition* aDefinition);
+
+ /**
+ * Enqueue a custom element callback reaction
+ * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction
+ */
+ void EnqueueCallbackReaction(Element* aElement,
+ UniquePtr<CustomElementCallback> aCustomElementCallback);
+
+ /**
+ * [CEReactions] Before executing the algorithm's steps.
+ * Increase the current recursion depth, and the element queue is pushed
+ * lazily when we really enqueue reactions.
+ *
+ * @return true if the element queue is pushed for "previous" recursion depth.
+ */
+ bool EnterCEReactions()
+ {
+ bool temp = mIsElementQueuePushedForCurrentRecursionDepth;
+ mRecursionDepth++;
+ // The is-element-queue-pushed flag is initially false when entering a new
+ // recursion level. The original value will be cached in AutoCEReaction
+ // and restored after leaving this recursion level.
+ mIsElementQueuePushedForCurrentRecursionDepth = false;
+ return temp;
+ }
+
+ /**
+ * [CEReactions] After executing the algorithm's steps.
+ * Pop and invoke the element queue if it is created and pushed for current
+ * recursion depth, then decrease the current recursion depth.
+ *
+ * @param aCx JSContext used for handling exception thrown by algorithm's
+ * steps, this could be a nullptr.
+ * aWasElementQueuePushed used for restoring status after leaving
+ * current recursion.
+ */
+ void LeaveCEReactions(JSContext* aCx, bool aWasElementQueuePushed)
+ {
+ MOZ_ASSERT(mRecursionDepth);
+
+ if (mIsElementQueuePushedForCurrentRecursionDepth) {
+ Maybe<JS::AutoSaveExceptionState> ases;
+ if (aCx) {
+ ases.emplace(aCx);
+ }
+ PopAndInvokeElementQueue();
+ }
+ mRecursionDepth--;
+ // Restore the is-element-queue-pushed flag cached in AutoCEReaction when
+ // leaving the recursion level.
+ mIsElementQueuePushedForCurrentRecursionDepth = aWasElementQueuePushed;
+
+ MOZ_ASSERT_IF(!mRecursionDepth, mReactionsStack.IsEmpty());
+ }
+
+private:
+ ~CustomElementReactionsStack() {};
+
+ /**
+ * Push a new element queue onto the custom element reactions stack.
+ */
+ void CreateAndPushElementQueue();
+
+ /**
+ * Pop the element queue from the custom element reactions stack, and invoke
+ * custom element reactions in that queue.
+ */
+ void PopAndInvokeElementQueue();
+
+ // The choice of 8 for the auto size here is based on gut feeling.
+ AutoTArray<UniquePtr<ElementQueue>, 8> mReactionsStack;
+ ElementQueue mBackupQueue;
+ // https://html.spec.whatwg.org/#enqueue-an-element-on-the-appropriate-element-queue
+ bool mIsBackupQueueProcessing;
+
+ void InvokeBackupQueue();
+
+ /**
+ * Invoke custom element reactions
+ * https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-element-reactions
+ */
+ void InvokeReactions(ElementQueue* aElementQueue, nsIGlobalObject* aGlobal);
+
+ void Enqueue(Element* aElement, CustomElementReaction* aReaction);
+
+ // Current [CEReactions] recursion depth.
+ uint32_t mRecursionDepth;
+ // True if the element queue is pushed into reaction stack for current
+ // recursion depth. This will be cached in AutoCEReaction when entering a new
+ // CEReaction recursion and restored after leaving the recursion.
+ bool mIsElementQueuePushedForCurrentRecursionDepth;
+
+private:
+ class BackupQueueMicroTask final : public mozilla::MicroTaskRunnable {
+ public:
+ explicit BackupQueueMicroTask(CustomElementReactionsStack* aReactionStack)
+ : MicroTaskRunnable()
+ , mReactionStack(aReactionStack)
+ {
+ MOZ_ASSERT(!mReactionStack->mIsBackupQueueProcessing,
+ "mIsBackupQueueProcessing should be initially false");
+ mReactionStack->mIsBackupQueueProcessing = true;
+ }
+
+ virtual void Run(AutoSlowOperation& aAso) override
+ {
+ mReactionStack->InvokeBackupQueue();
+ mReactionStack->mIsBackupQueueProcessing = false;
+ }
+
+ private:
+ RefPtr<CustomElementReactionsStack> mReactionStack;
+ };
};
class CustomElementRegistry final : public nsISupports,
@@ -142,36 +404,33 @@ public:
public:
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
JSObject* aObject = nullptr);
- static already_AddRefed<CustomElementRegistry> Create(nsPIDOMWindowInner* aWindow);
- static void ProcessTopElementQueue();
- static void XPCOMShutdown();
+ explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
/**
* Looking up a custom element definition.
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
*/
CustomElementDefinition* LookupCustomElementDefinition(
- const nsAString& aLocalName, const nsAString* aIs = nullptr) const;
+ nsIAtom* aNameAtom, nsIAtom* aTypeAtom) const;
- /**
- * Enqueue created callback or register upgrade candidate for
- * newly created custom elements, possibly extending an existing type.
- * ex. <x-button>, <button is="x-button> (type extension)
- */
- void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension);
+ CustomElementDefinition* LookupCustomElementDefinition(
+ JSContext* aCx, JSObject *aConstructor) const;
- void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
- Element* aCustomElement,
- LifecycleCallbackArgs* aArgs,
- CustomElementDefinition* aDefinition);
+ static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
+ Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition);
void GetCustomPrototype(nsIAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype);
-private:
- explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
- ~CustomElementRegistry();
+ /**
+ * Upgrade an element.
+ * https://html.spec.whatwg.org/multipage/scripting.html#upgrades
+ */
+ static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
/**
* Registers an unresolved custom element that is a candidate for
@@ -184,23 +443,48 @@ private:
void RegisterUnresolvedElement(Element* aElement,
nsIAtom* aTypeName = nullptr);
- void UpgradeCandidates(JSContext* aCx,
- nsIAtom* aKey,
- CustomElementDefinition* aDefinition);
+ /**
+ * Unregister an unresolved custom element that is a candidate for
+ * upgrade when a custom element is removed from tree.
+ */
+ void UnregisterUnresolvedElement(Element* aElement,
+ nsIAtom* aTypeName = nullptr);
+private:
+ ~CustomElementRegistry();
+
+ static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
+ nsIDocument::ElementCallbackType aType, Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition);
- typedef nsClassHashtable<nsISupportsHashKey, CustomElementDefinition>
+ void UpgradeCandidates(nsIAtom* aKey,
+ CustomElementDefinition* aDefinition,
+ ErrorResult& aRv);
+
+ typedef nsRefPtrHashtable<nsISupportsHashKey, CustomElementDefinition>
DefinitionMap;
typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
CandidateMap;
+ typedef JS::GCHashMap<JS::Heap<JSObject*>,
+ nsCOMPtr<nsIAtom>,
+ js::MovableCellHasher<JS::Heap<JSObject*>>,
+ js::SystemAllocPolicy> ConstructorMap;
// Hashtable for custom element definitions in web components.
// Custom prototypes are stored in the compartment where
// registerElement was called.
DefinitionMap mCustomDefinitions;
+ // Hashtable for looking up definitions by using constructor as key.
+ // Custom elements' name are stored here and we need to lookup
+ // mCustomDefinitions again to get definitions.
+ ConstructorMap mConstructors;
+
typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
WhenDefinedPromiseMap;
WhenDefinedPromiseMap mWhenDefinedPromiseMap;
+
// The "upgrade candidates map" from the web components spec. Maps from a
// namespace id and local name to a list of elements to upgrade if that
// element is registered as a custom element.
@@ -208,14 +492,6 @@ private:
nsCOMPtr<nsPIDOMWindowInner> mWindow;
- // Array representing the processing stack in the custom elements
- // specification. The processing stack is conceptually a stack of
- // element queues. Each queue is represented by a sequence of
- // CustomElementData in this array, separated by nullptr that
- // represent the boundaries of the items in the stack. The first
- // queue in the stack is the base element queue.
- static mozilla::Maybe<nsTArray<RefPtr<CustomElementData>>> sProcessingStack;
-
// It is used to prevent reentrant invocations of element definition.
bool mIsCustomDefinitionRunning;
@@ -252,6 +528,31 @@ public:
already_AddRefed<Promise> WhenDefined(const nsAString& aName, ErrorResult& aRv);
};
+class MOZ_RAII AutoCEReaction final {
+ public:
+ // JSContext is allowed to be a nullptr if we are guaranteeing that we're
+ // not doing something that might throw but not finish reporting a JS
+ // exception during the lifetime of the AutoCEReaction.
+ AutoCEReaction(CustomElementReactionsStack* aReactionsStack, JSContext* aCx)
+ : mReactionsStack(aReactionsStack)
+ , mCx(aCx)
+ {
+ mIsElementQueuePushedForPreviousRecursionDepth =
+ mReactionsStack->EnterCEReactions();
+ }
+
+ ~AutoCEReaction()
+ {
+ mReactionsStack->LeaveCEReactions(
+ mCx, mIsElementQueuePushedForPreviousRecursionDepth);
+ }
+
+ private:
+ RefPtr<CustomElementReactionsStack> mReactionsStack;
+ JSContext* mCx;
+ bool mIsElementQueuePushedForPreviousRecursionDepth;
+};
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/base/DocGroup.cpp b/dom/base/DocGroup.cpp
index 226879985..30c058f0c 100644
--- a/dom/base/DocGroup.cpp
+++ b/dom/base/DocGroup.cpp
@@ -46,6 +46,9 @@ DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
DocGroup::~DocGroup()
{
MOZ_ASSERT(mDocuments.IsEmpty());
+ if (!NS_IsMainThread()) {
+ NS_ReleaseOnMainThread(mReactionsStack.forget());
+ }
mTabGroup->mDocGroups.RemoveEntry(mKey);
}
diff --git a/dom/base/DocGroup.h b/dom/base/DocGroup.h
index f4f7ac8ad..5b8f627cc 100644
--- a/dom/base/DocGroup.h
+++ b/dom/base/DocGroup.h
@@ -14,6 +14,7 @@
#include "nsString.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/dom/CustomElementRegistry.h"
namespace mozilla {
namespace dom {
@@ -52,6 +53,14 @@ public:
{
return mTabGroup;
}
+ mozilla::dom::CustomElementReactionsStack* CustomElementReactionsStack()
+ {
+ if (!mReactionsStack) {
+ mReactionsStack = new mozilla::dom::CustomElementReactionsStack();
+ }
+
+ return mReactionsStack;
+ }
void RemoveDocument(nsIDocument* aWindow);
// Iterators for iterating over every document within the DocGroup
@@ -71,6 +80,7 @@ private:
nsCString mKey;
RefPtr<TabGroup> mTabGroup;
nsTArray<nsIDocument*> mDocuments;
+ RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
};
} // namespace dom
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 0054f4800..c8467e036 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -479,9 +479,13 @@ Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
if (data) {
// If this is a registered custom element then fix the prototype.
nsContentUtils::GetCustomPrototype(OwnerDoc(), NodeInfo()->NamespaceID(),
- data->mType, &customProto);
+ data->GetCustomElementType(), &customProto);
if (customProto &&
NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(customProto))) {
+ // The custom element prototype could be in different compartment.
+ if (!JS_WrapObject(aCx, &customProto)) {
+ return nullptr;
+ }
// Just go ahead and create with the right proto up front. Set
// customProto to null to flag that we don't need to do any post-facto
// proto fixups here.
@@ -1595,7 +1599,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
#endif
{
if (aBindingParent) {
- nsDOMSlots *slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
}
@@ -1618,7 +1622,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
}
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
if (parentContainingShadow) {
- DOMSlots()->mContainingShadow = parentContainingShadow;
+ ExtendedDOMSlots()->mContainingShadow = parentContainingShadow;
}
}
@@ -1684,14 +1688,17 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
SetSubtreeRootPointer(aParent->SubtreeRoot());
}
- nsIDocument* composedDoc = GetComposedDoc();
- if (composedDoc) {
- // Attached callback must be enqueued whenever custom element is inserted into a
- // document and this document has a browsing context.
- if (GetCustomElementData() && composedDoc->GetDocShell()) {
- // Enqueue an attached callback for the custom element.
- nsContentUtils::EnqueueLifecycleCallback(
- composedDoc, nsIDocument::eAttached, this);
+ if (CustomElementRegistry::IsCustomElementEnabled() && IsInComposedDoc()) {
+ // Connected callback must be enqueued whenever a custom element becomes
+ // connected.
+ CustomElementData* data = GetCustomElementData();
+ if (data) {
+ if (data->mState == CustomElementData::State::eCustom) {
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, this);
+ } else {
+ // Step 7.7.2.2 https://dom.spec.whatwg.org/#concept-node-insert
+ nsContentUtils::TryToUpgradeElement(this);
+ }
}
}
@@ -1986,12 +1993,21 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
document->ClearBoxObjectFor(this);
- // Detached must be enqueued whenever custom element is removed from
- // the document and this document has a browsing context.
- if (GetCustomElementData() && document->GetDocShell()) {
- // Enqueue a detached callback for the custom element.
- nsContentUtils::EnqueueLifecycleCallback(
- document, nsIDocument::eDetached, this);
+ // Disconnected must be enqueued whenever a connected custom element becomes
+ // disconnected.
+ if (CustomElementRegistry::IsCustomElementEnabled()) {
+ CustomElementData* data = GetCustomElementData();
+ if (data) {
+ if (data->mState == CustomElementData::State::eCustom) {
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eDisconnected,
+ this);
+ } else {
+ // Remove an unresolved custom element that is a candidate for
+ // upgrade when a custom element is disconnected.
+ // We will make sure it's shadow-including tree order in bug 1326028.
+ nsContentUtils::UnregisterUnresolvedElement(this);
+ }
+ }
}
}
@@ -2007,7 +2023,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
}
#endif
- nsDOMSlots* slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
if (clearBindingParent) {
slots->mBindingParent = nullptr;
@@ -2055,7 +2071,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
nsICSSDeclaration*
Element::GetSMILOverrideStyle()
{
- Element::nsDOMSlots *slots = DOMSlots();
+ Element::nsExtendedDOMSlots* slots = ExtendedDOMSlots();
if (!slots->mSMILOverrideStyle) {
slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
@@ -2067,7 +2083,7 @@ Element::GetSMILOverrideStyle()
DeclarationBlock*
Element::GetSMILOverrideStyleDeclaration()
{
- Element::nsDOMSlots *slots = GetExistingDOMSlots();
+ Element::nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
}
@@ -2075,7 +2091,7 @@ nsresult
Element::SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
bool aNotify)
{
- Element::nsDOMSlots *slots = DOMSlots();
+ Element::nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mSMILOverrideStyleDeclaration = aDeclaration;
@@ -2586,19 +2602,32 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
UpdateState(aNotify);
- nsIDocument* ownerDoc = OwnerDoc();
- if (ownerDoc && GetCustomElementData()) {
- nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
- nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
- LifecycleCallbackArgs args = {
- nsDependentAtomString(aName),
- aModType == nsIDOMMutationEvent::ADDITION ?
- NullString() : nsDependentAtomString(oldValueAtom),
- nsDependentAtomString(newValueAtom)
- };
-
- nsContentUtils::EnqueueLifecycleCallback(
- ownerDoc, nsIDocument::eAttributeChanged, this, &args);
+ if (CustomElementRegistry::IsCustomElementEnabled()) {
+ if (CustomElementData* data = GetCustomElementData()) {
+ if (CustomElementDefinition* definition =
+ nsContentUtils::GetElementDefinitionIfObservingAttr(this,
+ data->GetCustomElementType(),
+ aName)) {
+ MOZ_ASSERT(data->mState == CustomElementData::State::eCustom,
+ "AttributeChanged callback should fire only if "
+ "custom element state is custom");
+ nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
+ nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
+ nsAutoString ns;
+ nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
+
+ LifecycleCallbackArgs args = {
+ nsDependentAtomString(aName),
+ aModType == nsIDOMMutationEvent::ADDITION ?
+ NullString() : nsDependentAtomString(oldValueAtom),
+ nsDependentAtomString(newValueAtom),
+ (ns.IsEmpty() ? NullString() : ns)
+ };
+
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
+ this, &args, nullptr, definition);
+ }
+ }
}
if (aCallAfterSetAttr) {
@@ -2843,17 +2872,30 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
UpdateState(aNotify);
- nsIDocument* ownerDoc = OwnerDoc();
- if (ownerDoc && GetCustomElementData()) {
- nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
- LifecycleCallbackArgs args = {
- nsDependentAtomString(aName),
- nsDependentAtomString(oldValueAtom),
- NullString()
- };
-
- nsContentUtils::EnqueueLifecycleCallback(
- ownerDoc, nsIDocument::eAttributeChanged, this, &args);
+ if (CustomElementRegistry::IsCustomElementEnabled()) {
+ if (CustomElementData* data = GetCustomElementData()) {
+ if (CustomElementDefinition* definition =
+ nsContentUtils::GetElementDefinitionIfObservingAttr(this,
+ data->GetCustomElementType(),
+ aName)) {
+ MOZ_ASSERT(data->mState == CustomElementData::State::eCustom,
+ "AttributeChanged callback should fire only if "
+ "custom element state is custom");
+ nsAutoString ns;
+ nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
+
+ nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
+ LifecycleCallbackArgs args = {
+ nsDependentAtomString(aName),
+ nsDependentAtomString(oldValueAtom),
+ NullString(),
+ (ns.IsEmpty() ? NullString() : ns)
+ };
+
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
+ this, &args, nullptr, definition);
+ }
+ }
}
if (aNotify) {
@@ -3988,7 +4030,7 @@ Element::ClearDataset()
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers()
{
- nsDOMSlots* slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
return &slots->mRegisteredIntersectionObservers;
}
@@ -4037,3 +4079,31 @@ Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32
}
return false;
}
+
+void
+Element::SetCustomElementData(CustomElementData* aData)
+{
+ nsExtendedDOMSlots *slots = ExtendedDOMSlots();
+ MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
+ slots->mCustomElementData = aData;
+}
+
+CustomElementDefinition*
+Element::GetCustomElementDefinition() const
+{
+ CustomElementData* data = GetCustomElementData();
+ if (!data) {
+ return nullptr;
+ }
+
+ return data->GetCustomElementDefinition();
+}
+
+void
+Element::SetCustomElementDefinition(CustomElementDefinition* aDefinition)
+{
+ CustomElementData* data = GetCustomElementData();
+ MOZ_ASSERT(data);
+
+ data->SetCustomElementDefinition(aDefinition);
+}
diff --git a/dom/base/Element.h b/dom/base/Element.h
index ce84b74fb..782004703 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -390,6 +390,45 @@ public:
Directionality GetComputedDirectionality() const;
+ /**
+ * Gets the custom element data used by web components custom element.
+ * Custom element data is created at the first attempt to enqueue a callback.
+ *
+ * @return The custom element data or null if none.
+ */
+ inline CustomElementData* GetCustomElementData() const
+ {
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
+ if (slots) {
+ return slots->mCustomElementData;
+ }
+ return nullptr;
+ }
+
+ /**
+ * Sets the custom element data, ownership of the
+ * callback data is taken by this element.
+ *
+ * @param aData The custom element data.
+ */
+ void SetCustomElementData(CustomElementData* aData);
+
+ /**
+ * Gets the custom element definition used by web components custom element.
+ *
+ * @return The custom element definition or null if element is not a custom
+ * element or custom element is not defined yet.
+ */
+ CustomElementDefinition* GetCustomElementDefinition() const;
+
+ /**
+ * Sets the custom element definition, called when custom element is created
+ * or upgraded.
+ *
+ * @param aDefinition The custom element definition.
+ */
+ void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
+
protected:
/**
* Method to get the _intrinsic_ content state of this element. This is the
@@ -814,7 +853,7 @@ public:
ShadowRoot *FastGetShadowRoot() const
{
- nsDOMSlots* slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mShadowRoot.get() : nullptr;
}
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 9106778df..526c3c9d4 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -530,8 +530,7 @@ nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
//----------------------------------------------------------------------
FragmentOrElement::nsDOMSlots::nsDOMSlots()
: nsINode::nsSlots(),
- mDataset(nullptr),
- mBindingParent(nullptr)
+ mDataset(nullptr)
{
}
@@ -543,84 +542,104 @@ FragmentOrElement::nsDOMSlots::~nsDOMSlots()
}
void
-FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL)
+FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
cb.NoteXPCOMChild(mStyle.get());
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
- cb.NoteXPCOMChild(mSMILOverrideStyle.get());
-
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
cb.NoteXPCOMChild(mAttributeMap.get());
- if (aIsXUL) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
- cb.NoteXPCOMChild(mControllers);
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
+ cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
+ cb.NoteXPCOMChild(mClassList.get());
+
+ if (!mExtendedSlots) {
+ return;
}
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLBinding");
- cb.NoteNativeChild(mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mSMILOverrideStyle");
+ cb.NoteXPCOMChild(mExtendedSlots->mSMILOverrideStyle.get());
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
- cb.NoteXPCOMChild(mXBLInsertionParent.get());
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mControllers");
+ cb.NoteXPCOMChild(mExtendedSlots->mControllers);
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mShadowRoot");
- cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mLabelsList");
+ cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*,mExtendedSlots-> mLabelsList));
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
- cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mShadowRoot");
+ cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mShadowRoot));
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
- cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mContainingShadow");
+ cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mContainingShadow));
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
- cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLBinding");
+ cb.NoteNativeChild(mExtendedSlots->mXBLBinding,
+ NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
- cb.NoteXPCOMChild(mClassList.get());
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLInsertionParent");
+ cb.NoteXPCOMChild(mExtendedSlots->mXBLInsertionParent.get());
- if (mCustomElementData) {
- for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) {
- mCustomElementData->mCallbackQueue[i]->Traverse(cb);
- }
+ if (mExtendedSlots->mCustomElementData) {
+ mExtendedSlots->mCustomElementData->Traverse(cb);
}
- for (auto iter = mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter();
+ !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mRegisteredIntersectionObservers[i]");
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+ "mExtendedSlots->mRegisteredIntersectionObservers[i]");
cb.NoteXPCOMChild(observer);
}
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mFrameLoaderOrOpener");
+ cb.NoteXPCOMChild(mExtendedSlots->mFrameLoaderOrOpener);
}
void
-FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
+FragmentOrElement::nsDOMSlots::Unlink()
{
mStyle = nullptr;
- mSMILOverrideStyle = nullptr;
if (mAttributeMap) {
mAttributeMap->DropReference();
mAttributeMap = nullptr;
}
- if (aIsXUL)
- NS_IF_RELEASE(mControllers);
-
- MOZ_ASSERT(!mXBLBinding);
-
- mXBLInsertionParent = nullptr;
- mShadowRoot = nullptr;
- mContainingShadow = nullptr;
mChildrenList = nullptr;
- mLabelsList = nullptr;
- mCustomElementData = nullptr;
mClassList = nullptr;
- mRegisteredIntersectionObservers.Clear();
+
+ if (!mExtendedSlots) {
+ return;
+ }
+
+ mExtendedSlots->mSMILOverrideStyle = nullptr;
+ mExtendedSlots->mControllers = nullptr;
+ mExtendedSlots->mLabelsList = nullptr;
+ mExtendedSlots->mShadowRoot = nullptr;
+ mExtendedSlots->mContainingShadow = nullptr;
+ MOZ_ASSERT(!(mExtendedSlots->mXBLBinding));
+ mExtendedSlots->mXBLInsertionParent = nullptr;
+ if (mExtendedSlots->mCustomElementData) {
+ mExtendedSlots->mCustomElementData->Unlink();
+ mExtendedSlots->mCustomElementData = nullptr;
+ }
+ mExtendedSlots->mRegisteredIntersectionObservers.Clear();
+ nsCOMPtr<nsIFrameLoader> frameLoader =
+ do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
+ if (frameLoader) {
+ static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
+ }
+ mExtendedSlots->mFrameLoaderOrOpener = nullptr;
}
size_t
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
+ if (mExtendedSlots) {
+ n += aMallocSizeOf(mExtendedSlots.get());
+ }
if (mAttributeMap) {
n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf);
@@ -641,6 +660,19 @@ FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) c
return n;
}
+FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots()
+ : mBindingParent(nullptr)
+{
+}
+
+FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
+{
+ nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
+ if (frameLoader) {
+ static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
+ }
+}
+
FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsIContent(aNodeInfo)
{
@@ -962,7 +994,7 @@ FragmentOrElement::IsLink(nsIURI** aURI) const
nsIContent*
FragmentOrElement::GetBindingParent() const
{
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mBindingParent;
@@ -974,7 +1006,7 @@ nsXBLBinding*
FragmentOrElement::GetXBLBinding() const
{
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mXBLBinding;
}
@@ -1009,11 +1041,11 @@ FragmentOrElement::SetXBLBinding(nsXBLBinding* aBinding,
if (aBinding) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
- nsDOMSlots *slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mXBLBinding = aBinding;
bindingManager->AddBoundContent(this);
} else {
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
slots->mXBLBinding = nullptr;
}
@@ -1028,7 +1060,7 @@ nsIContent*
FragmentOrElement::GetXBLInsertionParent() const
{
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mXBLInsertionParent;
}
@@ -1040,7 +1072,7 @@ FragmentOrElement::GetXBLInsertionParent() const
ShadowRoot*
FragmentOrElement::GetContainingShadow() const
{
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mContainingShadow;
}
@@ -1050,21 +1082,21 @@ FragmentOrElement::GetContainingShadow() const
void
FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot)
{
- nsDOMSlots *slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mShadowRoot = aShadowRoot;
}
nsTArray<nsIContent*>&
FragmentOrElement::DestInsertionPoints()
{
- nsDOMSlots *slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
return slots->mDestInsertionPoints;
}
nsTArray<nsIContent*>*
FragmentOrElement::GetExistingDestInsertionPoints() const
{
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return &slots->mDestInsertionPoints;
}
@@ -1075,35 +1107,17 @@ void
FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
{
if (aContent) {
- nsDOMSlots *slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
slots->mXBLInsertionParent = aContent;
} else {
- nsDOMSlots *slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
slots->mXBLInsertionParent = nullptr;
}
}
}
-CustomElementData*
-FragmentOrElement::GetCustomElementData() const
-{
- nsDOMSlots *slots = GetExistingDOMSlots();
- if (slots) {
- return slots->mCustomElementData;
- }
- return nullptr;
-}
-
-void
-FragmentOrElement::SetCustomElementData(CustomElementData* aData)
-{
- nsDOMSlots *slots = DOMSlots();
- MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
- slots->mCustomElementData = aData;
-}
-
nsresult
FragmentOrElement::InsertChildAt(nsIContent* aKid,
uint32_t aIndex,
@@ -1366,14 +1380,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
- if (tmp->IsElement()) {
+ if (slots->mExtendedSlots && tmp->IsElement()) {
Element* elem = tmp->AsElement();
- for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ for (auto iter = slots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
+ !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem);
}
}
- slots->Unlink(tmp->IsXULElement());
+ slots->Unlink();
}
}
@@ -1938,7 +1953,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
- slots->Traverse(cb, tmp->IsXULElement());
+ slots->Traverse(cb);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
diff --git a/dom/base/FragmentOrElement.h b/dom/base/FragmentOrElement.h
index f0cc29f22..4edd88908 100644
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -15,6 +15,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
+#include "mozilla/UniquePtr.h"
#include "nsAttrAndChildArray.h" // member
#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
#include "nsIContent.h" // base class
@@ -37,6 +38,7 @@ class nsIURI;
namespace mozilla {
class DeclarationBlock;
namespace dom {
+struct CustomElementData;
class DOMIntersectionObserver;
class Element;
} // namespace dom
@@ -159,9 +161,6 @@ public:
virtual void SetXBLInsertionParent(nsIContent* aContent) override;
virtual bool IsLink(nsIURI** aURI) const override;
- virtual CustomElementData *GetCustomElementData() const override;
- virtual void SetCustomElementData(CustomElementData* aData) override;
-
virtual void DestroyContent() override;
virtual void SaveSubtreeState() override;
@@ -241,8 +240,6 @@ protected:
nsresult CopyInnerTo(FragmentOrElement* aDest);
public:
- // Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
- // otherwise nsXULElement::nsXULSlots doesn't compile.
/**
* There are a set of DOM- and scripting-specific instance variables
* that may only be instantiated when a content object is accessed
@@ -251,29 +248,13 @@ public:
* in a side structure that's only allocated when the content is
* accessed through the DOM.
*/
- class nsDOMSlots : public nsINode::nsSlots
+
+ class nsExtendedDOMSlots
{
public:
- nsDOMSlots();
- virtual ~nsDOMSlots();
-
- void Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL);
- void Unlink(bool aIsXUL);
-
- size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
-
- /**
- * The .style attribute (an interface that forwards to the actual
- * style rules)
- * @see nsGenericHTMLElement::GetStyle
- */
- nsCOMPtr<nsICSSDeclaration> mStyle;
+ nsExtendedDOMSlots();
- /**
- * The .dataset attribute.
- * @see nsGenericHTMLElement::GetDataset
- */
- nsDOMStringMap* mDataset; // [Weak]
+ ~nsExtendedDOMSlots();
/**
* SMIL Overridde style rules (for SMIL animation of CSS properties)
@@ -287,35 +268,17 @@ public:
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
/**
- * An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
- * @see FragmentOrElement::GetAttributes
- */
- RefPtr<nsDOMAttributeMap> mAttributeMap;
-
- union {
- /**
- * The nearest enclosing content node with a binding that created us.
- * @see FragmentOrElement::GetBindingParent
- */
- nsIContent* mBindingParent; // [Weak]
-
- /**
- * The controllers of the XUL Element.
- */
- nsIControllers* mControllers; // [OWNER]
- };
+ * The nearest enclosing content node with a binding that created us.
+ * @see FragmentOrElement::GetBindingParent
+ */
+ nsIContent* mBindingParent; // [Weak]
/**
- * An object implementing the .children property for this element.
- */
- RefPtr<nsContentList> mChildrenList;
+ * The controllers of the XUL Element.
+ */
+ nsCOMPtr<nsIControllers> mControllers;
/**
- * An object implementing the .classList property for this element.
- */
- RefPtr<nsDOMTokenList> mClassList;
-
- /*
* An object implementing the .labels property for this element.
*/
RefPtr<nsLabelsNodeList> mLabelsList;
@@ -356,6 +319,55 @@ public:
*/
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
mRegisteredIntersectionObservers;
+
+ /**
+ * For XUL to hold either frameloader or opener.
+ */
+ nsCOMPtr<nsISupports> mFrameLoaderOrOpener;
+
+ };
+
+ class nsDOMSlots : public nsINode::nsSlots
+ {
+ public:
+ nsDOMSlots();
+ virtual ~nsDOMSlots();
+
+ void Traverse(nsCycleCollectionTraversalCallback &cb);
+ void Unlink();
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
+ /**
+ * The .style attribute (an interface that forwards to the actual
+ * style rules)
+ * @see nsGenericHTMLElement::GetStyle
+ */
+ nsCOMPtr<nsICSSDeclaration> mStyle;
+
+ /**
+ * The .dataset attribute.
+ * @see nsGenericHTMLElement::GetDataset
+ */
+ nsDOMStringMap* mDataset; // [Weak]
+
+ /**
+ * An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
+ * @see FragmentOrElement::GetAttributes
+ */
+ RefPtr<nsDOMAttributeMap> mAttributeMap;
+
+ /**
+ * An object implementing the .children property for this element.
+ */
+ RefPtr<nsContentList> mChildrenList;
+
+ /**
+ * An object implementing the .classList property for this element.
+ */
+ RefPtr<nsDOMTokenList> mClassList;
+
+ mozilla::UniquePtr<nsExtendedDOMSlots> mExtendedSlots;
};
protected:
@@ -375,6 +387,26 @@ protected:
return static_cast<nsDOMSlots*>(GetExistingSlots());
}
+ nsExtendedDOMSlots* ExtendedDOMSlots()
+ {
+ nsDOMSlots* slots = DOMSlots();
+ if (!slots->mExtendedSlots) {
+ slots->mExtendedSlots = MakeUnique<nsExtendedDOMSlots>();
+ }
+
+ return slots->mExtendedSlots.get();
+ }
+
+ nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
+ {
+ nsDOMSlots* slots = GetExistingDOMSlots();
+ if (slots) {
+ return slots->mExtendedSlots.get();
+ }
+
+ return nullptr;
+ }
+
/**
* Calls SetIsElementInStyleScopeFlagOnSubtree for each shadow tree attached
* to this node, which is assumed to be an Element.
diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp
index 9540754f7..831987a96 100644
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -75,8 +75,8 @@ ShadowRoot::ShadowRoot(nsIContent* aContent,
SetFlags(NODE_IS_IN_SHADOW_TREE);
- DOMSlots()->mBindingParent = aContent;
- DOMSlots()->mContainingShadow = this;
+ ExtendedDOMSlots()->mBindingParent = aContent;
+ ExtendedDOMSlots()->mContainingShadow = this;
// Add the ShadowRoot as a mutation observer on the host to watch
// for mutations because the insertion points in this ShadowRoot
diff --git a/dom/base/crashtests/1341693.html b/dom/base/crashtests/1341693.html
new file mode 100644
index 000000000..677305ba5
--- /dev/null
+++ b/dom/base/crashtests/1341693.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+ var o1 = document.documentElement;
+ var o2 = document.createElement("frame");
+ document.documentElement.appendChild(o2);
+ var o3 = o2.contentWindow;
+ o1.parentNode.removeChild(o1);
+ o3.customElements;
+</script>
+</body>
+</html>
diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list
index a0739f074..0fb597b30 100644
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -209,3 +209,4 @@ load 1230422.html
load 1251361.html
load 1304437.html
pref(clipboard.autocopy,true) load 1385272-1.html
+pref(dom.webcomponents.customelements.enabled,true) load 1341693.html
diff --git a/dom/base/nsContentCreatorFunctions.h b/dom/base/nsContentCreatorFunctions.h
index 9576d9ba8..a5c210500 100644
--- a/dom/base/nsContentCreatorFunctions.h
+++ b/dom/base/nsContentCreatorFunctions.h
@@ -24,6 +24,7 @@ namespace mozilla {
namespace dom {
class Element;
class NodeInfo;
+struct CustomElementDefinition;
} // namespace dom
} // namespace mozilla
@@ -41,7 +42,8 @@ nsresult
NS_NewHTMLElement(mozilla::dom::Element** aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
mozilla::dom::FromParser aFromParser,
- const nsAString* aIs = nullptr);
+ const nsAString* aIs = nullptr,
+ mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
// First argument should be nsHTMLTag, but that adds dependency to parser
// for a bunch of files.
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 800f40fa1..b6cbbbace 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -227,6 +227,7 @@ extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
int ns_aware, const char** colon);
class imgLoader;
+class nsIAtom;
using namespace mozilla::dom;
using namespace mozilla::ipc;
@@ -258,7 +259,6 @@ nsIWordBreaker *nsContentUtils::sWordBreaker;
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
uint32_t nsContentUtils::sScriptBlockerCount = 0;
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
-uint32_t nsContentUtils::sMicroTaskLevel = 0;
AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = nullptr;
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
@@ -284,6 +284,8 @@ bool nsContentUtils::sIsResourceTimingEnabled = false;
bool nsContentUtils::sIsPerformanceNavigationTimingEnabled = false;
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
+bool nsContentUtils::sIsWebComponentsEnabled = false;
+bool nsContentUtils::sIsCustomElementsEnabled = false;
bool nsContentUtils::sEncodeDecodeURLHash = false;
bool nsContentUtils::sGettersDecodeURLHash = false;
bool nsContentUtils::sPrivacyResistFingerprinting = false;
@@ -584,6 +586,12 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
"dom.forms.autocomplete.experimental", false);
+ Preferences::AddBoolVarCache(&sIsWebComponentsEnabled,
+ "dom.webcomponents.enabled", false);
+
+ Preferences::AddBoolVarCache(&sIsCustomElementsEnabled,
+ "dom.webcomponents.customelements.enabled", false);
+
Preferences::AddBoolVarCache(&sEncodeDecodeURLHash,
"dom.url.encode_decode_hash", false);
@@ -5293,51 +5301,6 @@ nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
}
-void
-nsContentUtils::EnterMicroTask()
-{
- MOZ_ASSERT(NS_IsMainThread());
- ++sMicroTaskLevel;
-}
-
-void
-nsContentUtils::LeaveMicroTask()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (--sMicroTaskLevel == 0) {
- PerformMainThreadMicroTaskCheckpoint();
- }
-}
-
-bool
-nsContentUtils::IsInMicroTask()
-{
- MOZ_ASSERT(NS_IsMainThread());
- return sMicroTaskLevel != 0;
-}
-
-uint32_t
-nsContentUtils::MicroTaskLevel()
-{
- MOZ_ASSERT(NS_IsMainThread());
- return sMicroTaskLevel;
-}
-
-void
-nsContentUtils::SetMicroTaskLevel(uint32_t aLevel)
-{
- MOZ_ASSERT(NS_IsMainThread());
- sMicroTaskLevel = aLevel;
-}
-
-void
-nsContentUtils::PerformMainThreadMicroTaskCheckpoint()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- nsDOMMutationObserver::HandleMutations();
-}
-
/*
* Helper function for nsContentUtils::ProcessViewportInfo.
*
@@ -9567,11 +9530,34 @@ nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
return false;
}
+/* static */ void
+nsContentUtils::TryToUpgradeElement(Element* aElement)
+{
+ NodeInfo* nodeInfo = aElement->NodeInfo();
+ RefPtr<nsIAtom> typeAtom =
+ aElement->GetCustomElementData()->GetCustomElementType();
+
+ MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
+ CustomElementDefinition* definition =
+ nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+ nodeInfo->NameAtom(),
+ nodeInfo->NamespaceID(),
+ typeAtom);
+ if (definition) {
+ nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
+ } else {
+ // Add an unresolved custom element that is a candidate for
+ // upgrade when a custom element is connected to the document.
+ // We will make sure it's shadow-including tree order in bug 1326028.
+ nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
+ }
+}
+
/* static */ CustomElementDefinition*
nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
- const nsAString& aLocalName,
+ nsIAtom* aNameAtom,
uint32_t aNameSpaceID,
- const nsAString* aIs)
+ nsIAtom* aTypeAtom)
{
MOZ_ASSERT(aDoc);
@@ -9593,30 +9579,37 @@ nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
return nullptr;
}
- return registry->LookupCustomElementDefinition(aLocalName, aIs);
+ return registry->LookupCustomElementDefinition(aNameAtom, aTypeAtom);
}
/* static */ void
-nsContentUtils::SetupCustomElement(Element* aElement,
- const nsAString* aTypeExtension)
+nsContentUtils::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
{
MOZ_ASSERT(aElement);
- nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
-
- if (!doc) {
+ nsIDocument* doc = aElement->OwnerDoc();
+ nsPIDOMWindowInner* window(doc->GetInnerWindow());
+ if (!window) {
return;
}
- // To support imported document.
- doc = doc->MasterDocument();
-
- if (aElement->GetNameSpaceID() != kNameSpaceID_XHTML ||
- !doc->GetDocShell()) {
+ RefPtr<CustomElementRegistry> registry(window->CustomElements());
+ if (!registry) {
return;
}
- nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
+ registry->RegisterUnresolvedElement(aElement, aTypeName);
+}
+
+/* static */ void
+nsContentUtils::UnregisterUnresolvedElement(Element* aElement)
+{
+ MOZ_ASSERT(aElement);
+
+ RefPtr<nsIAtom> typeAtom =
+ aElement->GetCustomElementData()->GetCustomElementType();
+ nsIDocument* doc = aElement->OwnerDoc();
+ nsPIDOMWindowInner* window(doc->GetInnerWindow());
if (!window) {
return;
}
@@ -9626,36 +9619,59 @@ nsContentUtils::SetupCustomElement(Element* aElement,
return;
}
- return registry->SetupCustomElement(aElement, aTypeExtension);
+ registry->UnregisterUnresolvedElement(aElement, typeAtom);
+}
+
+/* static */ CustomElementDefinition*
+nsContentUtils::GetElementDefinitionIfObservingAttr(Element* aCustomElement,
+ nsIAtom* aExtensionType,
+ nsIAtom* aAttrName)
+{
+ CustomElementDefinition* definition =
+ aCustomElement->GetCustomElementDefinition();
+
+ // Custom element not defined yet or attribute is not in the observed
+ // attribute list.
+ if (!definition || !definition->IsInObservedAttributeList(aAttrName)) {
+ return nullptr;
+ }
+
+ return definition;
}
/* static */ void
-nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
- nsIDocument::ElementCallbackType aType,
- Element* aCustomElement,
- LifecycleCallbackArgs* aArgs,
- CustomElementDefinition* aDefinition)
+nsContentUtils::EnqueueUpgradeReaction(Element* aElement,
+ CustomElementDefinition* aDefinition)
{
- MOZ_ASSERT(aDoc);
+ MOZ_ASSERT(aElement);
- // To support imported document.
- nsCOMPtr<nsIDocument> doc = aDoc->MasterDocument();
+ nsIDocument* doc = aElement->OwnerDoc();
- if (!doc->GetDocShell()) {
+ // No DocGroup means no custom element reactions stack.
+ if (!doc->GetDocGroup()) {
return;
}
- nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
- if (!window) {
- return;
- }
+ CustomElementReactionsStack* stack =
+ doc->GetDocGroup()->CustomElementReactionsStack();
+ stack->EnqueueUpgradeReaction(aElement, aDefinition);
+}
- RefPtr<CustomElementRegistry> registry(window->CustomElements());
- if (!registry) {
+/* static */ void
+nsContentUtils::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
+ Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition)
+{
+ // No DocGroup means no custom element reactions stack.
+ if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
return;
}
- registry->EnqueueLifecycleCallback(aType, aCustomElement, aArgs, aDefinition);
+ CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
+ aAdoptedCallbackArgs,
+ aDefinition);
}
/* static */ void
@@ -9834,4 +9850,4 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
}
return false;
-} \ No newline at end of file
+}
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 606d67de9..bf6a59dcd 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -126,6 +126,7 @@ class EventTarget;
class IPCDataTransfer;
class IPCDataTransferItem;
struct LifecycleCallbackArgs;
+struct LifecycleAdoptedCallbackArgs;
class NodeInfo;
class nsIContentChild;
class nsIContentParent;
@@ -1739,17 +1740,6 @@ public:
*/
static void RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable);
- // Call EnterMicroTask when you're entering JS execution.
- // Usually the best way to do this is to use nsAutoMicroTask.
- static void EnterMicroTask();
- static void LeaveMicroTask();
-
- static bool IsInMicroTask();
- static uint32_t MicroTaskLevel();
- static void SetMicroTaskLevel(uint32_t aLevel);
-
- static void PerformMainThreadMicroTaskCheckpoint();
-
/* Process viewport META data. This gives us information for the scale
* and zoom of a page on mobile devices. We stick the information in
* the document header and use it later on after rendering.
@@ -2711,22 +2701,36 @@ public:
static bool HttpsStateIsModern(nsIDocument* aDocument);
/**
+ * Try to upgrade an element.
+ * https://html.spec.whatwg.org/multipage/custom-elements.html#concept-try-upgrade
+ */
+ static void TryToUpgradeElement(Element* aElement);
+
+ /**
* Looking up a custom element definition.
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
*/
static mozilla::dom::CustomElementDefinition*
LookupCustomElementDefinition(nsIDocument* aDoc,
- const nsAString& aLocalName,
+ nsIAtom* aNameAtom,
uint32_t aNameSpaceID,
- const nsAString* aIs = nullptr);
+ nsIAtom* aTypeAtom);
- static void SetupCustomElement(Element* aElement,
- const nsAString* aTypeExtension = nullptr);
+ static void RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName);
+ static void UnregisterUnresolvedElement(Element* aElement);
- static void EnqueueLifecycleCallback(nsIDocument* aDoc,
- nsIDocument::ElementCallbackType aType,
+ static mozilla::dom::CustomElementDefinition*
+ GetElementDefinitionIfObservingAttr(Element* aCustomElement,
+ nsIAtom* aExtensionType,
+ nsIAtom* aAttrName);
+
+ static void EnqueueUpgradeReaction(Element* aElement,
+ mozilla::dom::CustomElementDefinition* aDefinition);
+
+ static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
+ mozilla::dom::LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs = nullptr,
mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
static void GetCustomPrototype(nsIDocument* aDoc,
@@ -2743,6 +2747,12 @@ public:
static bool
IsLocalRefURL(const nsString& aString);
+ static bool
+ IsWebComponentsEnabled() { return sIsWebComponentsEnabled; }
+
+ static bool
+ IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
+
private:
static bool InitializeEventTable();
@@ -2829,7 +2839,6 @@ private:
static bool sInitialized;
static uint32_t sScriptBlockerCount;
static uint32_t sDOMNodeRemovedSuppressCount;
- static uint32_t sMicroTaskLevel;
// Not an nsCOMArray because removing elements from those is slower
static AutoTArray<nsCOMPtr<nsIRunnable>, 8>* sBlockedScriptRunners;
static uint32_t sRunnersCountAtFirstBlocker;
@@ -2850,6 +2859,8 @@ private:
static bool sIsUserTimingLoggingEnabled;
static bool sIsFrameTimingPrefEnabled;
static bool sIsExperimentalAutocompleteEnabled;
+ static bool sIsWebComponentsEnabled;
+ static bool sIsCustomElementsEnabled;
static bool sEncodeDecodeURLHash;
static bool sGettersDecodeURLHash;
static bool sPrivacyResistFingerprinting;
@@ -2905,19 +2916,6 @@ public:
}
};
-class MOZ_STACK_CLASS nsAutoMicroTask
-{
-public:
- nsAutoMicroTask()
- {
- nsContentUtils::EnterMicroTask();
- }
- ~nsAutoMicroTask()
- {
- nsContentUtils::LeaveMicroTask();
- }
-};
-
namespace mozilla {
namespace dom {
diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp
index 858a30ce5..4c4731c11 100644
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -32,8 +32,6 @@ using mozilla::dom::Element;
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>*
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
-nsDOMMutationObserver* nsDOMMutationObserver::sCurrentObserver = nullptr;
-
uint32_t nsDOMMutationObserver::sMutationLevel = 0;
uint64_t nsDOMMutationObserver::sCount = 0;
@@ -597,10 +595,32 @@ nsDOMMutationObserver::ScheduleForRun()
RescheduleForRun();
}
+class MutationObserverMicroTask final : public MicroTaskRunnable
+{
+public:
+ virtual void Run(AutoSlowOperation& aAso) override
+ {
+ nsDOMMutationObserver::HandleMutations(aAso);
+ }
+
+ virtual bool Suppressed() override
+ {
+ return nsDOMMutationObserver::AllScheduledMutationObserversAreSuppressed();
+ }
+};
+
void
nsDOMMutationObserver::RescheduleForRun()
{
if (!sScheduledMutationObservers) {
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (!ccjs) {
+ return;
+ }
+
+ RefPtr<MutationObserverMicroTask> momt =
+ new MutationObserverMicroTask();
+ ccjs->DispatchMicroTaskRunnable(momt.forget());
sScheduledMutationObservers = new AutoTArray<RefPtr<nsDOMMutationObserver>, 4>;
}
@@ -862,36 +882,9 @@ nsDOMMutationObserver::HandleMutation()
mCallback->Call(this, mutations, *this);
}
-class AsyncMutationHandler : public mozilla::Runnable
-{
-public:
- NS_IMETHOD Run() override
- {
- nsDOMMutationObserver::HandleMutations();
- return NS_OK;
- }
-};
-
void
-nsDOMMutationObserver::HandleMutationsInternal()
+nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
{
- if (!nsContentUtils::IsSafeToRunScript()) {
- nsContentUtils::AddScriptRunner(new AsyncMutationHandler());
- return;
- }
- static RefPtr<nsDOMMutationObserver> sCurrentObserver;
- if (sCurrentObserver && !sCurrentObserver->Suppressed()) {
- // In normal cases sScheduledMutationObservers will be handled
- // after previous mutations are handled. But in case some
- // callback calls a sync API, which spins the eventloop, we need to still
- // process other mutations happening during that sync call.
- // This does *not* catch all cases, but should work for stuff running
- // in separate tabs.
- return;
- }
-
- mozilla::AutoSlowOperation aso;
-
nsTArray<RefPtr<nsDOMMutationObserver> >* suppressedObservers = nullptr;
while (sScheduledMutationObservers) {
@@ -899,20 +892,21 @@ nsDOMMutationObserver::HandleMutationsInternal()
sScheduledMutationObservers;
sScheduledMutationObservers = nullptr;
for (uint32_t i = 0; i < observers->Length(); ++i) {
- sCurrentObserver = static_cast<nsDOMMutationObserver*>((*observers)[i]);
- if (!sCurrentObserver->Suppressed()) {
- sCurrentObserver->HandleMutation();
+ RefPtr<nsDOMMutationObserver> currentObserver =
+ static_cast<nsDOMMutationObserver*>((*observers)[i]);
+ if (!currentObserver->Suppressed()) {
+ currentObserver->HandleMutation();
} else {
if (!suppressedObservers) {
suppressedObservers = new nsTArray<RefPtr<nsDOMMutationObserver> >;
}
- if (!suppressedObservers->Contains(sCurrentObserver)) {
- suppressedObservers->AppendElement(sCurrentObserver);
+ if (!suppressedObservers->Contains(currentObserver)) {
+ suppressedObservers->AppendElement(currentObserver);
}
}
}
delete observers;
- aso.CheckForInterrupt();
+ aAso.CheckForInterrupt();
}
if (suppressedObservers) {
@@ -923,7 +917,6 @@ nsDOMMutationObserver::HandleMutationsInternal()
delete suppressedObservers;
suppressedObservers = nullptr;
}
- sCurrentObserver = nullptr;
}
nsDOMMutationRecord*
diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h
index cde32c57b..a8babc603 100644
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -552,13 +552,29 @@ public:
}
// static methods
- static void HandleMutations()
+ static void HandleMutations(mozilla::AutoSlowOperation& aAso)
{
if (sScheduledMutationObservers) {
- HandleMutationsInternal();
+ HandleMutationsInternal(aAso);
}
}
+ static bool AllScheduledMutationObserversAreSuppressed()
+ {
+ if (sScheduledMutationObservers) {
+ uint32_t len = sScheduledMutationObservers->Length();
+ if (len > 0) {
+ for (uint32_t i = 0; i < len; ++i) {
+ if (!(*sScheduledMutationObservers)[i]->Suppressed()) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
static void EnterMutationHandling();
static void LeaveMutationHandling();
@@ -594,7 +610,7 @@ protected:
return false;
}
- static void HandleMutationsInternal();
+ static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso);
static void AddCurrentlyHandlingObserver(nsDOMMutationObserver* aObserver,
uint32_t aMutationLevel);
@@ -622,7 +638,6 @@ protected:
static uint64_t sCount;
static AutoTArray<RefPtr<nsDOMMutationObserver>, 4>* sScheduledMutationObservers;
- static nsDOMMutationObserver* sCurrentObserver;
static uint32_t sMutationLevel;
static AutoTArray<AutoTArray<RefPtr<nsDOMMutationObserver>, 4>, 4>*
diff --git a/dom/base/nsDeprecatedOperationList.h b/dom/base/nsDeprecatedOperationList.h
index ea4b05289..96a6c3ac0 100644
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -34,7 +34,6 @@ DEPRECATED_OPERATION(UseOfCaptureEvents)
DEPRECATED_OPERATION(UseOfReleaseEvents)
DEPRECATED_OPERATION(UseOfDOM3LoadMethod)
DEPRECATED_OPERATION(ChromeUseOfDOM3LoadMethod)
-DEPRECATED_OPERATION(ShowModalDialog)
DEPRECATED_OPERATION(Window_Content)
DEPRECATED_OPERATION(SyncXMLHttpRequest)
DEPRECATED_OPERATION(DataContainerEvent)
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index afe88a454..293e48eb0 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1329,7 +1329,8 @@ nsIDocument::nsIDocument()
mFrameRequestCallbacksScheduled(false),
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
mPartID(0),
- mUserHasInteracted(false)
+ mUserHasInteracted(false),
+ mThrowOnDynamicMarkupInsertionCounter(0)
{
SetIsInDocument();
@@ -5395,18 +5396,14 @@ nsDocument::CreateElement(const nsAString& aTagName,
}
const nsString* is = nullptr;
- if (aOptions.IsElementCreationOptions()) {
- // Throw NotFoundError if 'is' is not-null and definition is null
- is = CheckCustomElementName(aOptions.GetAsElementCreationOptions(),
- needsLowercase ? lcTagName : aTagName, mDefaultElementType, rv);
- if (rv.Failed()) {
- return nullptr;
- }
- }
RefPtr<Element> elem = CreateElem(
needsLowercase ? lcTagName : aTagName, nullptr, mDefaultElementType, is);
+ if (is) {
+ elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
+ }
+
return elem.forget();
}
@@ -5443,14 +5440,6 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
}
const nsString* is = nullptr;
- if (aOptions.IsElementCreationOptions()) {
- // Throw NotFoundError if 'is' is not-null and definition is null
- is = CheckCustomElementName(aOptions.GetAsElementCreationOptions(),
- aQualifiedName, nodeInfo->NamespaceID(), rv);
- if (rv.Failed()) {
- return nullptr;
- }
- }
nsCOMPtr<Element> element;
rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
@@ -5459,6 +5448,10 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
return nullptr;
}
+ if (is) {
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
+ }
+
return element.forget();
}
@@ -5681,24 +5674,70 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
}
nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
- CustomElementDefinition* definition = registry->mCustomDefinitions.Get(typeAtom);
+ CustomElementDefinition* definition =
+ registry->mCustomDefinitions.GetWeak(typeAtom);
if (!definition) {
return true;
}
- nsDependentAtomString localName(definition->mLocalName);
+ RefPtr<Element> element;
+
+ // We integrate with construction stack and do prototype swizzling here, so
+ // that old upgrade behavior could also share the new upgrade steps.
+ // And this old upgrade will be remove at some point (when everything is
+ // switched to latest custom element spec).
+ nsTArray<RefPtr<nsGenericHTMLElement>>& constructionStack =
+ definition->mConstructionStack;
+ if (constructionStack.Length()) {
+ element = constructionStack.LastElement();
+ NS_ENSURE_TRUE(element != ALEADY_CONSTRUCTED_MARKER, false);
+
+ // Do prototype swizzling if dom reflector exists.
+ JS::Rooted<JSObject*> reflector(aCx, element->GetWrapper());
+ if (reflector) {
+ Maybe<JSAutoCompartment> ac;
+ JS::Rooted<JSObject*> prototype(aCx, definition->mPrototype);
+ if (element->NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(prototype))) {
+ ac.emplace(aCx, reflector);
+ if (!JS_WrapObject(aCx, &prototype) ||
+ !JS_SetPrototype(aCx, reflector, prototype)) {
+ return false;
+ }
+ } else {
+ // We want to set the custom prototype in the compartment where it was
+ // registered. We store the prototype from define() without unwrapped,
+ // hence the prototype's compartment is the compartment where it was
+ // registered.
+ // In the case that |reflector| and |prototype| are in different
+ // compartments, this will set the prototype on the |reflector|'s wrapper
+ // and thus only visible in the wrapper's compartment, since we know
+ // reflector's principal does not subsume prototype's in this case.
+ ac.emplace(aCx, prototype);
+ if (!JS_WrapObject(aCx, &reflector) ||
+ !JS_SetPrototype(aCx, reflector, prototype)) {
+ return false;
+ }
+ }
- nsCOMPtr<Element> element =
- document->CreateElem(localName, nullptr, kNameSpaceID_XHTML);
- NS_ENSURE_TRUE(element, true);
+ // Wrap into current context.
+ if (!JS_WrapObject(aCx, &reflector)) {
+ return false;
+ }
- if (definition->mLocalName != typeAtom) {
- // This element is a custom element by extension, thus we need to
- // do some special setup. For non-extended custom elements, this happens
- // when the element is created.
- nsContentUtils::SetupCustomElement(element, &elemName);
+ args.rval().setObject(*reflector);
+ return true;
+ }
+ } else {
+ nsDependentAtomString localName(definition->mLocalName);
+ element =
+ document->CreateElem(localName, nullptr, kNameSpaceID_XHTML,
+ (definition->mLocalName != typeAtom) ? &elemName
+ : nullptr);
+ NS_ENSURE_TRUE(element, false);
}
+ // The prototype setup happens in Element::WrapObject().
+
nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval());
NS_ENSURE_SUCCESS(rv, true);
@@ -5710,7 +5749,7 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
JS::Rooted<JSObject*> obj(aCx, aObject);
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
@@ -5726,7 +5765,7 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
bool
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
{
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
@@ -5770,6 +5809,8 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
return;
}
+ AutoCEReaction ceReaction(this->GetDocGroup()->CustomElementReactionsStack(),
+ aCx);
// Unconditionally convert TYPE to lowercase.
nsAutoString lcType;
nsContentUtils::ASCIIToLower(aType, lcType);
@@ -6536,6 +6577,49 @@ nsIDocument::GetHtmlChildElement(nsIAtom* aTag)
return nullptr;
}
+nsGenericHTMLElement*
+nsIDocument::GetBody()
+{
+ Element* html = GetHtmlElement();
+ if (!html) {
+ return nullptr;
+ }
+
+ for (nsIContent* child = html->GetFirstChild();
+ child;
+ child = child->GetNextSibling()) {
+ if (child->IsHTMLElement(nsGkAtoms::body) ||
+ child->IsHTMLElement(nsGkAtoms::frameset)) {
+ return static_cast<nsGenericHTMLElement*>(child);
+ }
+ }
+
+ return nullptr;
+}
+
+void
+nsIDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
+{
+ nsCOMPtr<Element> root = GetRootElement();
+
+ // The body element must be either a body tag or a frameset tag. And we must
+ // have a root element to be able to add kids to it.
+ if (!newBody ||
+ !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) ||
+ !root) {
+ rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
+ return;
+ }
+
+ // Use DOM methods so that we pass through the appropriate security checks.
+ nsCOMPtr<Element> currentBody = GetBody();
+ if (currentBody) {
+ root->ReplaceChild(*newBody, *currentBody, rv);
+ } else {
+ root->AppendChild(*newBody, rv);
+ }
+}
+
Element*
nsDocument::GetTitleElement()
{
@@ -12526,8 +12610,12 @@ MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
nsAutoSyncOperation::nsAutoSyncOperation(nsIDocument* aDoc)
{
- mMicroTaskLevel = nsContentUtils::MicroTaskLevel();
- nsContentUtils::SetMicroTaskLevel(0);
+ mMicroTaskLevel = 0;
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ mMicroTaskLevel = ccjs->MicroTaskLevel();
+ ccjs->SetMicroTaskLevel(0);
+ }
if (aDoc) {
if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
if (nsCOMPtr<nsPIDOMWindowOuter> top = win->GetTop()) {
@@ -12543,7 +12631,10 @@ nsAutoSyncOperation::~nsAutoSyncOperation()
for (int32_t i = 0; i < mDocuments.Count(); ++i) {
mDocuments[i]->SetIsInSyncOperation(false);
}
- nsContentUtils::SetMicroTaskLevel(mMicroTaskLevel);
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->SetMicroTaskLevel(mMicroTaskLevel);
+ }
}
gfxUserFontSet*
@@ -12713,30 +12804,6 @@ nsIDocument::UpdateStyleBackendType()
#endif
}
-const nsString*
-nsDocument::CheckCustomElementName(const ElementCreationOptions& aOptions,
- const nsAString& aLocalName,
- uint32_t aNamespaceID,
- ErrorResult& rv)
-{
- // only check aOptions if 'is' is passed and the webcomponents preference
- // is enabled
- if (!aOptions.mIs.WasPassed() ||
- !CustomElementRegistry::IsCustomElementEnabled()) {
- return nullptr;
- }
-
- const nsString* is = &aOptions.mIs.Value();
-
- // Throw NotFoundError if 'is' is not-null and definition is null
- if (!nsContentUtils::LookupCustomElementDefinition(this, aLocalName,
- aNamespaceID, is)) {
- rv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
- }
-
- return is;
-}
-
Selection*
nsIDocument::GetSelection(ErrorResult& aRv)
{
diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h
index 8ea4993f0..90e511dcb 100644
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1388,20 +1388,6 @@ protected:
private:
static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
- /**
- * Check if the passed custom element name, aOptions.mIs, is a registered
- * custom element type or not, then return the custom element name for future
- * usage.
- *
- * If there is no existing custom element definition for this name, throw a
- * NotFoundError.
- */
- const nsString* CheckCustomElementName(
- const mozilla::dom::ElementCreationOptions& aOptions,
- const nsAString& aLocalName,
- uint32_t aNamespaceID,
- ErrorResult& rv);
-
public:
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
GetCustomElementRegistry() override;
diff --git a/dom/base/nsGenericDOMDataNode.cpp b/dom/base/nsGenericDOMDataNode.cpp
index 0ae15e09e..73463ea5e 100644
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -793,17 +793,6 @@ nsGenericDOMDataNode::SetXBLInsertionParent(nsIContent* aContent)
}
}
-CustomElementData *
-nsGenericDOMDataNode::GetCustomElementData() const
-{
- return nullptr;
-}
-
-void
-nsGenericDOMDataNode::SetCustomElementData(CustomElementData* aData)
-{
-}
-
bool
nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
{
diff --git a/dom/base/nsGenericDOMDataNode.h b/dom/base/nsGenericDOMDataNode.h
index 63aa64e74..e8818b518 100644
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -162,9 +162,6 @@ public:
virtual bool IsNodeOfType(uint32_t aFlags) const override;
virtual bool IsLink(nsIURI** aURI) const override;
- virtual mozilla::dom::CustomElementData* GetCustomElementData() const override;
- virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) override;
-
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 47b46dda0..c965d5b97 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -909,7 +909,6 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mInnerObjectsFreed(false),
- mIsModalContentWindow(false),
mIsActive(false), mIsBackground(false),
mMediaSuspend(Preferences::GetBool("media.block-autoplay-until-in-foreground", true) ?
nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
@@ -1957,7 +1956,6 @@ nsGlobalWindow::CleanUp()
}
mArguments = nullptr;
- mDialogArguments = nullptr;
CleanupCachedXBLHandlers(this);
@@ -2195,7 +2193,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDialogArguments)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValue)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
@@ -2274,7 +2271,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mDialogArguments)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValue)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
@@ -3019,8 +3015,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
} else {
if (thisChrome) {
newInnerWindow = nsGlobalChromeWindow::Create(this);
- } else if (mIsModalContentWindow) {
- newInnerWindow = nsGlobalModalWindow::Create(this);
} else {
newInnerWindow = nsGlobalWindow::Create(this);
}
@@ -3871,31 +3865,16 @@ nsGlobalWindow::SetArguments(nsIArray *aArguments)
MOZ_ASSERT(IsOuterWindow());
nsresult rv;
- // Historically, we've used the same machinery to handle openDialog arguments
- // (exposed via window.arguments) and showModalDialog arguments (exposed via
- // window.dialogArguments), even though the former is XUL-only and uses an XPCOM
- // array while the latter is web-exposed and uses an arbitrary JS value.
- // Moreover, per-spec |dialogArguments| is a property of the browsing context
- // (outer), whereas |arguments| lives on the inner.
- //
// We've now mostly separated them, but the difference is still opaque to
// nsWindowWatcher (the caller of SetArguments in this little back-and-forth
// embedding waltz we do here).
//
// So we need to demultiplex the two cases here.
nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
- if (mIsModalContentWindow) {
- // nsWindowWatcher blindly converts the original nsISupports into an array
- // of length 1. We need to recover it, and then cast it back to the concrete
- // object we know it to be.
- nsCOMPtr<nsISupports> supports = do_QueryElementAt(aArguments, 0, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- mDialogArguments = static_cast<DialogValueHolder*>(supports.get());
- } else {
- mArguments = aArguments;
- rv = currentInner->DefineArgumentsProperty(aArguments);
- NS_ENSURE_SUCCESS(rv, rv);
- }
+
+ mArguments = aArguments;
+ rv = currentInner->DefineArgumentsProperty(aArguments);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@@ -3904,7 +3883,6 @@ nsresult
nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments)
{
MOZ_ASSERT(IsInnerWindow());
- MOZ_ASSERT(!mIsModalContentWindow); // Handled separately.
nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED);
@@ -4263,8 +4241,9 @@ CustomElementRegistry*
nsGlobalWindow::CustomElements()
{
MOZ_RELEASE_ASSERT(IsInnerWindow());
+
if (!mCustomElements) {
- mCustomElements = CustomElementRegistry::Create(AsInner());
+ mCustomElements = new CustomElementRegistry(AsInner());
}
return mCustomElements;
@@ -5040,21 +5019,6 @@ nsGlobalWindow::IsPrivilegedChromeWindow(JSContext* aCx, JSObject* aObj)
nsContentUtils::ObjectPrincipal(aObj) == nsContentUtils::GetSystemPrincipal();
}
-/* static */ bool
-nsGlobalWindow::IsShowModalDialogEnabled(JSContext*, JSObject*)
-{
- static bool sAddedPrefCache = false;
- static bool sIsDisabled;
- static const char sShowModalDialogPref[] = "dom.disable_window_showModalDialog";
-
- if (!sAddedPrefCache) {
- Preferences::AddBoolVarCache(&sIsDisabled, sShowModalDialogPref, false);
- sAddedPrefCache = true;
- }
-
- return !sIsDisabled && !XRE_IsContentProcess();
-}
-
nsIDOMOfflineResourceList*
nsGlobalWindow::GetApplicationCache(ErrorResult& aError)
{
@@ -9741,126 +9705,6 @@ nsGlobalWindow::ConvertDialogOptions(const nsAString& aOptions,
}
}
-already_AddRefed<nsIVariant>
-nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
- nsIVariant* aArgument,
- const nsAString& aOptions,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- MOZ_RELEASE_ASSERT(IsOuterWindow());
-
- if (mDoc) {
- mDoc->WarnOnceAbout(nsIDocument::eShowModalDialog);
- }
-
- if (!IsShowModalDialogEnabled()) {
- aError.Throw(NS_ERROR_NOT_AVAILABLE);
- return nullptr;
- }
-
- RefPtr<DialogValueHolder> argHolder =
- new DialogValueHolder(&aSubjectPrincipal, aArgument);
-
- // Before bringing up the window/dialog, unsuppress painting and flush
- // pending reflows.
- EnsureReflowFlushAndPaint();
-
- if (!AreDialogsEnabled()) {
- // We probably want to keep throwing here; silently doing nothing is a bit
- // weird given the typical use cases of showModalDialog().
- aError.Throw(NS_ERROR_NOT_AVAILABLE);
- return nullptr;
- }
-
- if (ShouldPromptToBlockDialogs() && !ConfirmDialogIfNeeded()) {
- aError.Throw(NS_ERROR_NOT_AVAILABLE);
- return nullptr;
- }
-
- nsCOMPtr<nsPIDOMWindowOuter> dlgWin;
- nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
-
- ConvertDialogOptions(aOptions, options);
-
- options.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
-
- EnterModalState();
- uint32_t oldMicroTaskLevel = nsContentUtils::MicroTaskLevel();
- nsContentUtils::SetMicroTaskLevel(0);
- aError = OpenInternal(aUrl, EmptyString(), options,
- false, // aDialog
- true, // aContentModal
- true, // aCalledNoScript
- true, // aDoJSFixups
- true, // aNavigate
- nullptr, argHolder, // args
- nullptr, // aLoadInfo
- false, // aForceNoOpener
- getter_AddRefs(dlgWin));
- nsContentUtils::SetMicroTaskLevel(oldMicroTaskLevel);
- LeaveModalState();
- if (aError.Failed()) {
- return nullptr;
- }
-
- nsCOMPtr<nsIDOMModalContentWindow> dialog = do_QueryInterface(dlgWin);
- if (!dialog) {
- return nullptr;
- }
-
- nsCOMPtr<nsIVariant> retVal;
- aError = dialog->GetReturnValue(getter_AddRefs(retVal));
- MOZ_ASSERT(!aError.Failed());
-
- return retVal.forget();
-}
-
-already_AddRefed<nsIVariant>
-nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
- const nsAString& aOptions,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- FORWARD_TO_OUTER_OR_THROW(ShowModalDialogOuter,
- (aUrl, aArgument, aOptions, aSubjectPrincipal,
- aError), aError, nullptr);
-}
-
-void
-nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
- JS::Handle<JS::Value> aArgument,
- const nsAString& aOptions,
- JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- MOZ_ASSERT(IsInnerWindow());
-
- nsCOMPtr<nsIVariant> args;
- aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
- aArgument,
- getter_AddRefs(args));
- if (aError.Failed()) {
- return;
- }
-
- nsCOMPtr<nsIVariant> retVal =
- ShowModalDialog(aUrl, args, aOptions, aSubjectPrincipal, aError);
- if (aError.Failed()) {
- return;
- }
-
- JS::Rooted<JS::Value> result(aCx);
- if (retVal) {
- aError = nsContentUtils::XPConnect()->VariantToJS(aCx,
- FastGetGlobalJSObject(),
- retVal, aRetval);
- } else {
- aRetval.setNull();
- }
-}
-
class ChildCommandDispatcher : public Runnable
{
public:
@@ -14613,70 +14457,6 @@ nsGlobalChromeWindow::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aO
return NS_OK;
}
-// nsGlobalModalWindow implementation
-
-// QueryInterface implementation for nsGlobalModalWindow
-NS_INTERFACE_MAP_BEGIN(nsGlobalModalWindow)
- NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
-NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
-
-NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
-NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
-
-
-void
-nsGlobalWindow::GetDialogArgumentsOuter(JSContext* aCx,
- JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- MOZ_RELEASE_ASSERT(IsOuterWindow());
- MOZ_ASSERT(IsModalContentWindow(),
- "This should only be called on modal windows!");
-
- if (!mDialogArguments) {
- MOZ_ASSERT(mIsClosed, "This window should be closed!");
- aRetval.setUndefined();
- return;
- }
-
- // This does an internal origin check, and returns undefined if the subject
- // does not subsumes the origin of the arguments.
- JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
- JSAutoCompartment ac(aCx, wrapper);
- mDialogArguments->Get(aCx, wrapper, &aSubjectPrincipal, aRetval, aError);
-}
-
-void
-nsGlobalWindow::GetDialogArguments(JSContext* aCx,
- JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- FORWARD_TO_OUTER_OR_THROW(GetDialogArgumentsOuter,
- (aCx, aRetval, aSubjectPrincipal, aError),
- aError, );
-}
-
-/* static */ already_AddRefed<nsGlobalModalWindow>
-nsGlobalModalWindow::Create(nsGlobalWindow *aOuterWindow)
-{
- RefPtr<nsGlobalModalWindow> window = new nsGlobalModalWindow(aOuterWindow);
- window->InitWasOffline();
- return window.forget();
-}
-
-NS_IMETHODIMP
-nsGlobalModalWindow::GetDialogArguments(nsIVariant **aArguments)
-{
- FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetDialogArguments, (aArguments),
- NS_ERROR_NOT_INITIALIZED);
-
- // This does an internal origin check, and returns undefined if the subject
- // does not subsumes the origin of the arguments.
- return mDialogArguments->Get(nsContentUtils::SubjectPrincipal(), aArguments);
-}
-
/* static */ already_AddRefed<nsGlobalWindow>
nsGlobalWindow::Create(nsGlobalWindow *aOuterWindow)
{
@@ -14691,96 +14471,6 @@ nsGlobalWindow::InitWasOffline()
mWasOffline = NS_IsOffline();
}
-void
-nsGlobalWindow::GetReturnValueOuter(JSContext* aCx,
- JS::MutableHandle<JS::Value> aReturnValue,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- MOZ_RELEASE_ASSERT(IsOuterWindow());
- MOZ_ASSERT(IsModalContentWindow(),
- "This should only be called on modal windows!");
-
- if (mReturnValue) {
- JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
- JSAutoCompartment ac(aCx, wrapper);
- mReturnValue->Get(aCx, wrapper, &aSubjectPrincipal, aReturnValue, aError);
- } else {
- aReturnValue.setUndefined();
- }
-}
-
-void
-nsGlobalWindow::GetReturnValue(JSContext* aCx,
- JS::MutableHandle<JS::Value> aReturnValue,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- FORWARD_TO_OUTER_OR_THROW(GetReturnValueOuter,
- (aCx, aReturnValue, aSubjectPrincipal, aError),
- aError, );
-}
-
-NS_IMETHODIMP
-nsGlobalModalWindow::GetReturnValue(nsIVariant **aRetVal)
-{
- FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue, (aRetVal), NS_OK);
-
- if (!mReturnValue) {
- nsCOMPtr<nsIVariant> variant = CreateVoidVariant();
- variant.forget(aRetVal);
- return NS_OK;
- }
- return mReturnValue->Get(nsContentUtils::SubjectPrincipal(), aRetVal);
-}
-
-void
-nsGlobalWindow::SetReturnValueOuter(JSContext* aCx,
- JS::Handle<JS::Value> aReturnValue,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- MOZ_RELEASE_ASSERT(IsOuterWindow());
- MOZ_ASSERT(IsModalContentWindow(),
- "This should only be called on modal windows!");
-
- nsCOMPtr<nsIVariant> returnValue;
- aError =
- nsContentUtils::XPConnect()->JSToVariant(aCx, aReturnValue,
- getter_AddRefs(returnValue));
- if (!aError.Failed()) {
- mReturnValue = new DialogValueHolder(&aSubjectPrincipal, returnValue);
- }
-}
-
-void
-nsGlobalWindow::SetReturnValue(JSContext* aCx,
- JS::Handle<JS::Value> aReturnValue,
- nsIPrincipal& aSubjectPrincipal,
- ErrorResult& aError)
-{
- FORWARD_TO_OUTER_OR_THROW(SetReturnValueOuter,
- (aCx, aReturnValue, aSubjectPrincipal, aError),
- aError, );
-}
-
-NS_IMETHODIMP
-nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
-{
- FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue, (aRetVal), NS_OK);
-
- mReturnValue = new DialogValueHolder(nsContentUtils::SubjectPrincipal(),
- aRetVal);
- return NS_OK;
-}
-
-/* static */
-bool
-nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
-{
- return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
-}
-
#if defined(MOZ_WIDGET_ANDROID)
int16_t
nsGlobalWindow::Orientation(CallerType aCallerType) const
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index 1f420895c..5cfd3f056 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -458,9 +458,6 @@ public:
static bool IsPrivilegedChromeWindow(JSContext* /* unused */, JSObject* aObj);
- static bool IsShowModalDialogEnabled(JSContext* /* unused */ = nullptr,
- JSObject* /* unused */ = nullptr);
-
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId,
JS::MutableHandle<JS::PropertyDescriptor> aDesc);
@@ -583,9 +580,6 @@ public:
return mIsChrome;
}
- using nsPIDOMWindow::IsModalContentWindow;
- static bool IsModalContentWindow(JSContext* aCx, JSObject* aGlobal);
-
// GetScrollFrame does not flush. Callers should do it themselves as needed,
// depending on which info they actually want off the scrollable frame.
nsIScrollableFrame *GetScrollFrame();
@@ -950,12 +944,6 @@ public:
mozilla::ErrorResult& aRv);
void PrintOuter(mozilla::ErrorResult& aError);
void Print(mozilla::ErrorResult& aError);
- void ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
- JS::Handle<JS::Value> aArgument,
- const nsAString& aOptions,
- JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- mozilla::ErrorResult& aError);
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
@@ -1227,12 +1215,6 @@ public:
mozilla::dom::Element* aPanel,
mozilla::ErrorResult& aError);
- void GetDialogArgumentsOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- mozilla::ErrorResult& aError);
- void GetDialogArguments(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
- nsIPrincipal& aSubjectPrincipal,
- mozilla::ErrorResult& aError);
void GetReturnValueOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
@@ -1681,18 +1663,6 @@ protected:
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
- already_AddRefed<nsIVariant>
- ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgument,
- const nsAString& aOptions,
- nsIPrincipal& aSubjectPrincipal,
- mozilla::ErrorResult& aError);
-
- already_AddRefed<nsIVariant>
- ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
- const nsAString& aOptions,
- nsIPrincipal& aSubjectPrincipal,
- mozilla::ErrorResult& aError);
-
// Ask the user if further dialogs should be blocked, if dialogs are currently
// being abused. This is used in the cases where we have no modifiable UI to
// show, in that case we show a separate dialog to ask this question.
@@ -1832,9 +1802,6 @@ protected:
// For |window.arguments|, via |openDialog|.
nsCOMPtr<nsIArray> mArguments;
- // For |window.dialogArguments|, via |showModalDialog|.
- RefPtr<DialogValueHolder> mDialogArguments;
-
// Only used in the outer.
RefPtr<DialogValueHolder> mReturnValue;
@@ -2067,40 +2034,14 @@ public:
nsCOMPtr<mozIDOMWindowProxy> mOpenerForInitialContentBrowser;
};
-/*
- * nsGlobalModalWindow inherits from nsGlobalWindow. It is the global
- * object created for a modal content windows only (i.e. not modal
- * chrome dialogs).
- */
-class nsGlobalModalWindow : public nsGlobalWindow,
- public nsIDOMModalContentWindow
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIDOMMODALCONTENTWINDOW
-
- static already_AddRefed<nsGlobalModalWindow> Create(nsGlobalWindow *aOuterWindow);
-
-protected:
- explicit nsGlobalModalWindow(nsGlobalWindow *aOuterWindow)
- : nsGlobalWindow(aOuterWindow)
- {
- mIsModalContentWindow = true;
- }
-
- ~nsGlobalModalWindow() {}
-};
-
/* factory function */
inline already_AddRefed<nsGlobalWindow>
-NS_NewScriptGlobalObject(bool aIsChrome, bool aIsModalContentWindow)
+NS_NewScriptGlobalObject(bool aIsChrome)
{
RefPtr<nsGlobalWindow> global;
if (aIsChrome) {
global = nsGlobalChromeWindow::Create(nullptr);
- } else if (aIsModalContentWindow) {
- global = nsGlobalModalWindow::Create(nullptr);
} else {
global = nsGlobalWindow::Create(nullptr);
}
diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h
index 405090865..dcdc632b4 100644
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -26,7 +26,6 @@ namespace mozilla {
class EventChainPreVisitor;
namespace dom {
class ShadowRoot;
-struct CustomElementData;
} // namespace dom
namespace widget {
struct IMEState;
@@ -730,22 +729,6 @@ public:
nsINode *GetFlattenedTreeParentNodeInternal() const;
/**
- * Gets the custom element data used by web components custom element.
- * Custom element data is created at the first attempt to enqueue a callback.
- *
- * @return The custom element data or null if none.
- */
- virtual mozilla::dom::CustomElementData *GetCustomElementData() const = 0;
-
- /**
- * Sets the custom element data, ownership of the
- * callback data is taken by this content.
- *
- * @param aCallbackData The custom element data.
- */
- virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) = 0;
-
- /**
* API to check if this is a link that's traversed in response to user input
* (e.g. a click event). Specializations for HTML/SVG/generic XML allow for
* different types of link in different types of content.
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index fdaee39ca..125816c95 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -61,6 +61,7 @@ class nsFrameLoader;
class nsHTMLCSSStyleSheet;
class nsHTMLDocument;
class nsHTMLStyleSheet;
+class nsGenericHTMLElement;
class nsIAtom;
class nsIBFCacheEntry;
class nsIChannel;
@@ -1036,6 +1037,11 @@ public:
Element* GetHeadElement() {
return GetHtmlChildElement(nsGkAtoms::head);
}
+ // Get the "body" in the sense of document.body: The first <body> or
+ // <frameset> that's a child of a root <html>
+ nsGenericHTMLElement* GetBody();
+ // Set the "body" in the sense of document.body.
+ void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
/**
* Accessors to the collection of stylesheets owned by this document.
@@ -2573,9 +2579,9 @@ public:
}
enum ElementCallbackType {
- eCreated,
- eAttached,
- eDetached,
+ eConnected,
+ eDisconnected,
+ eAdopted,
eAttributeChanged
};
@@ -2872,6 +2878,22 @@ public:
virtual void ScheduleIntersectionObserverNotification() = 0;
virtual void NotifyIntersectionObservers() = 0;
+ bool ShouldThrowOnDynamicMarkupInsertion()
+ {
+ return mThrowOnDynamicMarkupInsertionCounter;
+ }
+
+ void IncrementThrowOnDynamicMarkupInsertionCounter()
+ {
+ ++mThrowOnDynamicMarkupInsertionCounter;
+ }
+
+ void DecrementThrowOnDynamicMarkupInsertionCounter()
+ {
+ MOZ_ASSERT(mThrowOnDynamicMarkupInsertionCounter);
+ --mThrowOnDynamicMarkupInsertionCounter;
+ }
+
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
{
@@ -3319,6 +3341,11 @@ protected:
uint32_t mBlockDOMContentLoaded;
+ // Used in conjunction with the create-an-element-for-the-token algorithm to
+ // prevent custom element constructors from being able to use document.open(),
+ // document.close(), and document.write() when they are invoked by the parser.
+ uint32_t mThrowOnDynamicMarkupInsertionCounter;
+
// Our live MediaQueryLists
PRCList mDOMMediaQueryLists;
@@ -3392,6 +3419,23 @@ private:
uint32_t mMicroTaskLevel;
};
+class MOZ_RAII AutoSetThrowOnDynamicMarkupInsertionCounter final {
+ public:
+ explicit AutoSetThrowOnDynamicMarkupInsertionCounter(
+ nsIDocument* aDocument)
+ : mDocument(aDocument)
+ {
+ mDocument->IncrementThrowOnDynamicMarkupInsertionCounter();
+ }
+
+ ~AutoSetThrowOnDynamicMarkupInsertionCounter() {
+ mDocument->DecrementThrowOnDynamicMarkupInsertionCounter();
+ }
+
+ private:
+ nsIDocument* mDocument;
+};
+
// XXX These belong somewhere else
nsresult
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
index 98b367b66..b6c843065 100644
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -25,7 +25,7 @@
#include "xpcpublic.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
-
+#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Date.h"
#include "mozilla/dom/Element.h"
@@ -159,7 +159,8 @@ nsJSUtils::EvaluateString(JSContext* aCx,
aEvaluationGlobal);
MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval);
MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(nsContentUtils::IsInMicroTask());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
// Unfortunately, the JS engine actually compiles scripts with a return value
// in a different, less efficient way. Furthermore, it can't JIT them in many
@@ -293,7 +294,8 @@ nsJSUtils::CompileModule(JSContext* aCx,
aEvaluationGlobal);
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(nsContentUtils::IsInMicroTask());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
@@ -330,7 +332,8 @@ nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(nsContentUtils::IsInMicroTask());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp
index 75d408151..384e56cde 100644
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -301,9 +301,12 @@ nsNodeUtils::LastRelease(nsINode* aNode)
Element* elem = aNode->AsElement();
FragmentOrElement::nsDOMSlots* domSlots =
static_cast<FragmentOrElement::nsDOMSlots*>(slots);
- for (auto iter = domSlots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
- DOMIntersectionObserver* observer = iter.Key();
- observer->UnlinkTarget(*elem);
+ if (domSlots->mExtendedSlots) {
+ for (auto iter = domSlots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
+ !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Key();
+ observer->UnlinkTarget(*elem);
+ }
}
}
@@ -476,19 +479,33 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
rv = aNode->Clone(nodeInfo, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
- if (clone->IsElement()) {
+ if (CustomElementRegistry::IsCustomElementEnabled() &&
+ clone->IsHTMLElement()) {
// The cloned node may be a custom element that may require
- // enqueing created callback and prototype swizzling.
- Element* elem = clone->AsElement();
- if (nsContentUtils::IsCustomElementName(nodeInfo->NameAtom())) {
- nsContentUtils::SetupCustomElement(elem);
- } else {
- // Check if node may be custom element by type extension.
- // ex. <button is="x-button">
- nsAutoString extension;
- if (elem->GetAttr(kNameSpaceID_None, nsGkAtoms::is, extension) &&
- !extension.IsEmpty()) {
- nsContentUtils::SetupCustomElement(elem, &extension);
+ // enqueing upgrade reaction.
+ Element* cloneElem = clone->AsElement();
+ RefPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
+ CustomElementData* data = elem->GetCustomElementData();
+
+ // Check if node may be custom element by type extension.
+ // ex. <button is="x-button">
+ nsAutoString extension;
+ if (!data || data->GetCustomElementType() != tagAtom) {
+ cloneElem->GetAttr(kNameSpaceID_None, nsGkAtoms::is, extension);
+ }
+
+ if (data || !extension.IsEmpty()) {
+ RefPtr<nsIAtom> typeAtom = extension.IsEmpty() ? tagAtom : NS_Atomize(extension);
+ cloneElem->SetCustomElementData(new CustomElementData(typeAtom));
+
+ MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
+ CustomElementDefinition* definition =
+ nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+ nodeInfo->NameAtom(),
+ nodeInfo->NamespaceID(),
+ typeAtom);
+ if (definition) {
+ nsContentUtils::EnqueueUpgradeReaction(cloneElem, definition);
}
}
}
@@ -523,6 +540,23 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
nsIDocument* newDoc = aNode->OwnerDoc();
if (newDoc) {
+ if (CustomElementRegistry::IsCustomElementEnabled()) {
+ // Adopted callback must be enqueued whenever a node’s
+ // shadow-including inclusive descendants that is custom.
+ Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
+ if (element) {
+ CustomElementData* data = element->GetCustomElementData();
+ if (data && data->mState == CustomElementData::State::eCustom) {
+ LifecycleAdoptedCallbackArgs args = {
+ oldDoc,
+ newDoc
+ };
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAdopted,
+ element, nullptr, &args);
+ }
+ }
+ }
+
// XXX what if oldDoc is null, we don't know if this should be
// registered or not! Can that really happen?
if (wasRegistered) {
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index 47affbb06..5c07bf4d4 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -303,11 +303,6 @@ public:
virtual bool CanClose() = 0;
virtual void ForceClose() = 0;
- bool IsModalContentWindow() const
- {
- return mIsModalContentWindow;
- }
-
/**
* Call this to indicate that some node (this window, its document,
* or content in that document) has a paint event listener.
@@ -629,11 +624,6 @@ protected:
// This member is only used by inner windows.
bool mInnerObjectsFreed;
-
- // This variable is used on both inner and outer windows (and they
- // should match).
- bool mIsModalContentWindow;
-
// Tracks activation state that's used for :-moz-window-inactive.
// Only used on outer windows.
bool mIsActive;
diff --git a/dom/base/nsSandboxFlags.h b/dom/base/nsSandboxFlags.h
index d18527597..b8c9ac357 100644
--- a/dom/base/nsSandboxFlags.h
+++ b/dom/base/nsSandboxFlags.h
@@ -29,8 +29,7 @@ const unsigned long SANDBOXED_NAVIGATION = 0x1;
/**
* This flag prevents content from creating new auxiliary browsing contexts,
- * e.g. using the target attribute, the window.open() method, or the
- * showModalDialog() method.
+ * e.g. using the target attribute, or the window.open() method.
*/
const unsigned long SANDBOXED_AUXILIARY_NAVIGATION = 0x2;
diff --git a/dom/base/test/chrome/registerElement_ep.js b/dom/base/test/chrome/registerElement_ep.js
index de32ba51c..9189593c0 100644
--- a/dom/base/test/chrome/registerElement_ep.js
+++ b/dom/base/test/chrome/registerElement_ep.js
@@ -1,8 +1,8 @@
var proto = Object.create(HTMLElement.prototype);
proto.magicNumber = 42;
-proto.createdCallback = function() {
+proto.connectedCallback = function() {
finishTest(this.magicNumber === 42);
};
document.registerElement("x-foo", { prototype: proto });
-document.createElement("x-foo");
+document.firstChild.appendChild(document.createElement("x-foo"));
diff --git a/dom/base/test/chrome/test_registerElement_content.xul b/dom/base/test/chrome/test_registerElement_content.xul
index 9a918f2d7..bf00ed53d 100644
--- a/dom/base/test/chrome/test_registerElement_content.xul
+++ b/dom/base/test/chrome/test_registerElement_content.xul
@@ -21,19 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
<script type="application/javascript"><![CDATA[
/** Test for Bug 1130028 **/
- SimpleTest.waitForExplicitFinish();
+ var connectedCallbackCount = 0;
- var createdCallbackCount = 0;
-
- // Callback should be called once by element created in chrome,
- // and once by element created in content.
- function createdCallbackCalled() {
- createdCallbackCount++;
- ok(true, "Created callback called, should be called twice in test.");
+ // Callback should be called only once by element created in content.
+ function connectedCallbackCalled() {
+ connectedCallbackCount++;
+ is(connectedCallbackCount, 1, "Connected callback called, should be called once in test.");
is(this.magicNumber, 42, "Callback should be able to see the custom prototype.");
- if (createdCallbackCount == 2) {
- SimpleTest.finish();
- }
}
function startTests() {
@@ -45,10 +39,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
var proto = Object.create(frame.contentWindow.HTMLElement.prototype);
proto.magicNumber = 42;
- proto.createdCallback = createdCallbackCalled;
+ proto.connectedCallback = connectedCallbackCalled;
+
frame.contentDocument.registerElement("x-bar", { prototype: proto });
+ is(connectedCallbackCount, 1, "Connected callback should be called by element created in content.");
- frame.contentDocument.createElement("x-bar");
+ var element = frame.contentDocument.createElement("x-bar");
+ is(element.magicNumber, 42, "Should be able to see the custom prototype on created element.");
}
]]></script>
diff --git a/dom/base/test/chrome/test_registerElement_ep.xul b/dom/base/test/chrome/test_registerElement_ep.xul
index 6f1745268..b6a160c2e 100644
--- a/dom/base/test/chrome/test_registerElement_ep.xul
+++ b/dom/base/test/chrome/test_registerElement_ep.xul
@@ -26,8 +26,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
SimpleTest.waitForExplicitFinish();
function finishTest(canSeePrototype) {
- ok(true, "createdCallback called when reigsterElement was called with an extended principal.");
- ok(canSeePrototype, "createdCallback should be able to see custom prototype.");
+ ok(true, "connectedCallback called when reigsterElement was called with an extended principal.");
+ ok(canSeePrototype, "connectedCallback should be able to see custom prototype.");
SimpleTest.finish();
}
diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
index b3b804ce4..3dfd666f8 100644
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -196,7 +196,6 @@ support-files =
formReset.html
invalid_accesscontrol.resource
invalid_accesscontrol.resource^headers^
- mutationobserver_dialog.html
orientationcommon.js
script-1_bug597345.sjs
script-2_bug597345.js
@@ -627,9 +626,6 @@ subsuite = clipboard
skip-if = toolkit == 'android' #bug 904183
[test_createHTMLDocument.html]
[test_declare_stylesheet_obsolete.html]
-[test_dialogArguments.html]
-tags = openwindow
-skip-if = toolkit == 'android' || e10s # showmodaldialog
[test_document.all_iteration.html]
[test_document.all_unqualified.html]
[test_document_constructor.html]
diff --git a/dom/base/test/mutationobserver_dialog.html b/dom/base/test/mutationobserver_dialog.html
deleted file mode 100644
index 2cc815309..000000000
--- a/dom/base/test/mutationobserver_dialog.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<html>
- <head>
- <title></title>
- <script>
-
- var div = document.createElement("div");
-
- var M;
- if ("MozMutationObserver" in window) {
- M = window.MozMutationObserver;
- } else if ("WebKitMutationObserver" in window) {
- M = window.WebKitMutationObserver;
- } else {
- M = window.MutationObserver;
- }
-
- var didCall1 = false;
- var didCall2 = false;
- function testMutationObserverInDialog() {
- div.innerHTML = "<span>1</span><span>2</span>";
- m = new M(function(records, observer) {
- opener.is(records[0].type, "childList", "Should have got childList");
- opener.is(records[0].removedNodes.length, 2, "Should have got removedNodes");
- opener.is(records[0].addedNodes.length, 1, "Should have got addedNodes");
- observer.disconnect();
- m = null;
- didCall1 = true;
- });
- m.observe(div, { childList: true });
- div.innerHTML = "<span><span>foo</span></span>";
- }
-
- function testMutationObserverInDialog2() {
- div.innerHTML = "<span>1</span><span>2</span>";
- m = new M(function(records, observer) {
- opener.is(records[0].type, "childList", "Should have got childList");
- opener.is(records[0].removedNodes.length, 2, "Should have got removedNodes");
- opener.is(records[0].addedNodes.length, 1, "Should have got addedNodes");
- observer.disconnect();
- m = null;
- didCall2 = true;
- });
- m.observe(div, { childList: true });
- div.innerHTML = "<span><span>foo</span></span>";
- }
-
- window.addEventListener("load", testMutationObserverInDialog);
- window.addEventListener("load", testMutationObserverInDialog2);
- window.addEventListener("load",
- function() {
- opener.ok(didCall1, "Should have called 1st mutation callback");
- opener.ok(didCall2, "Should have called 2nd mutation callback");
- window.close();
- });
- </script>
- <style>
- </style>
- </head>
- <body>
- <input type="button" onclick="window.close()" value="close">
- </body>
-</html>
diff --git a/dom/base/test/test_dialogArguments.html b/dom/base/test/test_dialogArguments.html
deleted file mode 100644
index 70a091d00..000000000
--- a/dom/base/test/test_dialogArguments.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>Test for Bug 1019761</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-
- <meta http-equiv="content-type" content="text/html; charset=utf-8">
-</head>
-<body>
-<script type="application/javascript">
-
-/*
- Tests whether Firefox crashes when accessing the dialogArguments property
- of a modal window that has been closed.
-*/
-SimpleTest.waitForExplicitFinish();
-
-function openModal() {
- showModalDialog("javascript:opener.winRef = window; \
- window.opener.setTimeout(\'winRef.dialogArguments;\', 0);\
- window.close();");
-
- ok(true, "dialogArguments did not cause a crash.");
- SimpleTest.finish();
-}
-
-window.onload = openModal;
-</script>
-</body>
-</html>
diff --git a/dom/base/test/test_mutationobservers.html b/dom/base/test/test_mutationobservers.html
index bde07c79c..7e4c99423 100644
--- a/dom/base/test/test_mutationobservers.html
+++ b/dom/base/test/test_mutationobservers.html
@@ -362,7 +362,7 @@ function testChildList5() {
is(records[5].previousSibling, c3, "");
is(records[5].nextSibling, c5, "");
observer.disconnect();
- then(testAdoptNode);
+ then(testNestedMutations);
m = null;
});
m.observe(div, { childList: true, subtree: true });
@@ -375,6 +375,37 @@ function testChildList5() {
div.appendChild(emptyDF); // empty document shouldn't cause mutation records
}
+function testNestedMutations() {
+ div.textContent = null;
+ div.appendChild(document.createTextNode("foo"));
+ var m2WasCalled = false;
+ m = new M(function(records, observer) {
+ is(records[0].type, "characterData", "Should have got characterData");
+ observer.disconnect();
+ m = null;
+ m3 = new M(function(records, observer) {
+ ok(m2WasCalled, "m2 should have been called before m3!");
+ is(records[0].type, "characterData", "Should have got characterData");
+ observer.disconnect();
+ then(testAdoptNode);
+ m3 = null;
+ });
+ m3.observe(div, { characterData: true, subtree: true});
+ div.firstChild.data = "foo";
+ });
+ m2 = new M(function(records, observer) {
+ m2WasCalled = true;
+ is(records[0].type, "characterData", "Should have got characterData");
+ observer.disconnect();
+ m2 = null;
+ });
+ m2.observe(div, { characterData: true, subtree: true});
+ div.appendChild(document.createTextNode("foo"));
+ m.observe(div, { characterData: true, subtree: true });
+
+ div.firstChild.data = "bar";
+}
+
function testAdoptNode() {
var d1 = document.implementation.createHTMLDocument(null);
var d2 = document.implementation.createHTMLDocument(null);
@@ -484,28 +515,6 @@ function testSyncXHR() {
function testSyncXHR2() {
ok(callbackHandled, "Should have called the mutation callback!");
- then(testModalDialog);
-}
-
-function testModalDialog() {
- var didHandleCallback = false;
- div.innerHTML = "<span>1</span><span>2</span>";
- m = new M(function(records, observer) {
- is(records[0].type, "childList", "Should have got childList");
- is(records[0].removedNodes.length, 2, "Should have got removedNodes");
- is(records[0].addedNodes.length, 1, "Should have got addedNodes");
- observer.disconnect();
- m = null;
- didHandleCallback = true;
- });
- m.observe(div, { childList: true });
- div.innerHTML = "<span><span>foo</span></span>";
- try {
- window.showModalDialog("mutationobserver_dialog.html");
- ok(didHandleCallback, "Should have called the callback while showing modal dialog!");
- } catch(e) {
- todo(false, "showModalDialog not implemented on this platform");
- }
then(testTakeRecords);
}
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index b244d4d2a..f76f14d95 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -16,13 +16,16 @@
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/Unused.h"
#include "mozilla/UseCounter.h"
+#include "mozilla/dom/DocGroup.h"
#include "AccessCheck.h"
#include "jsfriendapi.h"
+#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsIDocShell.h"
#include "nsIDOMGlobalPropertyInitializer.h"
+#include "nsIParserService.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsIXPConnect.h"
@@ -37,6 +40,7 @@
#include "nsGlobalWindow.h"
#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/DOMErrorBinding.h"
#include "mozilla/dom/DOMException.h"
@@ -44,6 +48,7 @@
#include "mozilla/dom/HTMLObjectElement.h"
#include "mozilla/dom/HTMLObjectElementBinding.h"
#include "mozilla/dom/HTMLSharedObjectElement.h"
+#include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/HTMLEmbedElementBinding.h"
#include "mozilla/dom/HTMLAppletElementBinding.h"
#include "mozilla/dom/Promise.h"
@@ -62,6 +67,30 @@ namespace dom {
using namespace workers;
+// Forward declare GetConstructorObject methods.
+#define HTML_TAG(_tag, _classname, _interfacename) \
+namespace HTML##_interfacename##ElementBinding { \
+ JSObject* GetConstructorObject(JSContext*); \
+}
+#define HTML_OTHER(_tag)
+#include "nsHTMLTagList.h"
+#undef HTML_TAG
+#undef HTML_OTHER
+
+typedef JSObject* (*constructorGetterCallback)(JSContext*);
+
+// Mapping of html tag and GetConstructorObject methods.
+#define HTML_TAG(_tag, _classname, _interfacename) HTML##_interfacename##ElementBinding::GetConstructorObject,
+#define HTML_OTHER(_tag) nullptr,
+// We use eHTMLTag_foo (where foo is the tag) which is defined in nsHTMLTags.h
+// to index into this array.
+static const constructorGetterCallback sConstructorGetterCallback[] = {
+ HTMLUnknownElementBinding::GetConstructorObject,
+#include "nsHTMLTagList.h"
+#undef HTML_TAG
+#undef HTML_OTHER
+};
+
const JSErrorFormatString ErrorFormatString[] = {
#define MSG_DEF(_name, _argc, _exn, _str) \
{ #_name, _str, _argc, _exn },
@@ -3377,6 +3406,189 @@ GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
return true;
}
+CustomElementReactionsStack*
+GetCustomElementReactionsStack(JS::Handle<JSObject*> aObj)
+{
+ // This might not be the right object, if there are wrappers. Unwrap if we can.
+ JSObject* obj = js::CheckedUnwrap(aObj);
+ if (!obj) {
+ return nullptr;
+ }
+
+ nsGlobalWindow* window = xpc::WindowGlobalOrNull(obj);
+ if (!window) {
+ return nullptr;
+ }
+
+ DocGroup* docGroup = window->AsInner()->GetDocGroup();
+ if (!docGroup) {
+ return nullptr;
+ }
+
+ return docGroup->CustomElementReactionsStack();
+}
+
+// https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor
+already_AddRefed<nsGenericHTMLElement>
+CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
+ JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv)
+{
+ // Step 1.
+ nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
+ if (!window) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ nsIDocument* doc = window->GetExtantDoc();
+ if (!doc) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ RefPtr<mozilla::dom::CustomElementRegistry> registry(window->CustomElements());
+ if (!registry) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ // Step 2 is in the code output by CGClassConstructor.
+ // Step 3.
+ JSContext* cx = aGlobal.Context();
+ JS::Rooted<JSObject*> newTarget(cx, &aCallArgs.newTarget().toObject());
+ CustomElementDefinition* definition =
+ registry->LookupCustomElementDefinition(cx, newTarget);
+ if (!definition) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
+ return nullptr;
+ }
+
+ // The callee might be an Xray. Unwrap it to get actual callee.
+ JS::Rooted<JSObject*> callee(cx, js::CheckedUnwrap(&aCallArgs.callee()));
+ if (!callee) {
+ aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+ return nullptr;
+ }
+
+ // And the actual callee might be in different compartment, so enter its
+ // compartment before getting the standard constructor object to compare to,
+ // so we get it from the same global as callee itself.
+ JSAutoCompartment ac(cx, callee);
+ int32_t tag = eHTMLTag_userdefined;
+ if (!definition->IsCustomBuiltIn()) {
+ // Step 4.
+ // If the definition is for an autonomous custom element, the active
+ // function should be HTMLElement.
+ JS::Rooted<JSObject*> constructor(cx, HTMLElementBinding::GetConstructorObject(cx));
+ if (!constructor) {
+ aRv.NoteJSContextException(cx);
+ return nullptr;
+ }
+
+ if (callee != constructor) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
+ return nullptr;
+ }
+ } else {
+ // Step 5.
+ // If the definition is for a customized built-in element, the localName
+ // should be defined in the specification.
+ nsIParserService* parserService = nsContentUtils::GetParserService();
+ if (!parserService) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ tag = parserService->HTMLCaseSensitiveAtomTagToId(definition->mLocalName);
+ if (tag == eHTMLTag_userdefined) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
+ return nullptr;
+ }
+
+ MOZ_ASSERT(tag <= NS_HTML_TAG_MAX, "tag is out of bounds");
+
+ // If the definition is for a customized built-in element, the active
+ // function should be the localname's element interface.
+ constructorGetterCallback cb = sConstructorGetterCallback[tag];
+ if (!cb) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
+ return nullptr;
+ }
+
+ JS::Rooted<JSObject*> constructor(cx, cb(cx));
+ if (!constructor) {
+ aRv.NoteJSContextException(cx);
+ return nullptr;
+ }
+
+ if (callee != constructor) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
+ return nullptr;
+ }
+ }
+
+ RefPtr<mozilla::dom::NodeInfo> nodeInfo =
+ doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
+ nullptr,
+ kNameSpaceID_XHTML,
+ nsIDOMNode::ELEMENT_NODE);
+ if (!nodeInfo) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ // Step 6 and Step 7 are in the code output by CGClassConstructor.
+ // Step 8.
+ nsTArray<RefPtr<nsGenericHTMLElement>>& constructionStack =
+ definition->mConstructionStack;
+ if (constructionStack.IsEmpty()) {
+ RefPtr<nsGenericHTMLElement> newElement;
+ if (tag == eHTMLTag_userdefined) {
+ // Autonomous custom element.
+ newElement = NS_NewHTMLElement(nodeInfo.forget());
+ } else {
+ // Customized built-in element.
+ newElement = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
+ }
+
+ newElement->SetCustomElementData(
+ new CustomElementData(definition->mType, CustomElementData::State::eCustom));
+
+ newElement->SetCustomElementDefinition(definition);
+
+ return newElement.forget();
+ }
+
+ // Step 9.
+ RefPtr<nsGenericHTMLElement>& element = constructionStack.LastElement();
+
+ // Step 10.
+ if (element == ALEADY_CONSTRUCTED_MARKER) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return nullptr;
+ }
+
+ // Step 11.
+ // Do prototype swizzling for upgrading a custom element here, for cases when
+ // we have a reflector already. If we don't have one yet, our caller will
+ // create it with the right proto (by calling DoGetOrCreateDOMReflector with
+ // that proto).
+ JS::Rooted<JSObject*> reflector(cx, element->GetWrapper());
+ if (reflector) {
+ // reflector might be in different compartment.
+ JSAutoCompartment ac(cx, reflector);
+ JS::Rooted<JSObject*> givenProto(cx, aGivenProto);
+ if (!JS_WrapObject(cx, &givenProto) ||
+ !JS_SetPrototype(cx, reflector, givenProto)) {
+ aRv.NoteJSContextException(cx);
+ return nullptr;
+ }
+ }
+
+ // Step 12 and Step 13.
+ return element.forget();
+}
+
#ifdef DEBUG
namespace binding_detail {
void
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 5cab835b3..e583d0e06 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -42,6 +42,7 @@
#include "nsWrapperCacheInlines.h"
+class nsGenericHTMLElement;
class nsIJSID;
namespace mozilla {
@@ -49,6 +50,7 @@ namespace mozilla {
enum UseCounter : int16_t;
namespace dom {
+class CustomElementReactionsStack;
template<typename KeyType, typename ValueType> class Record;
nsresult
@@ -3420,6 +3422,19 @@ bool
GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
JS::MutableHandle<JSObject*> aDesiredProto);
+// Get the CustomElementReactionsStack for the docgroup of the global
+// of the underlying object of aObj. This can be null if aObj can't
+// be CheckUnwrapped, or if the global of the result has no docgroup
+// (e.g. because it's not a Window global).
+CustomElementReactionsStack*
+GetCustomElementReactionsStack(JS::Handle<JSObject*> aObj);
+// This function is expected to be called from the constructor function for an
+// HTML element interface; the global/callargs need to be whatever was passed to
+// that constructor function.
+already_AddRefed<nsGenericHTMLElement>
+CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
+ JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
+
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter);
diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
index b00af2085..9428529f4 100644
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1638,6 +1638,15 @@ DOMInterfaces = {
'register': False,
},
+'TestHTMLConstructorInterface' : {
+ 'headerFile': 'TestBindingHeader.h',
+ 'register': False,
+ },
+
+'TestCEReactionsInterface' : {
+ 'headerFile': 'TestBindingHeader.h',
+ 'register': False,
+ },
}
# These are temporary, until they've been converted to use new DOM bindings
diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp
index bb01c804c..398acf9da 100644
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/CallbackObject.h"
+#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "jsfriendapi.h"
#include "nsIScriptGlobalObject.h"
@@ -79,7 +80,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
, mIsMainThread(NS_IsMainThread())
{
if (mIsMainThread) {
- nsContentUtils::EnterMicroTask();
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->EnterMicroTask();
+ }
}
// Compute the caller's subject principal (if necessary) early, before we
@@ -288,7 +292,10 @@ CallbackObject::CallSetup::~CallSetup()
// It is important that this is the last thing we do, after leaving the
// compartment and undoing all our entry/incumbent script changes
if (mIsMainThread) {
- nsContentUtils::LeaveMicroTask();
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->LeaveMicroTask();
+ }
}
}
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 6b23e8225..8ee732cca 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1747,6 +1747,71 @@ class CGClassConstructor(CGAbstractStaticMethod):
else:
ctorName = self.descriptor.interface.identifier.name
+ # [HTMLConstructor] for custom element
+ # This needs to live in bindings code because it directly examines
+ # newtarget and the callee function to do HTMLConstructor specific things.
+ if self._ctor.isHTMLConstructor():
+ htmlConstructorSanityCheck = dedent("""
+ // The newTarget might be a cross-compartment wrapper. Get the underlying object
+ // so we can do the spec's object-identity checks.
+ JS::Rooted<JSObject*> newTarget(cx, js::CheckedUnwrap(&args.newTarget().toObject()));
+ if (!newTarget) {
+ return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
+ }
+
+ // Step 2 of https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor.
+ // Enter the compartment of our underlying newTarget object, so we end
+ // up comparing to the constructor object for our interface from that global.
+ {
+ JSAutoCompartment ac(cx, newTarget);
+ JS::Handle<JSObject*> constructor(GetConstructorObjectHandle(cx));
+ if (!constructor) {
+ return false;
+ }
+ if (newTarget == constructor) {
+ return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
+ }
+ }
+
+ """)
+
+ # If we are unable to get desired prototype from newTarget, then we
+ # fall back to the interface prototype object from newTarget's realm.
+ htmlConstructorFallback = dedent("""
+ if (!desiredProto) {
+ // Step 7 of https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor.
+ // This fallback behavior is designed to match analogous behavior for the
+ // JavaScript built-ins. So we enter the compartment of our underlying
+ // newTarget object and fall back to the prototype object from that global.
+ // XXX The spec says to use GetFunctionRealm(), which is not actually
+ // the same thing as what we have here (e.g. in the case of scripted callable proxies
+ // whose target is not same-compartment with the proxy, or bound functions, etc).
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1317658
+ {
+ JSAutoCompartment ac(cx, newTarget);
+ desiredProto = GetProtoObjectHandle(cx);
+ if (!desiredProto) {
+ return false;
+ }
+ }
+
+ // desiredProto is in the compartment of the underlying newTarget object.
+ // Wrap it into the context compartment.
+ if (!JS_WrapObject(cx, &desiredProto)) {
+ return false;
+ }
+ }
+ """)
+ else:
+ htmlConstructorSanityCheck = ""
+ htmlConstructorFallback = ""
+
+
+ # If we're a constructor, "obj" may not be a function, so calling
+ # XrayAwareCalleeGlobal() on it is not safe. Of course in the
+ # constructor case either "obj" is an Xray or we're already in the
+ # content compartment, not the Xray compartment, so just
+ # constructing the GlobalObject from "obj" is fine.
preamble = fill(
"""
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@@ -1757,19 +1822,41 @@ class CGClassConstructor(CGAbstractStaticMethod):
// Adding more relocations
return ThrowConstructorWithoutNew(cx, "${ctorName}");
}
+
+ GlobalObject global(cx, obj);
+ if (global.Failed()) {
+ return false;
+ }
+
+ $*{htmlConstructorSanityCheck}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args, &desiredProto)) {
return false;
}
+ $*{htmlConstructorFallback}
""",
chromeOnlyCheck=chromeOnlyCheck,
- ctorName=ctorName)
-
- name = self._ctor.identifier.name
- nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
- callGenerator = CGMethodCall(nativeName, True, self.descriptor,
- self._ctor, isConstructor=True,
- constructorName=ctorName)
+ ctorName=ctorName,
+ htmlConstructorSanityCheck=htmlConstructorSanityCheck,
+ htmlConstructorFallback=htmlConstructorFallback)
+
+ if self._ctor.isHTMLConstructor():
+ signatures = self._ctor.signatures()
+ assert len(signatures) == 1
+ # Given that HTMLConstructor takes no args, we can just codegen a
+ # call to CreateHTMLElement() in BindingUtils which reuses the
+ # factory thing in HTMLContentSink. Then we don't have to implement
+ # Constructor on all the HTML elements.
+ callGenerator = CGPerSignatureCall(signatures[0][0], signatures[0][1],
+ "CreateHTMLElement", True,
+ self.descriptor, self._ctor,
+ isConstructor=True)
+ else:
+ name = self._ctor.identifier.name
+ nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
+ callGenerator = CGMethodCall(nativeName, True, self.descriptor,
+ self._ctor, isConstructor=True,
+ constructorName=ctorName)
return preamble + "\n" + callGenerator.define()
@@ -7386,7 +7473,7 @@ class CGPerSignatureCall(CGThing):
def __init__(self, returnType, arguments, nativeMethodName, static,
descriptor, idlNode, argConversionStartsAt=0, getter=False,
setter=False, isConstructor=False, useCounterName=None,
- resultVar=None):
+ resultVar=None, objectName="obj"):
assert idlNode.isMethod() == (not getter and not setter)
assert idlNode.isAttr() == (getter or setter)
# Constructors are always static
@@ -7440,26 +7527,23 @@ class CGPerSignatureCall(CGThing):
argsPre = []
if idlNode.isStatic():
- # If we're a constructor, "obj" may not be a function, so calling
- # XrayAwareCalleeGlobal() on it is not safe. Of course in the
- # constructor case either "obj" is an Xray or we're already in the
- # content compartment, not the Xray compartment, so just
- # constructing the GlobalObject from "obj" is fine.
- if isConstructor:
- objForGlobalObject = "obj"
- else:
- objForGlobalObject = "xpc::XrayAwareCalleeGlobal(obj)"
- cgThings.append(CGGeneric(fill(
- """
- GlobalObject global(cx, ${obj});
- if (global.Failed()) {
- return false;
- }
+ # If we're a constructor, the GlobalObject struct will be created in
+ # CGClassConstructor.
+ if not isConstructor:
+ cgThings.append(CGGeneric(dedent(
+ """
+ GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
+ if (global.Failed()) {
+ return false;
+ }
+
+ """)))
- """,
- obj=objForGlobalObject)))
argsPre.append("global")
+ if isConstructor and idlNode.isHTMLConstructor():
+ argsPre.extend(["args", "desiredProto"])
+
# For JS-implemented interfaces we do not want to base the
# needsCx decision on the types involved, just on our extended
# attributes. Also, JSContext is not needed for the static case
@@ -7588,6 +7672,17 @@ class CGPerSignatureCall(CGThing):
CGIfWrapper(CGList(xraySteps),
"objIsXray"))
+ if (idlNode.getExtendedAttribute('CEReactions') is not None and
+ not getter):
+ cgThings.append(CGGeneric(fill(
+ """
+ CustomElementReactionsStack* reactionsStack = GetCustomElementReactionsStack(${obj});
+ Maybe<AutoCEReaction> ceReaction;
+ if (reactionsStack) {
+ ceReaction.emplace(reactionsStack, cx);
+ }
+ """, obj=objectName)))
+
# If this is a method that was generated by a maplike/setlike
# interface, use the maplike/setlike generator to fill in the body.
# Otherwise, use CGCallGenerator to call the native method.
@@ -10985,7 +11080,8 @@ class CGProxySpecialOperation(CGPerSignatureCall):
# CGPerSignatureCall won't do any argument conversion of its own.
CGPerSignatureCall.__init__(self, returnType, arguments, nativeName,
False, descriptor, operation,
- len(arguments), resultVar=resultVar)
+ len(arguments), resultVar=resultVar,
+ objectName="proxy")
if operation.isSetter() or operation.isCreator():
# arguments[0] is the index or name of the item that we're setting.
@@ -13755,12 +13851,18 @@ class CGBindingRoot(CGThing):
iface = desc.interface
return any(m.getExtendedAttribute("Deprecated") for m in iface.members + [iface])
+ def descriptorHasCEReactions(desc):
+ iface = desc.interface
+ return any(m.getExtendedAttribute("CEReactions") for m in iface.members + [iface])
+
bindingHeaders["nsIDocument.h"] = any(
descriptorDeprecated(d) for d in descriptors)
bindingHeaders["mozilla/Preferences.h"] = any(
descriptorRequiresPreferences(d) for d in descriptors)
bindingHeaders["mozilla/dom/DOMJSProxyHandler.h"] = any(
d.concrete and d.proxy for d in descriptors)
+ bindingHeaders["mozilla/dom/CustomElementRegistry.h"] = any(
+ descriptorHasCEReactions(d) for d in descriptors)
def descriptorHasChromeOnly(desc):
ctor = desc.interface.ctor()
diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py
index 4f602365b..81911996d 100644
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1582,7 +1582,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
[self.location])
self._noInterfaceObject = True
- elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
+ elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
if identifier == "Constructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
@@ -1595,11 +1595,20 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
+ if identifier == "HTMLConstructor":
+ if not self.hasInterfaceObject():
+ raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
+ [self.location])
+
+ if not attr.noArguments():
+ raise WebIDLError(str(identifier) + " must take no arguments",
+ [attr.location])
+
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
- if identifier == "Constructor" or identifier == "ChromeConstructor":
+ if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
name = "constructor"
allowForbidden = True
else:
@@ -1610,7 +1619,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
allowForbidden=allowForbidden)
method = IDLMethod(self.location, methodIdentifier, retType,
- args, static=True)
+ args, static=True,
+ htmlConstructor=(identifier == "HTMLConstructor"))
# Constructors are always NewObject and are always
# assumed to be able to throw (since there's no way to
# indicate otherwise) and never have any other
@@ -1622,7 +1632,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
- if identifier == "Constructor" or identifier == "ChromeConstructor":
+ if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across
@@ -4073,6 +4083,11 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("Attribute returns a type that is not exposed "
"everywhere where the attribute is exposed",
[self.location])
+ if self.getExtendedAttribute("CEReactions"):
+ if self.readonly:
+ raise WebIDLError("[CEReactions] is not allowed on "
+ "readonly attributes",
+ [self.location])
def handleExtendedAttribute(self, attr):
identifier = attr.identifier()
@@ -4243,6 +4258,10 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("[Unscopable] is only allowed on non-static "
"attributes and operations",
[attr.location, self.location])
+ elif identifier == "CEReactions":
+ if not attr.noArguments():
+ raise WebIDLError("[CEReactions] must take no arguments",
+ [attr.location])
elif (identifier == "Pref" or
identifier == "Deprecated" or
identifier == "SetterThrows" or
@@ -4537,7 +4556,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
static=False, getter=False, setter=False, creator=False,
deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False, jsonifier=False,
- maplikeOrSetlikeOrIterable=None):
+ maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Method)
@@ -4567,6 +4586,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self._jsonifier = jsonifier
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
+ assert isinstance(htmlConstructor, bool)
+ # The identifier of a HTMLConstructor must be 'constructor'.
+ assert not htmlConstructor or identifier.name == "constructor"
+ self._htmlConstructor = htmlConstructor
self._specialType = specialType
self._unforgeable = False
self.dependsOn = "Everything"
@@ -4667,6 +4690,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self.isStringifier() or
self.isJsonifier())
+ def isHTMLConstructor(self):
+ return self._htmlConstructor
+
def hasOverloads(self):
return self._hasOverloads
@@ -4722,6 +4748,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert not method.isStringifier()
assert not self.isJsonifier()
assert not method.isJsonifier()
+ assert not self.isHTMLConstructor()
+ assert not method.isHTMLConstructor()
return self
@@ -4964,6 +4992,15 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[Unscopable] is only allowed on non-static "
"attributes and operations",
[attr.location, self.location])
+ elif identifier == "CEReactions":
+ if not attr.noArguments():
+ raise WebIDLError("[CEReactions] must take no arguments",
+ [attr.location])
+
+ if self.isSpecial() and not self.isSetter() and not self.isDeleter():
+ raise WebIDLError("[CEReactions] is only allowed on operation, "
+ "attribute, setter, and deleter",
+ [attr.location, self.location])
elif (identifier == "Throws" or
identifier == "NewObject" or
identifier == "ChromeOnly" or
diff --git a/dom/bindings/parser/tests/test_cereactions.py b/dom/bindings/parser/tests/test_cereactions.py
new file mode 100644
index 000000000..2f9397d90
--- /dev/null
+++ b/dom/bindings/parser/tests/test_cereactions.py
@@ -0,0 +1,162 @@
+def WebIDLTest(parser, harness):
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions(DOMString a)] void foo(boolean arg2);
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions(DOMString b)] readonly attribute boolean bar;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] attribute boolean bar;
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, e:
+ harness.ok(False, "Shouldn't have thrown for [CEReactions] used on writable attribute. %s" % e)
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] void foo(boolean arg2);
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, e:
+ harness.ok(False, "Shouldn't have thrown for [CEReactions] used on regular operations. %s" % e)
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] readonly attribute boolean A;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a readonly attribute")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [CEReactions]
+ interface Foo {
+ }
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a interface")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] getter any(DOMString name);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a named getter")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] creator boolean (DOMString name, boolean value);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a named creator")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] legacycaller double compute(double x);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a legacycaller")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] stringifier DOMString ();
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a stringifier")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] jsonifier;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")
diff --git a/dom/bindings/parser/tests/test_constructor.py b/dom/bindings/parser/tests/test_constructor.py
index 348204c7d..fb651c08d 100644
--- a/dom/bindings/parser/tests/test_constructor.py
+++ b/dom/bindings/parser/tests/test_constructor.py
@@ -13,7 +13,7 @@ def WebIDLTest(parser, harness):
def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False, creator=False,
deleter=False, legacycaller=False, stringifier=False,
- chromeOnly=False):
+ chromeOnly=False, htmlConstructor=False):
harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method")
@@ -29,6 +29,7 @@ def WebIDLTest(parser, harness):
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
+ harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
sigpairs = zip(method.signatures(), signatures)
@@ -80,6 +81,21 @@ def WebIDLTest(parser, harness):
parser = parser.reset()
parser.parse("""
+ [HTMLConstructor]
+ interface TestHTMLConstructor {
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results), 1, "Should be one production")
+ harness.ok(isinstance(results[0], WebIDL.IDLInterface),
+ "Should be an IDLInterface")
+
+ checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
+ "constructor", [("TestHTMLConstructor (Wrapper)", [])],
+ htmlConstructor=True)
+
+ parser = parser.reset()
+ parser.parse("""
[ChromeConstructor()]
interface TestChromeConstructor {
};
@@ -107,3 +123,151 @@ def WebIDLTest(parser, harness):
threw = True
harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
+
+ # Test HTMLConstructor with argument
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor(DOMString a)]
+ interface TestHTMLConstructorWithArgs {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "HTMLConstructor should take no argument")
+
+ # Test HTMLConstructor on a callback interface
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor]
+ callback interface TestHTMLConstructorOnCallbackInterface {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
+
+ # Test HTMLConstructor and Constructor
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [Constructor,
+ HTMLConstructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ Constructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ Constructor(DOMString a)]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [Constructor(DOMString a),
+ HTMLConstructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ # Test HTMLConstructor and ChromeConstructor
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [ChromeConstructor,
+ HTMLConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ ChromeConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [ChromeConstructor(DOMString a),
+ HTMLConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ ChromeConstructor(DOMString a)]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor") \ No newline at end of file
diff --git a/dom/bindings/parser/tests/test_constructor_no_interface_object.py b/dom/bindings/parser/tests/test_constructor_no_interface_object.py
index 2b09ae71e..af7b73d67 100644
--- a/dom/bindings/parser/tests/test_constructor_no_interface_object.py
+++ b/dom/bindings/parser/tests/test_constructor_no_interface_object.py
@@ -34,3 +34,36 @@ def WebIDLTest(parser, harness):
interface TestNamedConstructorNoInterfaceObject {
};
""")
+
+ # Test HTMLConstructor and NoInterfaceObject
+ parser = parser.reset()
+
+ threw = False
+ try:
+ parser.parse("""
+ [NoInterfaceObject, HTMLConstructor]
+ interface TestHTMLConstructorNoInterfaceObject {
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor, NoInterfaceObject]
+ interface TestHTMLConstructorNoInterfaceObject {
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown.") \ No newline at end of file
diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h
index ca5aafdc5..7d9963700 100644
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -939,6 +939,11 @@ public:
void NeedsCallerTypeMethod(CallerType);
bool NeedsCallerTypeAttr(CallerType);
void SetNeedsCallerTypeAttr(bool, CallerType);
+ void CeReactionsMethod();
+ void CeReactionsMethodOverload();
+ void CeReactionsMethodOverload(const nsAString&);
+ bool CeReactionsAttr() const;
+ void SetCeReactionsAttr(bool);
int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&);
void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&,
TestInterface*, const Dict&, double,
@@ -1425,6 +1430,31 @@ public:
void SetNeedsCallerTypeAttr(bool, CallerType);
};
+class TestHTMLConstructorInterface : public nsGenericHTMLElement
+{
+public:
+ virtual nsISupports* GetParentObject();
+};
+
+class TestCEReactionsInterface : public nsISupports,
+ public nsWrapperCache
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // We need a GetParentObject to make binding codegen happy
+ virtual nsISupports* GetParentObject();
+
+ int32_t Item(uint32_t);
+ uint32_t Length() const;
+ int32_t IndexedGetter(uint32_t, bool &);
+ void IndexedSetter(uint32_t, int32_t);
+ void NamedDeleter(const nsAString&, bool &);
+ void NamedGetter(const nsAString&, bool &, nsString&);
+ void NamedSetter(const nsAString&, const nsAString&);
+ void GetSupportedNames(nsTArray<nsString>&);
+};
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl
index 4fb9be270..3fce5e21b 100644
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -947,6 +947,10 @@ interface TestInterface {
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
+ [CEReactions] void ceReactionsMethod();
+ [CEReactions] void ceReactionsMethodOverload();
+ [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+ [CEReactions] attribute boolean ceReactionsAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,
@@ -1262,3 +1266,16 @@ interface TestWorkerExposedInterface {
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
};
+
+[HTMLConstructor]
+interface TestHTMLConstructorInterface {
+};
+
+interface TestCEReactionsInterface {
+ [CEReactions] setter creator void (unsigned long index, long item);
+ [CEReactions] setter creator void (DOMString name, DOMString item);
+ [CEReactions] deleter void (DOMString name);
+ getter long item(unsigned long index);
+ getter DOMString (DOMString name);
+ readonly attribute unsigned long length;
+};
diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl
index ea6387a84..a2183c002 100644
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -777,6 +777,10 @@ interface TestExampleInterface {
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
+ [CEReactions] void ceReactionsMethod();
+ [CEReactions] void ceReactionsMethodOverload();
+ [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+ [CEReactions] attribute boolean ceReactionsAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,
diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl
index a131dcdfe..a133b9981 100644
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -794,6 +794,10 @@ interface TestJSImplInterface {
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
+ [CEReactions] void ceReactionsMethod();
+ [CEReactions] void ceReactionsMethodOverload();
+ [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+ [CEReactions] attribute boolean ceReactionsAttr;
// NeedsSubjectPrincipal not supported on JS-implemented things for
// now, because we always pass in the caller principal anyway.
// [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
diff --git a/dom/bindings/test/test_bug560072.html b/dom/bindings/test/test_bug560072.html
index 82bb1c2c6..0eebff116 100644
--- a/dom/bindings/test/test_bug560072.html
+++ b/dom/bindings/test/test_bug560072.html
@@ -20,11 +20,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=560072
/** Test for Bug 560072 **/
is(document.body,
- Object.getOwnPropertyDescriptor(HTMLDocument.prototype, "body").get.call(document),
+ Object.getOwnPropertyDescriptor(Document.prototype, "body").get.call(document),
"Should get body out of property descriptor");
is(document.body,
- Object.getOwnPropertyDescriptor(Object.getPrototypeOf(document), "body").get.call(document),
+ Object.getOwnPropertyDescriptor(
+ Object.getPrototypeOf(Object.getPrototypeOf(document)), "body").get.call(document),
"Should get body out of property descriptor this way too");
</script>
diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp
index ebf0aa8c2..30d4c6522 100644
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -440,6 +440,13 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
{
MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized");
+ if (!gl->MakeCurrent(true)) {
+ MOZ_ASSERT(false);
+ *out_failReason = { "FEATURE_FAILURE_WEBGL_MAKECURRENT",
+ "Failed to MakeCurrent for init." };
+ return false;
+ }
+
// Unconditionally create a new format usage authority. This is
// important when restoring contexts and extensions need to add
// formats back into the authority.
diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp
index 0774c3296..2add7d009 100644
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -1087,7 +1087,10 @@ EventListenerManager::HandleEventSubType(Listener* aListener,
if (NS_SUCCEEDED(result)) {
if (mIsMainThreadELM) {
- nsContentUtils::EnterMicroTask();
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->EnterMicroTask();
+ }
}
// nsIDOMEvent::currentTarget is set in EventDispatcher.
if (listenerHolder.HasWebIDLCallback()) {
@@ -1099,7 +1102,10 @@ EventListenerManager::HandleEventSubType(Listener* aListener,
result = listenerHolder.GetXPCOMCallback()->HandleEvent(aDOMEvent);
}
if (mIsMainThreadELM) {
- nsContentUtils::LeaveMicroTask();
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->LeaveMicroTask();
+ }
}
}
diff --git a/dom/flyweb/FlyWebDiscoveryManager.cpp b/dom/flyweb/FlyWebDiscoveryManager.cpp
index 5a97eb6d8..14ad5aa1f 100644
--- a/dom/flyweb/FlyWebDiscoveryManager.cpp
+++ b/dom/flyweb/FlyWebDiscoveryManager.cpp
@@ -16,6 +16,7 @@
#include "mozilla/dom/FlyWebDiscoveryManager.h"
#include "mozilla/dom/FlyWebDiscoveryManagerBinding.h"
+#include "mozilla/dom/Element.h"
namespace mozilla {
namespace dom {
diff --git a/dom/html/HTMLDetailsElement.cpp b/dom/html/HTMLDetailsElement.cpp
index ed20b50ca..8619b1450 100644
--- a/dom/html/HTMLDetailsElement.cpp
+++ b/dom/html/HTMLDetailsElement.cpp
@@ -6,39 +6,11 @@
#include "mozilla/dom/HTMLDetailsElement.h"
#include "mozilla/dom/HTMLDetailsElementBinding.h"
-#include "mozilla/dom/HTMLUnknownElement.h"
-#include "mozilla/Preferences.h"
-
-// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Details) to add pref check.
-nsGenericHTMLElement*
-NS_NewHTMLDetailsElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
- mozilla::dom::FromParser aFromParser)
-{
- if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) {
- return new mozilla::dom::HTMLUnknownElement(aNodeInfo);
- }
-
- return new mozilla::dom::HTMLDetailsElement(aNodeInfo);
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Details)
namespace mozilla {
namespace dom {
-/* static */ bool
-HTMLDetailsElement::IsDetailsEnabled()
-{
- static bool isDetailsEnabled = false;
- static bool added = false;
-
- if (!added) {
- Preferences::AddBoolVarCache(&isDetailsEnabled,
- "dom.details_element.enabled");
- added = true;
- }
-
- return isDetailsEnabled;
-}
-
HTMLDetailsElement::~HTMLDetailsElement()
{
}
diff --git a/dom/html/HTMLDetailsElement.h b/dom/html/HTMLDetailsElement.h
index 5a3af27b4..6adf567bf 100644
--- a/dom/html/HTMLDetailsElement.h
+++ b/dom/html/HTMLDetailsElement.h
@@ -23,8 +23,6 @@ class HTMLDetailsElement final : public nsGenericHTMLElement
public:
using NodeInfo = mozilla::dom::NodeInfo;
- static bool IsDetailsEnabled();
-
explicit HTMLDetailsElement(already_AddRefed<NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
diff --git a/dom/html/HTMLElement.cpp b/dom/html/HTMLElement.cpp
index b2f23b931..d3901bdf3 100644
--- a/dom/html/HTMLElement.cpp
+++ b/dom/html/HTMLElement.cpp
@@ -52,3 +52,12 @@ NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
{
return new mozilla::dom::HTMLElement(aNodeInfo);
}
+
+// Distinct from the above in order to have function pointer that compared unequal
+// to a function pointer to the above.
+nsGenericHTMLElement*
+NS_NewCustomElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser)
+{
+ return new mozilla::dom::HTMLElement(aNodeInfo);
+}
diff --git a/dom/html/HTMLSummaryElement.cpp b/dom/html/HTMLSummaryElement.cpp
index ee3c07b20..42ead6b87 100644
--- a/dom/html/HTMLSummaryElement.cpp
+++ b/dom/html/HTMLSummaryElement.cpp
@@ -14,17 +14,7 @@
#include "mozilla/TextEvents.h"
#include "nsFocusManager.h"
-// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) to add pref check.
-nsGenericHTMLElement*
-NS_NewHTMLSummaryElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
- mozilla::dom::FromParser aFromParser)
-{
- if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) {
- return new mozilla::dom::HTMLUnknownElement(aNodeInfo);
- }
-
- return new mozilla::dom::HTMLSummaryElement(aNodeInfo);
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Summary)
namespace mozilla {
namespace dom {
diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index 0c8bcc9c8..78e4d5b95 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -497,7 +497,7 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// We need to consider a labels element is moved to another subtree
// with different root, it needs to update labels list and its root
// as well.
- nsDOMSlots* slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
}
@@ -524,7 +524,7 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
// We need to consider a labels element is removed from tree,
// it needs to update labels list and its root as well.
- nsDOMSlots* slots = GetExistingDOMSlots();
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
}
@@ -1730,7 +1730,7 @@ nsGenericHTMLElement::Labels()
{
MOZ_ASSERT(IsLabelable(),
"Labels() only allow labelable elements to use it.");
- nsDOMSlots* slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
if (!slots->mLabelsList) {
slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement,
diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h
index acbebe087..2b8b608b9 100644
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -1588,6 +1588,15 @@ protected:
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \
mNodeInfo->Equals(nsGkAtoms::_tag))
+namespace mozilla {
+namespace dom {
+
+typedef nsGenericHTMLElement* (*HTMLContentCreatorFunction)(
+ already_AddRefed<mozilla::dom::NodeInfo>&&,
+ mozilla::dom::FromParser aFromParser);
+
+} // namespace dom
+} // namespace mozilla
/**
* A macro to declare the NS_NewHTMLXXXElement() functions.
@@ -1636,6 +1645,13 @@ nsGenericHTMLElement*
NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
+// Distinct from the above in order to have function pointer that compared unequal
+// to a function pointer to the above.
+nsGenericHTMLElement*
+NS_NewCustomElement(
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
+
NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared)
NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject)
diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp
index 3e8e019b8..1fe5d2a86 100644
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -84,10 +84,6 @@ using namespace mozilla::dom;
//----------------------------------------------------------------------
-typedef nsGenericHTMLElement*
- (*contentCreatorCallback)(already_AddRefed<mozilla::dom::NodeInfo>&&,
- FromParser aFromParser);
-
nsGenericHTMLElement*
NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser)
@@ -96,14 +92,12 @@ NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
return nullptr;
}
-#define HTML_TAG(_tag, _classname) NS_NewHTML##_classname##Element,
-#define HTML_HTMLELEMENT_TAG(_tag) NS_NewHTMLElement,
+#define HTML_TAG(_tag, _classname, _interfacename) NS_NewHTML##_classname##Element,
#define HTML_OTHER(_tag) NS_NewHTMLNOTUSEDElement,
-static const contentCreatorCallback sContentCreatorCallbacks[] = {
+static const HTMLContentCreatorFunction sHTMLContentCreatorFunctions[] = {
NS_NewHTMLUnknownElement,
#include "nsHTMLTagList.h"
#undef HTML_TAG
-#undef HTML_HTMLELEMENT_TAG
#undef HTML_OTHER
NS_NewHTMLUnknownElement
};
@@ -234,9 +228,35 @@ public:
int32_t mStackPos;
};
+static void
+DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, nsIAtom* aLocalName,
+ CustomElementConstructor* aConstructor, ErrorResult& aRv)
+{
+ RefPtr<Element> element =
+ aConstructor->Construct("Custom Element Create", aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ if (!element || !element->IsHTMLElement()) {
+ aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement"));
+ return;
+ }
+
+ if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
+ element->HasChildren() || element->GetAttrCount() ||
+ element->NodeInfo()->NameAtom() != aLocalName) {
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ element.forget(aElement);
+}
+
nsresult
NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
- FromParser aFromParser, const nsAString* aIs)
+ FromParser aFromParser, const nsAString* aIs,
+ mozilla::dom::CustomElementDefinition* aDefinition)
{
*aResult = nullptr;
@@ -247,16 +267,109 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
return NS_ERROR_OUT_OF_MEMORY;
nsIAtom *name = nodeInfo->NameAtom();
+ RefPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
+ RefPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
"Trying to HTML elements that don't have the XHTML namespace");
int32_t tag = parserService->HTMLCaseSensitiveAtomTagToId(name);
- // Per the Custom Element specification, unknown tags that are valid custom
- // element names should be HTMLElement instead of HTMLUnknownElement.
bool isCustomElementName = (tag == eHTMLTag_userdefined &&
nsContentUtils::IsCustomElementName(name));
+ bool isCustomElement = isCustomElementName || aIs;
+ MOZ_ASSERT_IF(aDefinition, isCustomElement);
+
+ // https://dom.spec.whatwg.org/#concept-create-element
+ // We only handle the "synchronous custom elements flag is set" now.
+ // For the unset case (e.g. cloning a node), see bug 1319342 for that.
+ // Step 4.
+ CustomElementDefinition* definition = aDefinition;
+ if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement &&
+ !definition) {
+ MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
+ definition =
+ nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+ nodeInfo->NameAtom(),
+ nodeInfo->NamespaceID(),
+ typeAtom);
+ }
+
+ // It might be a problem that parser synchronously calls constructor, so filed
+ // bug 1378079 to figure out what we should do for parser case.
+ if (definition) {
+ /*
+ * Synchronous custom elements flag is determined by 3 places in spec,
+ * 1) create an element for a token, the flag is determined by
+ * "will execute script" which is not originally created
+ * for the HTML fragment parsing algorithm.
+ * 2) createElement and createElementNS, the flag is the same as
+ * NOT_FROM_PARSER.
+ * 3) clone a node, our implementation will not go into this function.
+ * For the unset case which is non-synchronous only applied for
+ * inner/outerHTML.
+ */
+ bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT ||
+ aFromParser == dom::NOT_FROM_PARSER;
+ // Per discussion in https://github.com/w3c/webcomponents/issues/635,
+ // use entry global in those places that are called from JS APIs and use the
+ // node document's global object if it is called from parser.
+ nsIGlobalObject* global;
+ if (aFromParser == dom::NOT_FROM_PARSER) {
+ global = GetEntryGlobal();
+ } else {
+ global = nodeInfo->GetDocument()->GetScopeObject();
+ }
+ if (!global) {
+ // In browser chrome code, one may have access to a document which doesn't
+ // have scope object anymore.
+ return NS_ERROR_FAILURE;
+ }
+
+ AutoEntryScript aes(global, "create custom elements");
+ JSContext* cx = aes.cx();
+ ErrorResult rv;
+
+ // Step 5.
+ if (definition->IsCustomBuiltIn()) {
+ // SetupCustomElement() should be called with an element that don't have
+ // CustomElementData setup, if not we will hit the assertion in
+ // SetCustomElementData().
+ // Built-in element
+ *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
+ (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
+ if (synchronousCustomElements) {
+ CustomElementRegistry::Upgrade(*aResult, definition, rv);
+ if (rv.MaybeSetPendingException(cx)) {
+ aes.ReportException();
+ }
+ } else {
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ }
+
+ return NS_OK;
+ }
+
+ // Step 6.1.
+ if (synchronousCustomElements) {
+ DoCustomElementCreate(aResult, nodeInfo->GetDocument(),
+ nodeInfo->NameAtom(),
+ definition->mConstructor, rv);
+ if (rv.MaybeSetPendingException(cx)) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
+ }
+ return NS_OK;
+ }
+
+ // Step 6.2.
+ NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
+ (*aResult)->SetCustomElementData(new CustomElementData(definition->mType));
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ return NS_OK;
+ }
+
+ // Per the Custom Element specification, unknown tags that are valid custom
+ // element names should be HTMLElement instead of HTMLUnknownElement.
if (isCustomElementName) {
NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
} else {
@@ -267,8 +380,8 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
return NS_ERROR_OUT_OF_MEMORY;
}
- if (isCustomElementName || aIs) {
- nsContentUtils::SetupCustomElement(*aResult, aIs);
+ if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement) {
+ (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
}
return NS_OK;
@@ -283,7 +396,7 @@ CreateHTMLElement(uint32_t aNodeType,
aNodeType == eHTMLTag_userdefined,
"aNodeType is out of bounds");
- contentCreatorCallback cb = sContentCreatorCallbacks[aNodeType];
+ HTMLContentCreatorFunction cb = sHTMLContentCreatorFunctions[aNodeType];
NS_ASSERTION(cb != NS_NewHTMLNOTUSEDElement,
"Don't know how to construct tag element!");
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index 0f2d90673..f530d75e1 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1013,26 +1013,6 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
rv = NodePrincipal()->SetDomain(newURI);
}
-nsGenericHTMLElement*
-nsHTMLDocument::GetBody()
-{
- Element* html = GetHtmlElement();
- if (!html) {
- return nullptr;
- }
-
- for (nsIContent* child = html->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (child->IsHTMLElement(nsGkAtoms::body) ||
- child->IsHTMLElement(nsGkAtoms::frameset)) {
- return static_cast<nsGenericHTMLElement*>(child);
- }
- }
-
- return nullptr;
-}
-
NS_IMETHODIMP
nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
{
@@ -1054,31 +1034,6 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
return rv.StealNSResult();
}
-void
-nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
-{
- nsCOMPtr<Element> root = GetRootElement();
-
- // The body element must be either a body tag or a frameset tag. And we must
- // have a html root tag, otherwise GetBody will not return the newly set
- // body.
- if (!newBody ||
- !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) ||
- !root || !root->IsHTMLElement() ||
- !root->IsHTMLElement(nsGkAtoms::html)) {
- rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
- return;
- }
-
- // Use DOM methods so that we pass through the appropriate security checks.
- nsCOMPtr<Element> currentBody = GetBodyElement();
- if (currentBody) {
- root->ReplaceChild(*newBody, *currentBody, rv);
- } else {
- root->AppendChild(*newBody, rv);
- }
-}
-
NS_IMETHODIMP
nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead)
{
@@ -1446,6 +1401,11 @@ nsHTMLDocument::Open(JSContext* cx,
return nullptr;
}
+ if (ShouldThrowOnDynamicMarkupInsertion()) {
+ aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return nullptr;
+ }
+
// Set up the content type for insertion
nsAutoCString contentType;
contentType.AssignLiteral("text/html");
@@ -1653,6 +1613,11 @@ nsHTMLDocument::Close(ErrorResult& rv)
return;
}
+ if (ShouldThrowOnDynamicMarkupInsertion()) {
+ rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
if (!mParser || !mParser->IsScriptCreated()) {
return;
}
@@ -1728,6 +1693,10 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
+ if (ShouldThrowOnDynamicMarkupInsertion()) {
+ return NS_ERROR_DOM_INVALID_STATE_ERR;
+ }
+
if (mParserAborted) {
// Hixie says aborting the parser doesn't undefine the insertion point.
// However, since we null out mParser in that case, we track the
diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h
index 1fa81f6cd..c9e46b3fa 100644
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -175,8 +175,8 @@ public:
JS::MutableHandle<JSObject*> aRetval,
mozilla::ErrorResult& rv);
void GetSupportedNames(nsTArray<nsString>& aNames);
- nsGenericHTMLElement *GetBody();
- void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
+ using nsIDocument::GetBody;
+ using nsIDocument::SetBody;
mozilla::dom::HTMLSharedElement *GetHead() {
return static_cast<mozilla::dom::HTMLSharedElement*>(GetHeadElement());
}
diff --git a/dom/html/test/file_iframe_sandbox_c_if4.html b/dom/html/test/file_iframe_sandbox_c_if4.html
index 53bf49559..828592d63 100644
--- a/dom/html/test/file_iframe_sandbox_c_if4.html
+++ b/dom/html/test/file_iframe_sandbox_c_if4.html
@@ -12,7 +12,7 @@
}
function doStuff() {
- // try to open a new window via target="_blank", target="BC341604", window.open(), and showModalDialog()
+ // try to open a new window via target="_blank", target="BC341604", and window.open()
// the window we try to open closes itself once it opens
sendMouseEvent({type:'click'}, 'target_blank');
sendMouseEvent({type:'click'}, 'target_BC341604');
@@ -25,15 +25,6 @@
}
ok(threw, "window.open threw a JS exception and was not allowed");
-
- threw = false;
- try {
- window.showModalDialog("about:blank");
- } catch(error) {
- threw = true;
- }
-
- ok(threw, "window.showModalDialog threw a JS exception and was not allowed");
}
</script>
<body onLoad="doStuff()">
diff --git a/dom/html/test/file_iframe_sandbox_j_if1.html b/dom/html/test/file_iframe_sandbox_j_if1.html
deleted file mode 100644
index 6d4347dfc..000000000
--- a/dom/html/test/file_iframe_sandbox_j_if1.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 766282</title>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-
-<script type="text/javascript">
- function doStuff() {
- // Open a new window via showModalDialog().
- try {
- window.showModalDialog("file_iframe_sandbox_k_if5.html");
- } catch(e) {
- window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
- }
-
- // Open a new window via showModalDialog().
- try {
- window.showModalDialog("file_iframe_sandbox_k_if7.html");
- } catch(e) {
- window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
- }
- }
-</script>
-
-<body onLoad="doStuff()">
- I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation".
-</body>
-</html>
diff --git a/dom/html/test/file_iframe_sandbox_j_if2.html b/dom/html/test/file_iframe_sandbox_j_if2.html
deleted file mode 100644
index 9552307ee..000000000
--- a/dom/html/test/file_iframe_sandbox_j_if2.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 766282</title>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-
-<script type="text/javascript">
- function doSubOpens() {
- // Open a new window showModalDialog().
- try {
- window.showModalDialog("file_iframe_sandbox_k_if9.html");
- } catch(e) {
- window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
- }
- }
-
- window.doSubOpens = doSubOpens;
-</script>
-
-<body>
- I am sandboxed but with "allow-scripts allow-popups allow-same-origin".
- After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html,
- which attemps to call a function in my parent.
- This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded.
-</body>
-</html>
diff --git a/dom/html/test/file_iframe_sandbox_j_if3.html b/dom/html/test/file_iframe_sandbox_j_if3.html
deleted file mode 100644
index 07c5b66c1..000000000
--- a/dom/html/test/file_iframe_sandbox_j_if3.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Tests for Bug 766282</title>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-
-</head>
-<script type="text/javascript">
- function ok(result, desc) {
- window.parent.ok_wrapper(result, desc);
- }
-
- function doStuff() {
- // Try to open a new window via showModalDialog().
- // The window we try to open closes itself once it opens.
- try {
- window.showModalDialog("file_iframe_sandbox_open_window_pass.html");
- } catch(e) {
- ok(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
- }
- }
-</script>
-<body onLoad="doStuff()">
- I am sandboxed but with "allow-popups allow-scripts allow-same-origin"
-</body>
-</html>
diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini
index 024de1cd9..4a50a9c3f 100644
--- a/dom/html/test/mochitest.ini
+++ b/dom/html/test/mochitest.ini
@@ -154,9 +154,6 @@ support-files =
file_iframe_sandbox_form_pass.html
file_iframe_sandbox_g_if1.html
file_iframe_sandbox_h_if1.html
- file_iframe_sandbox_j_if1.html
- file_iframe_sandbox_j_if2.html
- file_iframe_sandbox_j_if3.html
file_iframe_sandbox_k_if1.html
file_iframe_sandbox_k_if2.html
file_iframe_sandbox_k_if3.html
@@ -471,9 +468,6 @@ skip-if = toolkit == 'android' # just copy the conditions from the test above
tags = openwindow
[test_iframe_sandbox_inheritance.html]
tags = openwindow
-[test_iframe_sandbox_modal.html]
-tags = openwindow
-skip-if = toolkit == 'android' || e10s #modal tests fail on android
[test_iframe_sandbox_navigation.html]
tags = openwindow
[test_iframe_sandbox_navigation2.html]
@@ -540,8 +534,6 @@ skip-if = toolkit == 'android' #bug 811644
[test_bug369370.html]
skip-if = toolkit == "android" || toolkit == "windows" # disabled on Windows because of bug 1234520
[test_bug380383.html]
-[test_bug391777.html]
-skip-if = toolkit == 'android' || e10s
[test_bug402680.html]
[test_bug403868.html]
[test_bug403868.xhtml]
@@ -607,4 +599,4 @@ skip-if = os == "android" # up/down arrow keys not supported on android
[test_script_module.html]
support-files =
file_script_module.html
- file_script_nomodule.html \ No newline at end of file
+ file_script_nomodule.html
diff --git a/dom/html/test/test_bug391777.html b/dom/html/test/test_bug391777.html
deleted file mode 100644
index aa01a45de..000000000
--- a/dom/html/test/test_bug391777.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=391777
--->
-<head>
- <title>Test for Bug 391777</title>
- <script type="text/javascript" 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=391777">Mozilla Bug 391777</a>
-<p id="display"></p>
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 391777 **/
-var arg = {};
-arg.testVal = "foo";
-var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg);
-ok(true, "We should get here without user interaction");
-is(result, "foo", "Unexpected result from showModalDialog");
-
-</script>
-</body>
-</html>
diff --git a/dom/html/test/test_iframe_sandbox_general.html b/dom/html/test/test_iframe_sandbox_general.html
index 6d3a190ee..83f0e9045 100644
--- a/dom/html/test/test_iframe_sandbox_general.html
+++ b/dom/html/test/test_iframe_sandbox_general.html
@@ -41,7 +41,7 @@ function ok_wrapper(result, desc) {
passedTests++;
}
- if (completedTests == 33) {
+ if (completedTests == 32) {
is(passedTests, completedTests, "There are " + completedTests + " general tests that should pass");
SimpleTest.finish();
}
diff --git a/dom/html/test/test_iframe_sandbox_modal.html b/dom/html/test/test_iframe_sandbox_modal.html
deleted file mode 100644
index 1307ea9a5..000000000
--- a/dom/html/test/test_iframe_sandbox_modal.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=766282
-implement allow-popups directive for iframe sandbox
--->
-<head>
- <meta charset="utf-8">
- <title>Tests for Bug 766282</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-
-<script>
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("untriaged");
-
-// A postMessage handler that is used by sandboxed iframes without
-// 'allow-same-origin' to communicate pass/fail back to this main page.
-window.addEventListener("message", receiveMessage, false);
-
-function receiveMessage(event) {
- switch (event.data.type) {
- case "attempted":
- testAttempted();
- break;
- case "ok":
- ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
- break;
- default:
- // allow for old style message
- if (event.data.ok != undefined) {
- ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
- }
- }
-}
-
-var attemptedTests = 0;
-var passedTests = 0;
-var totalTestsToPass = 5;
-var totalTestsToAttempt = 5;
-
-function ok_wrapper(result, desc, addToAttempted = true) {
- ok(result, desc);
-
- if (result) {
- passedTests++;
- }
-
- if (addToAttempted) {
- testAttempted();
- }
-}
-
-// Added so that tests that don't register unless they fail,
-// can at least notify that they've attempted to run.
-function testAttempted() {
- attemptedTests++;
- if (attemptedTests == totalTestsToAttempt) {
- // Make sure all tests have had a chance to complete.
- setTimeout(function() {finish();}, 1000);
- }
-}
-
-var finishCalled = false;
-
-function finish() {
- if (!finishCalled) {
- finishCalled = true;
- is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " modal tests that should pass");
-
- SimpleTest.finish();
- }
-}
-
-function doTest() {
- // passes if good and fails if bad
- // 1) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
- // allow-same-origin" should not have its origin sandbox flag set and be able to access
- // document.cookie. (Done by file_iframe_sandbox_k_if5.html opened from
- // file_iframe_sandbox_j_if1.html) using showModalDialog.)
-
- // passes if good
- // 2) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
- // allow-top-navigation" should not have its top-level navigation sandbox flag set and be able to
- // navigate top. (Done by file_iframe_sandbox_k_if5.html (and if6) opened from
- // file_iframe_sandbox_j_if1.html) using showModalDialog.)
-
- // passes if good
- // 3) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
- // all-forms" should not have its forms sandbox flag set and be able to submit forms.
- // (Done by file_iframe_sandbox_k_if7.html opened from
- // file_iframe_sandbox_j_if1.html) using showModalDialog.)
-
- // passes if good
- // 4) Make sure that the sandbox flags copied to a new browsing context are taken from the
- // current active document not the browsing context (iframe / docShell).
- // This is done by removing allow-same-origin and calling doSubOpens from file_iframe_sandbox_j_if2.html,
- // which opens file_iframe_sandbox_k_if9.html using showModalDialog.
- var if_2 = document.getElementById('if_2');
- if_2.sandbox = 'allow-scripts allow-popups';
- if_2.contentWindow.doSubOpens();
-
- // passes if good
- // 5) Test that a sandboxed iframe with "allow-popups" can open a new window using window.ShowModalDialog.
- // This is done via file_iframe_sandbox_j_if3.html which is sandboxed with "allow-popups allow-scripts
- // allow-same-origin". The window it attempts to open calls window.opener.ok(true, ...) and
- // file_iframe_j_if3.html has an ok() function that calls window.parent.ok_wrapper.
-}
-
-addLoadEvent(doTest);
-</script>
-
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - implement allow-popups directive for iframe sandbox
-<p id="display"></p>
-<div id="content">
-<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin allow-forms allow-top-navigation" id="if_1" src="file_iframe_sandbox_j_if1.html" height="10" width="10"></iframe>
-<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin" id="if_2" src="file_iframe_sandbox_j_if2.html" height="10" width="10"></iframe>
-<iframe sandbox="allow-popups allow-modals allow-same-origin allow-scripts" id="if_3" src="file_iframe_sandbox_j_if3.html" height="10" width="10"></iframe>
-</div>
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index 90171db10..df1e6cbf5 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -46,6 +46,7 @@
#include "nsIWritablePropertyBag2.h"
#include "nsIContentSecurityPolicy.h"
#include "nsSandboxFlags.h"
+#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsILoadInfo.h"
#include "nsContentSecurityManager.h"
@@ -241,7 +242,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
// New script entry point required, due to the "Create a script" step of
// http://www.whatwg.org/specs/web-apps/current-work/#javascript-protocol
- nsAutoMicroTask mt;
+ mozilla::nsAutoMicroTask mt;
AutoEntryScript aes(innerGlobal, "javascript: URI", true);
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> globalJSObject(cx, innerGlobal->GetGlobalJSObject());
diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties
index 0472979d7..6bd3aac94 100644
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -174,8 +174,6 @@ UseOfCaptureEventsWarning=Use of captureEvents() is deprecated. To upgrade your
UseOfReleaseEventsWarning=Use of releaseEvents() is deprecated. To upgrade your code, use the DOM 2 removeEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.removeEventListener
# LOCALIZATION NOTE: Do not translate "document.load()" or "XMLHttpRequest"
UseOfDOM3LoadMethodWarning=Use of document.load() is deprecated. To upgrade your code, use the DOM XMLHttpRequest object. For more help https://developer.mozilla.org/en/XMLHttpRequest
-# LOCALIZATION NOTE: Do not translate "window.showModalDialog()" or "window.open()"
-ShowModalDialogWarning=Use of window.showModalDialog() is deprecated. Use window.open() instead. For more help https://developer.mozilla.org/en-US/docs/Web/API/Window.open
# LOCALIZATION NOTE: Do not translate "window._content" or "window.content"
Window_ContentWarning=window._content is deprecated. Please use window.content instead.
# LOCALIZATION NOTE: Do not translate "XMLHttpRequest"
diff --git a/dom/media/webspeech/recognition/test/test_nested_eventloop.html b/dom/media/webspeech/recognition/test/test_nested_eventloop.html
index bdbed6524..8b4cea6d7 100644
--- a/dom/media/webspeech/recognition/test/test_nested_eventloop.html
+++ b/dom/media/webspeech/recognition/test/test_nested_eventloop.html
@@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=650295
SimpleTest.waitForExplicitFinish();
/*
- * window.showModalDialog() can be used to spin the event loop, causing
+ * SpecialPowers.spinEventLoop can be used to spin the event loop, causing
* queued SpeechEvents (such as those created by calls to start(), stop()
* or abort()) to be processed immediately.
* When this is done from inside DOM event handlers, it is possible to
@@ -33,7 +33,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=650295
}
function doneFunc() {
// Trigger gc now and wait some time to make sure this test gets the blame
- // for any assertions caused by showModalDialog
+ // for any assertions caused by spinning the event loop.
//
// NB - The assertions should be gone, but this looks too scary to touch
// during batch cleanup.
diff --git a/dom/svg/SVGElementFactory.cpp b/dom/svg/SVGElementFactory.cpp
index abbb0a865..d3e922ee5 100644
--- a/dom/svg/SVGElementFactory.cpp
+++ b/dom/svg/SVGElementFactory.cpp
@@ -15,31 +15,28 @@ using namespace mozilla;
using namespace mozilla::dom;
// Hash table that maps nsIAtom* SVG tags to an offset index
-// within the array sContentCreatorCallbacks (offset by TABLE_VALUE_OFFSET)
+// within the array sSVGContentCreatorFunctions (offset by TABLE_VALUE_OFFSET)
static PLHashTable* sTagAtomTable = nullptr;
// We don't want to store 0 in the hash table as a return value of 0 from
// PL_HashTableLookupConst indicates that the value is not found
#define TABLE_VALUE_OFFSET 1
-#define SVG_TAG(_tag, _classname) \
-nsresult \
-NS_NewSVG##_classname##Element(nsIContent** aResult, \
- already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); \
-\
-static inline nsresult \
-Create##_classname##Element(nsIContent** aResult, \
- already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
- FromParser aFromParser) \
-{ \
- return NS_NewSVG##_classname##Element(aResult, mozilla::Move(aNodeInfo)); \
-}
+#define SVG_TAG(_tag, _classname) \
+ nsresult NS_NewSVG##_classname##Element( \
+ nsIContent** aResult, \
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); \
+ \
+ nsresult NS_NewSVG##_classname##Element( \
+ nsIContent** aResult, \
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ FromParser aFromParser) \
+ { \
+ return NS_NewSVG##_classname##Element(aResult, mozilla::Move(aNodeInfo)); \
+ }
+
+#define SVG_FROM_PARSER_TAG(_tag, _classname)
-#define SVG_FROM_PARSER_TAG(_tag, _classname) \
-nsresult \
-NS_NewSVG##_classname##Element(nsIContent** aResult, \
- already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
- FromParser aFromParser);
#include "SVGTagList.h"
#undef SVG_TAG
#undef SVG_FROM_PARSER_TAG
@@ -48,13 +45,8 @@ nsresult
NS_NewSVGElement(Element** aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
-typedef nsresult
- (*contentCreatorCallback)(nsIContent** aResult,
- already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
- FromParser aFromParser);
-
-static const contentCreatorCallback sContentCreatorCallbacks[] = {
-#define SVG_TAG(_tag, _classname) Create##_classname##Element,
+static const SVGContentCreatorFunction sSVGContentCreatorFunctions[] = {
+#define SVG_TAG(_tag, _classname) NS_NewSVG##_classname##Element,
#define SVG_FROM_PARSER_TAG(_tag, _classname) NS_NewSVG##_classname##Element,
#include "SVGTagList.h"
#undef SVG_TAG
@@ -124,7 +116,7 @@ NS_NewSVGElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& a
MOZ_CRASH();
}
- contentCreatorCallback cb = sContentCreatorCallbacks[index];
+ SVGContentCreatorFunction cb = sSVGContentCreatorFunctions[index];
nsCOMPtr<nsIContent> content;
nsresult rv = cb(getter_AddRefs(content), ni.forget(), aFromParser);
@@ -135,3 +127,15 @@ NS_NewSVGElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& a
// if we don't know what to create, just create a standard svg element:
return NS_NewSVGElement(aResult, ni.forget());
}
+
+nsresult
+NS_NewSVGUnknownElement(nsIContent** aResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ FromParser aFromParser)
+{
+ RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
+ nsCOMPtr<Element> element;
+ nsresult rv = NS_NewSVGElement(getter_AddRefs(element), ni.forget());
+ element.forget(aResult);
+ return rv;
+}
diff --git a/dom/svg/SVGElementFactory.h b/dom/svg/SVGElementFactory.h
index 3a75ef750..6d6fa1ca9 100644
--- a/dom/svg/SVGElementFactory.h
+++ b/dom/svg/SVGElementFactory.h
@@ -18,7 +18,32 @@ public:
static void Shutdown();
};
+typedef nsresult (*SVGContentCreatorFunction)(
+ nsIContent** aResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+
} // namespace dom
} // namespace mozilla
+#define SVG_TAG(_tag, _classname) \
+ nsresult NS_NewSVG##_classname##Element( \
+ nsIContent** aResult, \
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser);
+
+#define SVG_FROM_PARSER_TAG(_tag, _classname) \
+ nsresult NS_NewSVG##_classname##Element( \
+ nsIContent** aResult, \
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser);
+#include "SVGTagList.h"
+#undef SVG_TAG
+#undef SVG_FROM_PARSER_TAG
+
+nsresult
+NS_NewSVGUnknownElement(nsIContent** aResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+
#endif /* mozilla_dom_SVGElementFactory_h */
diff --git a/dom/svg/SVGTagList.h b/dom/svg/SVGTagList.h
index 219cafc43..6fb5c0bef 100644
--- a/dom/svg/SVGTagList.h
+++ b/dom/svg/SVGTagList.h
@@ -9,7 +9,14 @@
This file contains the list of all SVG tags.
It is designed to be used as inline input to SVGElementFactory.cpp
- *only* through the magic of C preprocessing.
+ through the magic of C preprocessing.
+
+ Additionally, it is consumed by the self-regeneration code in
+ ElementName.java from which nsHtml5ElementName.cpp/h is translated.
+ See parser/html/java/README.txt.
+
+ If you edit this list, you need to re-run ElementName.java
+ self-regeneration and the HTML parser Java to C++ translation.
All entries must be enclosed in the macro SVG_TAG or SVG_FROM_PARSER_TAG
which will have cruel and unusual things done to them.
diff --git a/dom/svg/moz.build b/dom/svg/moz.build
index 298a7293d..08cf1d78d 100644
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -14,6 +14,7 @@ EXPORTS += [
'SVGContentUtils.h',
'SVGPreserveAspectRatio.h',
'SVGStringList.h',
+ 'SVGTagList.h',
]
EXPORTS.mozilla.dom += [
@@ -39,6 +40,7 @@ EXPORTS.mozilla.dom += [
'SVGDefsElement.h',
'SVGDescElement.h',
'SVGDocument.h',
+ 'SVGElementFactory.h',
'SVGEllipseElement.h',
'SVGFEBlendElement.h',
'SVGFEColorMatrixElement.h',
diff --git a/dom/tests/mochitest/bugs/file_bug291653.html b/dom/tests/mochitest/bugs/file_bug291653.html
deleted file mode 100644
index 4bfc8337e..000000000
--- a/dom/tests/mochitest/bugs/file_bug291653.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
- <head>
- <script>
- <!--
- function listener1() {
- window.showModalDialog("data:text/html,<script>var maintest = opener.opener; opener.location = 'data:text/html,test'; maintest.end(); window.close();</script>");
- }
-
- function listener2() {
- opener.secondListenerDidRun = true;
- }
-
- window.addEventListener("foo", listener1);
- window.addEventListener("foo", listener2);
-
-
- function fireFoo() {
- var e = document.createEvent("Events");
- e.initEvent("foo", true, true);
- window.dispatchEvent(e);
- }
- //-->
- </script>
- </head>
- <body onload="setTimeout(fireFoo, 0)">
- Test for bug 291653
- </body>
-</html>
diff --git a/dom/tests/mochitest/bugs/file_bug504862.html b/dom/tests/mochitest/bugs/file_bug504862.html
deleted file mode 100644
index dc11ced6f..000000000
--- a/dom/tests/mochitest/bugs/file_bug504862.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html>
-<body>
-<script>
-window.returnValue = 3;
-
-if (location.toString().match(/^http:\/\/mochi.test:8888/)) {
- // Test that we got the right arguments.
- opener.is(window.dialogArguments, "my args",
- "dialog did not get the right arguments.");
-
- // Load a different url, and test that it sees the arguments (since it's same origin).
- window.location="data:text/html,<html><body onload=\"opener.is(window.dialogArguments, 'my args', 'subsequent dialog document did not get the right arguments.'); close();\">';";
-} else {
- // Post a message containing our arguments to the opener to test
- // that this cross origing dialog does *not* see the passed in
- // arguments.
- opener.postMessage("args: " + window.dialogArguments,
- "http://mochi.test:8888");
-
- close();
-}
-</script>
diff --git a/dom/tests/mochitest/bugs/mochitest.ini b/dom/tests/mochitest/bugs/mochitest.ini
index 309aab6e0..3743c6782 100644
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -10,9 +10,6 @@ support-files =
child_bug260264.html
devicemotion_inner.html
devicemotion_outer.html
- file_bug291653.html
- file_bug406375.html
- file_bug504862.html
file_bug593174_1.html
file_bug593174_2.html
file_bug809290_b1.html
@@ -45,7 +42,6 @@ skip-if = toolkit == 'android'
[test_bug260264_nested.html]
[test_bug265203.html]
[test_bug291377.html]
-[test_bug291653.html]
skip-if = toolkit == 'android' #TIMED_OUT
[test_bug304459.html]
[test_bug308856.html]
@@ -67,28 +63,21 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_bug396843.html]
[test_bug400204.html]
[test_bug404748.html]
-[test_bug406375.html]
-skip-if = toolkit == 'android'
-[test_bug414291.html]
-tags = openwindow
[test_bug427744.html]
skip-if = toolkit == 'android'
[test_bug42976.html]
[test_bug430276.html]
-[test_bug437361.html]
skip-if = toolkit == 'android'
[test_bug440572.html]
[test_bug456151.html]
[test_bug458091.html]
[test_bug459848.html]
[test_bug465263.html]
-[test_bug479143.html]
skip-if = toolkit == 'android'
[test_bug484775.html]
[test_bug492925.html]
[test_bug49312.html]
[test_bug495219.html]
-[test_bug504862.html]
skip-if = toolkit == 'android' #RANDOM
[test_bug529328.html]
[test_bug531176.html]
@@ -126,7 +115,6 @@ skip-if = toolkit == 'android'
[test_bug698061.html]
[test_bug698551.html]
[test_bug707749.html]
-[test_bug735237.html]
[test_bug739038.html]
[test_bug740811.html]
[test_bug743615.html]
diff --git a/dom/tests/mochitest/bugs/test_bug291653.html b/dom/tests/mochitest/bugs/test_bug291653.html
deleted file mode 100644
index 1543cdd96..000000000
--- a/dom/tests/mochitest/bugs/test_bug291653.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=291653
--->
-<head>
- <title>Test for Bug 291653</title>
- <script type="application/javascript" 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=291653">Mozilla Bug 291653</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 291653 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("untriaged");
-
-var secondListenerDidRun = false;
-
-var w;
-function start() {
- if ("showModalDialog" in window) {
- w = window.open("file_bug291653.html", "foo", "width=300,height=300");
- } else {
- // window.showModalDialog doesn't exist in e10s mode, nothing to do in this test.
- ok(true, "nothing to do in e10s mode");
- SimpleTest.finish();
- }
-}
-
-function closeTest() {
- w.setTimeout("close()", 0);
- setTimeout("finish()", 500);
-}
-
-function finish() {
- ok(!secondListenerDidRun, "Shouldn't have run second listener!");
- SimpleTest.finish();
-}
-
-function end() {
- setTimeout("closeTest()", 500);
-}
-
-start();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/bugs/test_bug406375.html b/dom/tests/mochitest/bugs/test_bug406375.html
deleted file mode 100644
index 2cd459ffa..000000000
--- a/dom/tests/mochitest/bugs/test_bug406375.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=406375
--->
-<head>
- <title>Test for Bug 406375</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body onload="runTest()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=406375">Mozilla Bug 406375</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 406375 **/
-
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
- if ("showModalDialog" in window) {
- window.showModalDialog("file_bug406375.html");
- }
- ok(true, "This test should not hang");
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/bugs/test_bug414291.html b/dom/tests/mochitest/bugs/test_bug414291.html
index 883e52bb4..0ee5cb393 100644
--- a/dom/tests/mochitest/bugs/test_bug414291.html
+++ b/dom/tests/mochitest/bugs/test_bug414291.html
@@ -16,7 +16,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=414291
var result1 = 0;
var result2 = 0;
-var result3 = 0;
window.open("data:text/html,<html><body onload='close(); opener.result1 = 1;'>", "w1");
is(result1, 0, "window should not be opened either as modal or loaded synchronously.");
@@ -24,11 +23,6 @@ is(result1, 0, "window should not be opened either as modal or loaded synchronou
window.open("data:text/html,<html><body onload='close(); opener.result2 = 2;'>", "w2", "modal=yes");
is(result2, 0, "window should not be opened either as modal or data loaded synchronously.");
-if (window.showModalDialog) {
- result3 = window.showModalDialog("data:text/html,<html><body onload='close(); returnValue = 3;'>");
- is(result3, 3, "window should be opened as modal.");
-}
-
</script>
</pre>
</body>
diff --git a/dom/tests/mochitest/bugs/test_bug437361.html b/dom/tests/mochitest/bugs/test_bug437361.html
deleted file mode 100644
index ecc2cb08d..000000000
--- a/dom/tests/mochitest/bugs/test_bug437361.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=437361
--->
-<head>
- <title>Test for Bug 437361</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
- <script class="testbody" type="text/javascript">
-
- /** Test for Bug 437361 **/
-
- function testModalDialogBlockedCleanly() {
- is(true, SpecialPowers.getBoolPref("dom.disable_open_during_load"), "mozprefs sanity check");
- var rv = window.showModalDialog( // should be blocked without exception
- "data:text/html,<html><body onload='close(); returnValue = 1;' /></html>");
- is(rv, null, "Modal dialog opened unexpectedly.");
- }
-
- function testModalDialogAllowed() {
- is(false, SpecialPowers.getBoolPref("dom.disable_open_during_load"), "mozprefs sanity check");
- var rv = window.showModalDialog( // should not be blocked this time
- "data:text/html,<html><body onload='close(); returnValue = 1;' /></html>");
- is(rv, 1, "Problem with modal dialog returnValue.");
- }
-
- function testOtherExceptionsNotTrapped() {
- is(false, SpecialPowers.getBoolPref("dom.disable_open_during_load"), "mozprefs sanity check");
- window.showModalDialog('about:config'); // forbidden by SecurityCheckURL
- }
-
- function test(disableOpen, exceptionExpected, testFn, errorMsg) {
- if ("showModalDialog" in window) {
- var oldPrefVal = SpecialPowers.getBoolPref("dom.disable_open_during_load");
- try {
- SpecialPowers.setBoolPref("dom.disable_open_during_load", disableOpen);
- testFn();
- ok(!exceptionExpected, errorMsg);
- } catch (_) {
- ok(exceptionExpected, errorMsg);
- }
- finally {
- SpecialPowers.setBoolPref("dom.disable_open_during_load", oldPrefVal);
- }
- } else {
- ok(true, "nothing to do in e10s mode");
- }
- }
-
- test(true, false, testModalDialogBlockedCleanly,
- "Blocked showModalDialog caused an exception.");
-
- test(false, false, testModalDialogAllowed,
- "showModalDialog was blocked even though dom.disable_open_during_load was false.");
-
- test(false, true, testOtherExceptionsNotTrapped,
- "Incorrectly suppressed insecure showModalDialog exception.");
-
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=437361">Mozilla Bug 437361</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>
-
diff --git a/dom/tests/mochitest/bugs/test_bug479143.html b/dom/tests/mochitest/bugs/test_bug479143.html
deleted file mode 100644
index 03db4ddea..000000000
--- a/dom/tests/mochitest/bugs/test_bug479143.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=479143
--->
-<head>
- <title>Test for Bug 411103</title>
- <script type="text/javascript" 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=479143">Mozilla Bug 479143</a>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
- SimpleTest.waitForExplicitFinish();
-
- setTimeout(function() {
- if ("showModalDialog" in window) {
- var interval = setInterval(function() { var i = 0; i++; }, 10);
-
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "test_bug479143.html", false);
- xhr.send(null);
-
- window.showModalDialog("javascript:" +
- "setTimeout(function() { window.close(); }, 1000);",
- null);
-
- clearInterval(interval);
- }
-
- ok(true, "did not crash");
-
- SimpleTest.finish();
- }, 0);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/bugs/test_bug504862.html b/dom/tests/mochitest/bugs/test_bug504862.html
deleted file mode 100644
index 713165bc3..000000000
--- a/dom/tests/mochitest/bugs/test_bug504862.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=504862
--->
-<head>
- <title>Test for Bug 504862</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body onload="runTest()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504862">Mozilla Bug 504862</a>
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 504862 **/
-SimpleTest.waitForExplicitFinish();
-function onMsgRcv(event)
-{
- is(event.data, "args: undefined", "Unexpected cross origin dialog arguments.");
-}
-
-function runTest() {
- if ("showModalDialog" in window) {
- window.addEventListener("message", onMsgRcv, false);
-
- var result = window.showModalDialog("file_bug504862.html", "my args");
- // NB: We used to clear returnValue on each navigation, but now we do a
- // security check on access, so we can safely make returnValue live on
- // the browsing context, per spec.
- is(result, 3, "window sees previous dialog documents return value.");
-
- result = window.showModalDialog("http://test1.example.com/tests/dom/tests/mochitest/bugs/file_bug504862.html", "my args");
-
- is(result, undefined, "Able to see return value from cross origin dialog.");
- } else {
- ok(true, "nothing to do in e10s mode");
- }
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/bugs/test_bug61098.html b/dom/tests/mochitest/bugs/test_bug61098.html
index 4c6ce967d..ed16e099b 100644
--- a/dom/tests/mochitest/bugs/test_bug61098.html
+++ b/dom/tests/mochitest/bugs/test_bug61098.html
@@ -306,28 +306,6 @@ function runtestsInner()
w.close();
- // Test that showModalDialog() works normally and then gets blocked
- // on the second call.
- if (window.showModalDialog) {
- w = window.open();
- w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
- is (promptState, void(0), "Wrong prompt state");
-
- try {
- w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
- ok(false, "showModalDialog call should throw an exception");
- } catch(e) {
- is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
- }
- is (promptState.method, "confirm", "Wrong prompt method called");
- is (promptState.parent, w, "Wrong confirm parent");
- is (promptState.msg, "Prevent this page from creating additional dialogs",
- "Wrong confirm message");
- promptState = void(0);
-
- w.close();
- }
-
mockPromptFactoryRegisterer.unregister();
mockPromptServiceRegisterer.unregister();
diff --git a/dom/tests/mochitest/bugs/test_bug735237.html b/dom/tests/mochitest/bugs/test_bug735237.html
deleted file mode 100644
index e1a25a425..000000000
--- a/dom/tests/mochitest/bugs/test_bug735237.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=735237
--->
-<head>
- <title>Test for Bug 735237</title>
- <script type="application/javascript" 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=735237">Mozilla Bug 735237</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 735237 **/
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_showModalDialog", true]]}, function() {
- var caughtException = false;
- try {
- window.showModalDialog("http://example.com/");
- } catch (e) {
- caughtException = true;
- }
- ok(caughtException, "showModalDialog should throw an exception");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/general/file_showModalDialog.html b/dom/tests/mochitest/general/file_showModalDialog.html
deleted file mode 100644
index 1cae0b1c0..000000000
--- a/dom/tests/mochitest/general/file_showModalDialog.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
- function go() {
- is(SpecialPowers.wrap(window).location.toString(), location.toString(), "sanity");
- ok("returnValue" in window && "dialogArguments" in window, "We are modal");
- var iwin = document.getElementById('ifr').contentWindow;
- is(SpecialPowers.Cu.getClassName(iwin, /* aUnwrap = */ true), "Window", "Descendant frames should not be modal");
-
- if (location.origin != "http://mochi.test:8888") {
- is(window.dialogArguments, undefined,
- "dialogArguments should be undefined cross-origin: " + location.origin);
- }
-
- window.returnValue = "rv: " + window.dialogArguments;
-
- // Allow for testing navigations in series.
- if (location.search == "") {
- window.close();
- } else {
- var origins = location.search.split('?')[1].split(',');
- var newsearch = '?' + origins.splice(1).join(',');
- var newurl = location.toString().replace(location.origin, origins[0])
- .replace(location.search, newsearch);
- location = newurl;
- }
-
- }
-</script>
-</head>
-<body onload="opener.postMessage('dosetup', '*');">
-<iframe id="ifr"></iframe>
-</body>
-</html>
diff --git a/dom/tests/mochitest/general/mochitest.ini b/dom/tests/mochitest/general/mochitest.ini
index d00ea1d4b..9f2fad785 100755
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -9,7 +9,6 @@ support-files =
file_interfaces.xml
file_moving_nodeList.html
file_moving_xhr.html
- file_showModalDialog.html
historyframes.html
image_50.png
image_100.png
@@ -116,8 +115,6 @@ support-files = test_offsets.js
[test_resource_timing_frameset.html]
[test_selectevents.html]
skip-if = toolkit == 'android' # bug 1230232 - Mouse doesn't select in the same way
-[test_showModalDialog.html]
-skip-if = e10s || toolkit == 'android' #Don't run modal tests on Android
[test_showModalDialog_e10s.html]
run-if = e10s
[test_storagePermissionsAccept.html]
diff --git a/dom/tests/mochitest/general/test_showModalDialog.html b/dom/tests/mochitest/general/test_showModalDialog.html
deleted file mode 100644
index 511c79e63..000000000
--- a/dom/tests/mochitest/general/test_showModalDialog.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=862918
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 862918</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- /** Test for window.showModalDialog. **/
-
- // The modal window needs to touch Cu, which means that it needs
- // SpecialPowers. But given the semantics of modal windows, we have to
- // do some funny stuff with postMessage to set this up.
- window.onmessage = function(evt) {
- is(evt.data, 'dosetup', "message from modal window is correct");
- var win = SpecialPowers.wrap(evt.source);
- win.wrappedJSObject.SpecialPowers = SpecialPowers;
- SpecialPowers.setWrapped(win.wrappedJSObject, 'is', SpecialPowers.wrap(is));
- SpecialPowers.setWrapped(win.wrappedJSObject, 'ok', SpecialPowers.wrap(ok));
- win.wrappedJSObject.go();
- };
-
- var someObj = { foo: 42, bar: "hi"};
- var xurl = location.toString()
- .replace('mochi.test:8888', 'example.org')
- .replace('test_showModal', 'file_showModal');
- if (xurl.indexOf('?') != -1)
- xurl = xurl.substring(0, xurl.indexOf('?'));
- is(showModalDialog('file_showModalDialog.html'), "rv: undefined");
- is(showModalDialog(xurl), undefined);
- is(showModalDialog('file_showModalDialog.html', 3), "rv: 3");
- is(showModalDialog(xurl, 3), undefined);
- is(showModalDialog('file_showModalDialog.html', someObj), "rv: " + someObj);
- is(showModalDialog(xurl, someObj), undefined);
-
- // Test sequential navigations.
- is(showModalDialog('file_showModalDialog.html?http://mochi.test:8888', 4),
- 'rv: 4');
- is(showModalDialog('file_showModalDialog.html?http://example.com', 4), undefined);
- is(showModalDialog('file_showModalDialog.html?http://example.com,http://mochi.test:8888', 4), 'rv: 4');
-
- // This test used to assert after gc. Make sure it doesn't.
- SpecialPowers.gc();
-
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=862918">Mozilla Bug 862918</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/chrome.ini b/dom/tests/mochitest/webcomponents/chrome.ini
new file mode 100644
index 000000000..5e25c2123
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/chrome.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+support-files =
+ dummy_page.html
+
+[test_custom_element_htmlconstructor_chrome.html]
+skip-if = os == 'android' # bug 1323645
+support-files =
+ htmlconstructor_autonomous_tests.js
+ htmlconstructor_builtin_tests.js
diff --git a/dom/tests/mochitest/webcomponents/dummy_page.html b/dom/tests/mochitest/webcomponents/dummy_page.html
new file mode 100644
index 000000000..fd238954c
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/dummy_page.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>Dummy test page</title>
+<meta charset="utf-8"/>
+</head>
+<body>
+<p>Dummy test page</p>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js b/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js
new file mode 100644
index 000000000..636d9aff6
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js
@@ -0,0 +1,81 @@
+promises.push(test_with_new_window((testWindow) => {
+ // Test calling the HTMLElement constructor.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ testWindow.HTMLElement();
+ }, 'calling the HTMLElement constructor should throw a TypeError');
+ })();
+
+ // Test constructing a HTMLELement.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ new testWindow.HTMLElement();
+ }, 'constructing a HTMLElement should throw a TypeError');
+ })();
+
+ // Test constructing a custom element with defining HTMLElement as entry.
+ (() => {
+ testWindow.customElements.define('x-defining-html-element',
+ testWindow.HTMLElement);
+ SimpleTest.doesThrow(() => {
+ new testWindow.HTMLElement();
+ }, 'constructing a custom element with defining HTMLElement as registry ' +
+ 'entry should throw a TypeError');
+ })();
+
+ // Test calling a custom element constructor and constructing an autonomous
+ // custom element.
+ (() => {
+ let num_constructor_invocations = 0;
+ class X extends testWindow.HTMLElement {
+ constructor() {
+ super();
+ num_constructor_invocations++;
+ }
+ }
+ testWindow.customElements.define('x-element', X);
+ SimpleTest.doesThrow(() => {
+ X();
+ }, 'calling an autonomous custom element constructor should throw a TypeError');
+
+ let element = new X();
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(element)), X.prototype,
+ 'constructing an autonomous custom element; ' +
+ 'the element should be a registered constructor');
+ SimpleTest.is(element.localName, 'x-element',
+ 'constructing an autonomous custom element; ' +
+ 'the element tag name should be "x-element"');
+ SimpleTest.is(element.namespaceURI, 'http://www.w3.org/1999/xhtml',
+ 'constructing an autonomous custom element; ' +
+ 'the element should be in the HTML namespace');
+ SimpleTest.is(element.prefix, null,
+ 'constructing an autonomous custom element; ' +
+ 'the element name should not have a prefix');
+ SimpleTest.is(element.ownerDocument, testWindow.document,
+ 'constructing an autonomous custom element; ' +
+ 'the element should be owned by the registry\'s associated ' +
+ 'document');
+ SimpleTest.is(num_constructor_invocations, 1,
+ 'constructing an autonomous custom element; ' +
+ 'the constructor should have been invoked once');
+ })();
+
+ // Test if prototype is no an object.
+ (() => {
+ function ElementWithNonObjectPrototype() {
+ let o = Reflect.construct(testWindow.HTMLElement, [], new.target);
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(o)), window.HTMLElement.prototype,
+ 'constructing an autonomous custom element; ' +
+ 'if prototype is not object, fallback from NewTarget\'s realm');
+ }
+
+ // Prototype have to be an object during define(), otherwise define will
+ // throw an TypeError exception.
+ ElementWithNonObjectPrototype.prototype = {};
+ testWindow.customElements.define('x-non-object-prototype',
+ ElementWithNonObjectPrototype);
+
+ ElementWithNonObjectPrototype.prototype = "string";
+ new ElementWithNonObjectPrototype();
+ })();
+}));
diff --git a/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js b/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js
new file mode 100644
index 000000000..dd6515148
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js
@@ -0,0 +1,247 @@
+[
+ // [TagName, InterfaceName]
+ ['a', 'Anchor'],
+ ['abbr', ''],
+ ['acronym', ''],
+ ['address', ''],
+ ['area', 'Area'],
+ ['article', ''],
+ ['aside', ''],
+ ['audio', 'Audio'],
+ ['b', ''],
+ ['base', 'Base'],
+ ['basefont', ''],
+ ['bdo', ''],
+ ['big', ''],
+ ['blockquote', 'Quote'],
+ ['body', 'Body'],
+ ['br', 'BR'],
+ ['button', 'Button'],
+ ['canvas', 'Canvas'],
+ ['caption', 'TableCaption'],
+ ['center', ''],
+ ['cite', ''],
+ ['code', ''],
+ ['col', 'TableCol'],
+ ['colgroup', 'TableCol'],
+ ['data', 'Data'],
+ ['datalist', 'DataList'],
+ ['dd', ''],
+ ['del', 'Mod'],
+ ['details', 'Details'],
+ ['dfn', ''],
+ ['dir', 'Directory'],
+ ['div', 'Div'],
+ ['dl', 'DList'],
+ ['dt', ''],
+ ['em', ''],
+ ['embed', 'Embed'],
+ ['fieldset', 'FieldSet'],
+ ['figcaption', ''],
+ ['figure', ''],
+ ['font', 'Font'],
+ ['footer', ''],
+ ['form', 'Form'],
+ ['frame', 'Frame'],
+ ['frameset', 'FrameSet'],
+ ['h1', 'Heading'],
+ ['h2', 'Heading'],
+ ['h3', 'Heading'],
+ ['h4', 'Heading'],
+ ['h5', 'Heading'],
+ ['h6', 'Heading'],
+ ['head', 'Head'],
+ ['header', ''],
+ ['hgroup', ''],
+ ['hr', 'HR'],
+ ['html', 'Html'],
+ ['i', ''],
+ ['iframe', 'IFrame'],
+ ['image', ''],
+ ['img', 'Image'],
+ ['input', 'Input'],
+ ['ins', 'Mod'],
+ ['kbd', ''],
+ ['label', 'Label'],
+ ['legend', 'Legend'],
+ ['li', 'LI'],
+ ['link', 'Link'],
+ ['listing', 'Pre'],
+ ['main', ''],
+ ['map', 'Map'],
+ ['mark', ''],
+ ['marquee', 'Div'],
+ ['menu', 'Menu'],
+ ['menuitem', 'MenuItem'],
+ ['meta', 'Meta'],
+ ['meter', 'Meter'],
+ ['nav', ''],
+ ['nobr', ''],
+ ['noembed', ''],
+ ['noframes', ''],
+ ['noscript', ''],
+ ['object', 'Object'],
+ ['ol', 'OList'],
+ ['optgroup', 'OptGroup'],
+ ['option', 'Option'],
+ ['output', 'Output'],
+ ['p', 'Paragraph'],
+ ['param', 'Param'],
+ ['picture', 'Picture'],
+ ['plaintext', ''],
+ ['pre', 'Pre'],
+ ['progress', 'Progress'],
+ ['q', 'Quote'],
+ ['rb', ''],
+ ['rp', ''],
+ ['rt', ''],
+ ['rtc', ''],
+ ['ruby', ''],
+ ['s', ''],
+ ['samp', ''],
+ ['script', 'Script'],
+ ['section', ''],
+ ['select', 'Select'],
+ ['small', ''],
+ ['source', 'Source'],
+ ['span', 'Span'],
+ ['strike', ''],
+ ['strong', ''],
+ ['style', 'Style'],
+ ['sub', ''],
+ ['summary', ''],
+ ['sup', ''],
+ ['table', 'Table'],
+ ['tbody', 'TableSection'],
+ ['td', 'TableCell'],
+ ['textarea', 'TextArea'],
+ ['tfoot', 'TableSection'],
+ ['th', 'TableCell'],
+ ['thead', 'TableSection'],
+ ['template', 'Template'],
+ ['time', 'Time'],
+ ['title', 'Title'],
+ ['tr', 'TableRow'],
+ ['track', 'Track'],
+ ['tt', ''],
+ ['u', ''],
+ ['ul', 'UList'],
+ ['var', ''],
+ ['video', 'Video'],
+ ['wbr', ''],
+ ['xmp', 'Pre'],
+].forEach((e) => {
+ let tagName = e[0];
+ let interfaceName = 'HTML' + e[1] + 'Element';
+ promises.push(test_with_new_window((testWindow) => {
+ // Use window from iframe to isolate the test.
+ // Test calling the HTML*Element constructor.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ testWindow[interfaceName]();
+ }, 'calling the ' + interfaceName + ' constructor should throw a TypeError');
+ })();
+
+ // Test constructing a HTML*ELement.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ new testWindow[interfaceName]();
+ }, 'constructing a ' + interfaceName + ' should throw a TypeError');
+ })();
+
+ // Test constructing a custom element with defining HTML*Element as entry.
+ (() => {
+ testWindow.customElements.define('x-defining-' + tagName,
+ testWindow[interfaceName]);
+ SimpleTest.doesThrow(() => {
+ new testWindow[interfaceName]();
+ }, 'constructing a custom element with defining ' + interfaceName +
+ ' as registry entry should throw a TypeError');
+ })();
+
+ // Since HTMLElement can be registered without specifying "extends", skip
+ // testing HTMLElement tags.
+ if (interfaceName !== "HTMLElement") {
+ // Test constructing a customized HTML*Element with defining a registry entry
+ // without specifying "extends".
+ (() => {
+ class X extends testWindow[interfaceName] {}
+ testWindow.customElements.define('x-defining-invalid-' + tagName, X);
+ SimpleTest.doesThrow(() => {
+ new X();
+ }, 'constructing a customized ' + interfaceName + ' with defining a ' +
+ 'registry entry without specifying "extends" should throw a TypeError');
+ })();
+ }
+
+ // Test constructing a built-in custom element with defining a registry entry
+ // with incorrect "extends" information.
+ (() => {
+ class X extends testWindow[interfaceName] {}
+ testWindow.customElements.define('x-defining-incorrect-' + tagName, X,
+ { extends: tagName === 'img' ? 'p' : 'img' });
+ SimpleTest.doesThrow(() => {
+ new X();
+ }, 'constructing a customized ' + interfaceName + ' with defining a ' +
+ 'registry entry with incorrect "extends" should throw a TypeError');
+ })();
+
+ // Test calling a custom element constructor and constructing a built-in
+ // custom element.
+ (() => {
+ let num_constructor_invocations = 0;
+ class X extends testWindow[interfaceName] {
+ constructor() {
+ super();
+ num_constructor_invocations++;
+ }
+ }
+ testWindow.customElements.define('x-' + tagName, X, { extends: tagName });
+ SimpleTest.doesThrow(() => {
+ X();
+ }, 'calling a customized ' + interfaceName + ' constructor should throw a TypeError');
+
+ let element = new X();
+
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(element)), X.prototype,
+ 'constructing a customized ' + interfaceName +
+ '; the element should be a registered constructor');
+ SimpleTest.is(element.localName, tagName,
+ 'constructing a customized ' + interfaceName +
+ '; the element tag name should be "' + tagName + '"');
+ SimpleTest.is(element.namespaceURI, 'http://www.w3.org/1999/xhtml',
+ 'constructing a customized ' + interfaceName +
+ '; the element should be in the HTML namespace');
+ SimpleTest.is(element.prefix, null,
+ 'constructing a customized ' + interfaceName +
+ '; the element name should not have a prefix');
+ SimpleTest.is(element.ownerDocument, testWindow.document,
+ 'constructing a customized ' + interfaceName +
+ '; the element should be owned by the registry\'s associated ' +
+ 'document');
+ SimpleTest.is(num_constructor_invocations, 1,
+ 'constructing a customized ' + interfaceName +
+ '; the constructor should have been invoked once');
+ })();
+
+ // Test if prototype is no an object.
+ (() => {
+ function ElementWithNonObjectPrototype() {
+ let o = Reflect.construct(testWindow[interfaceName], [], new.target);
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(o)), window[interfaceName].prototype,
+ 'constructing a customized ' + interfaceName +
+ '; if prototype is not object, fallback from NewTarget\'s realm');
+ }
+
+ // Prototype have to be an object during define(), otherwise define will
+ // throw an TypeError exception.
+ ElementWithNonObjectPrototype.prototype = {};
+ testWindow.customElements.define('x-non-object-prototype-' + tagName,
+ ElementWithNonObjectPrototype,
+ { extends: tagName });
+
+ ElementWithNonObjectPrototype.prototype = "string";
+ new ElementWithNonObjectPrototype();
+ })();
+ }));
+});
diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini
index 496f7ea4d..f5d0f84ea 100644
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -1,21 +1,28 @@
[DEFAULT]
support-files =
inert_style.css
+ dummy_page.html
[test_bug900724.html]
[test_bug1017896.html]
[test_bug1176757.html]
[test_bug1276240.html]
[test_content_element.html]
-[test_custom_element_adopt_callbacks.html]
[test_custom_element_callback_innerhtml.html]
-[test_custom_element_clone_callbacks.html]
-[test_custom_element_clone_callbacks_extended.html]
-[test_custom_element_import_node_created_callback.html]
+skip-if = true # disabled - See bug 1390396
+[test_custom_element_htmlconstructor.html]
+skip-if = os == 'android' # bug 1323645
+support-files =
+ htmlconstructor_autonomous_tests.js
+ htmlconstructor_builtin_tests.js
[test_custom_element_in_shadow.html]
+skip-if = true || stylo # disabled - See bug 1390396 and 1293844
[test_custom_element_register_invalid_callbacks.html]
+[test_custom_element_throw_on_dynamic_markup_insertion.html]
[test_custom_element_get.html]
[test_custom_element_when_defined.html]
+[test_custom_element_uncatchable_exception.html]
+skip-if = !debug # TestFunctions only applied in debug builds
[test_nested_content_element.html]
[test_dest_insertion_points.html]
[test_dest_insertion_points_shadow.html]
@@ -25,10 +32,11 @@ support-files =
[test_document_adoptnode.html]
[test_document_importnode.html]
[test_document_register.html]
-[test_document_register_base_queue.html]
[test_document_register_lifecycle.html]
+skip-if = true # disabled - See bug 1390396
[test_document_register_parser.html]
[test_document_register_stack.html]
+skip-if = true # disabled - See bug 1390396
[test_document_shared_registry.html]
[test_event_dispatch.html]
[test_event_retarget.html]
diff --git a/dom/tests/mochitest/webcomponents/test_bug1276240.html b/dom/tests/mochitest/webcomponents/test_bug1276240.html
index 33e532a6a..ded8d8276 100644
--- a/dom/tests/mochitest/webcomponents/test_bug1276240.html
+++ b/dom/tests/mochitest/webcomponents/test_bug1276240.html
@@ -47,7 +47,7 @@ test();
// test with webcomponents disabled
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
- { 'set': [["dom.webcomponents.enabled", false]]}, runTest);
+ { 'set': [["dom.webcomponents.customelements.enabled", false]]}, runTest);
</script>
</pre>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_adopt_callbacks.html b/dom/tests/mochitest/webcomponents/test_custom_element_adopt_callbacks.html
deleted file mode 100644
index 28597b7c6..000000000
--- a/dom/tests/mochitest/webcomponents/test_custom_element_adopt_callbacks.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1081039
--->
-<head>
- <title>Test callbacks for adopted custom elements.</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<template id="template"><x-foo></x-foo></template>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081039">Bug 1081039</a>
-<script>
-
-var p = Object.create(HTMLElement.prototype);
-p.createdCallback = function() {
- ok(false, "Created callback should not be called for adopted node.");
-};
-
-document.registerElement("x-foo", { prototype: p });
-
-var template = document.getElementById("template");
-var adoptedFoo = document.adoptNode(template.content.firstChild);
-is(adoptedFoo.nodeName, "X-FOO");
-
-</script>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html b/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
index 94b02032f..bb5008538 100644
--- a/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
@@ -16,7 +16,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1102502
SimpleTest.waitForExplicitFinish();
-var attachedCallbackCount = 0;
+var connectedCallbackCount = 0;
var p = Object.create(HTMLElement.prototype);
@@ -24,12 +24,12 @@ p.createdCallback = function() {
ok(true, "createdCallback called.");
};
-p.attachedCallback = function() {
- ok(true, "attachedCallback should be called when the parser creates an element in the document.");
- attachedCallbackCount++;
- // attachedCallback should be called twice, once for the element created for innerHTML and
+p.connectedCallback = function() {
+ ok(true, "connectedCallback should be called when the parser creates an element in the document.");
+ connectedCallbackCount++;
+ // connectedCallback should be called twice, once for the element created for innerHTML and
// once for the element created in this document.
- if (attachedCallbackCount == 2) {
+ if (connectedCallbackCount == 2) {
SimpleTest.finish();
}
}
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks.html b/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks.html
deleted file mode 100644
index eea9bafe0..000000000
--- a/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1081039
--->
-<head>
- <title>Test callbacks for cloned custom elements.</title>
- <script type="text/javascript" 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=1081039">Bug 1081039</a>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-// Test to make sure created callback is called on clones that are upgraded and clones
-// created after registering the custom element.
-
-var callbackCalledOnUpgrade = false;
-var callbackCalledOnClone = false;
-
-var foo = document.createElement("x-foo");
-var fooClone = foo.cloneNode(true);
-
-var p = Object.create(HTMLElement.prototype);
-p.createdCallback = function() {
- is(this.__proto__, p, "Correct prototype should be set on custom elements.");
-
- if (this == fooClone) {
- // Callback called for the element created before registering the custom element.
- // Should be called on element upgrade.
- is(callbackCalledOnUpgrade, false, "Upgrade should only be called once per clone.");
- callbackCalledOnUpgrade = true;
- } else if (this != foo) {
- // Callback called for the element created after registering the custom element.
- is(callbackCalledOnClone, false, "Upgrade should only be called once per clone.");
- callbackCalledOnClone = true;
- }
-
- if (callbackCalledOnUpgrade && callbackCalledOnClone) {
- SimpleTest.finish();
- }
-};
-
-document.registerElement("x-foo", { prototype: p });
-
-var anotherFooClone = foo.cloneNode(true);
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks_extended.html b/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks_extended.html
deleted file mode 100644
index b3531b0ea..000000000
--- a/dom/tests/mochitest/webcomponents/test_custom_element_clone_callbacks_extended.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1081039
--->
-<head>
- <title>Test callbacks for cloned extended custom elements.</title>
- <script type="text/javascript" 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=1081039">Bug 1081039</a>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-// Test to make sure created callback is called on clones created after
-// registering the custom element.
-
-var count = 0;
-var p = Object.create(HTMLButtonElement.prototype);
-p.createdCallback = function() { // should be called by createElement and cloneNode
- is(this.__proto__, p, "Correct prototype should be set on custom elements.");
-
- if (++count == 2) {
- SimpleTest.finish();
- }
-};
-
-document.registerElement("x-foo", { prototype: p, extends: "button" });
-var foo = document.createElement("button", {is: "x-foo"});
-is(foo.getAttribute("is"), "x-foo");
-
-var fooClone = foo.cloneNode(true);
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html
new file mode 100644
index 000000000..b022a7887
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1274159
+-->
+<head>
+ <title>Test HTMLConstructor for custom elements.</title>
+ <script type="text/javascript" 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=1274159">Bug 1274159</a>
+<script type="text/javascript">
+function test_with_new_window(f) {
+ return new Promise((aResolve) => {
+ let iframe = document.createElement('iframe');
+ iframe.setAttribute('type', 'content');
+ iframe.setAttribute('src', 'dummy_page.html');
+ iframe.onload = function() {
+ f(iframe.contentWindow);
+ aResolve();
+ };
+ document.body.appendChild(iframe);
+ });
+}
+
+// Fake the Cu.waiveXrays, so that we can share the tests with mochitest chrome.
+var Cu = { waiveXrays: (obj) => obj };
+var promises = [];
+SimpleTest.waitForExplicitFinish();
+</script>
+<!-- Test cases for autonomous element -->
+<script type="text/javascript" src="htmlconstructor_autonomous_tests.js"></script>
+<!-- Test cases for customized built-in element -->
+<script type="text/javascript" src="htmlconstructor_builtin_tests.js"></script>
+<script type="text/javascript">
+Promise.all(promises).then(() => {
+ SimpleTest.finish();
+});
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html
new file mode 100644
index 000000000..8c7ec0ac6
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1274159
+-->
+<head>
+ <title>Test HTMLConstructor for custom elements.</title>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1274159">Bug 1274159</a>
+<script type="text/javascript">
+function test_with_new_window(f) {
+ return new Promise((aResolve) => {
+ let iframe = document.createElement('iframe');
+ iframe.setAttribute('type', 'content');
+ iframe.setAttribute('src', 'http://example.org/tests/dom/tests/mochitest/webcomponents/dummy_page.html');
+ iframe.onload = function() {
+ f(iframe.contentWindow);
+ aResolve();
+ };
+ document.body.appendChild(iframe);
+ });
+}
+
+var Cu = Components.utils;
+var promises = [];
+SimpleTest.waitForExplicitFinish();
+</script>
+<!-- Test cases for autonomous element -->
+<script type="text/javascript" src="htmlconstructor_autonomous_tests.js"></script>
+<!-- Test cases for customized built-in element -->
+<script type="text/javascript" src="htmlconstructor_builtin_tests.js"></script>
+<script type="text/javascript">
+Promise.all(promises).then(() => {
+ SimpleTest.finish();
+});
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_import_node_created_callback.html b/dom/tests/mochitest/webcomponents/test_custom_element_import_node_created_callback.html
deleted file mode 100644
index f533b507c..000000000
--- a/dom/tests/mochitest/webcomponents/test_custom_element_import_node_created_callback.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1093680
--->
-<head>
- <title>Test created callback order for imported custom element.</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<template id="template"><x-foo><span></span></x-foo></template>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093680">Bug 1093680</a>
-<script>
-
-var fooProtoCreatedCallbackCalled = false;
-var fooProto = Object.create(HTMLElement.prototype);
-fooProto.createdCallback = function() {
- ok(this.firstElementChild, "When the created callback is called, the element should already have a child because the callback should only be called after cloning all the contents.");
- fooProtoCreatedCallbackCalled = true;
-};
-
-document.registerElement("x-foo", { prototype: fooProto });
-
-var template = document.getElementById("template");
-
-// Importing node will implicityly clone the conent in the main document.
-var adoptedFoo = document.importNode(template.content, true);
-
-ok(fooProtoCreatedCallbackCalled, "Created callback should be called after importing custom element into document");
-
-</script>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_register_invalid_callbacks.html b/dom/tests/mochitest/webcomponents/test_custom_element_register_invalid_callbacks.html
index a349f4aa5..572579ba8 100644
--- a/dom/tests/mochitest/webcomponents/test_custom_element_register_invalid_callbacks.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_register_invalid_callbacks.html
@@ -19,9 +19,6 @@ const testWindow = iframe.contentDocument.defaultView;
// This is for backward compatibility.
// We should do the same checks for the callbacks from v0 spec.
[
- 'createdCallback',
- 'attachedCallback',
- 'detachedCallback',
'attributeChangedCallback',
].forEach(callback => {
var c = class {};
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_throw_on_dynamic_markup_insertion.html b/dom/tests/mochitest/webcomponents/test_custom_element_throw_on_dynamic_markup_insertion.html
new file mode 100644
index 000000000..b5ef66860
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_throw_on_dynamic_markup_insertion.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1378079
+-->
+<head>
+ <title>Test throw on dynamic markup insertion when creating element synchronously from parser</title>
+ <script type="text/javascript" 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=1378079">Bug 1378079</a>
+<div id="container"></div>
+
+<script>
+
+class DoDocumentOpenInCtor extends HTMLElement {
+ constructor() {
+ super();
+ document.open();
+ }
+};
+customElements.define('x-document-open-in-ctor', DoDocumentOpenInCtor);
+
+class DoDocumentWriteInCtor extends HTMLElement {
+ constructor() {
+ super();
+ document.write('<div>This should not be shown</div>');
+ }
+};
+customElements.define('x-document-write-in-ctor', DoDocumentWriteInCtor);
+
+class DoDocumentCloseInCtor extends HTMLElement {
+ constructor() {
+ super();
+ document.close();
+ }
+};
+customElements.define('x-document-close-in-ctor', DoDocumentCloseInCtor);
+
+window.errors = [];
+window.onerror = function(message, url, lineNumber, columnNumber, error) {
+ errors.push(error.name);
+ return true;
+}
+var expectedErrorCount = 0;
+
+document.write("<x-document-open-in-ctor></x-document-open-in-ctor>");
+expectedErrorCount++;
+is(window.errors.length, expectedErrorCount, "expectedErrorCount should be " + expectedErrorCount);
+is(window.errors[expectedErrorCount - 1], 'InvalidStateError', "Error name should be 'InvalidStateError'");
+
+document.write("<x-document-write-in-ctor></x-document-write-in-ctor>");
+expectedErrorCount++;
+is(window.errors.length, expectedErrorCount, "expectedErrorCount should be " + expectedErrorCount);
+is(window.errors[expectedErrorCount - 1], 'InvalidStateError', "Error name should be 'InvalidStateError'");
+
+document.write("<x-document-close-in-ctor></x-document-close-in-ctor>");
+expectedErrorCount++;
+is(window.errors.length, expectedErrorCount, "expectedErrorCount should be " + expectedErrorCount);
+is(window.errors[expectedErrorCount - 1], 'InvalidStateError', "Error name should be 'InvalidStateError'");
+
+</script>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_uncatchable_exception.html b/dom/tests/mochitest/webcomponents/test_custom_element_uncatchable_exception.html
new file mode 100644
index 000000000..f60bf1674
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_uncatchable_exception.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1407669
+-->
+<head>
+ <title>Test custom elements runtime exception</title>
+ <script type="text/javascript" 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=1407669">Bug 1407669</a>
+<script type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
+ window.onerror = function (e) {
+ ok(false, "How did we get here!?");
+ }
+
+ class Foo extends HTMLElement {
+ constructor() {
+ super()
+ TestFunctions.throwUncatchableException();
+ }
+ }
+
+ customElements.define("test-custom-element", Foo);
+ let element = document.createElement("test-custom-element");
+ is(element instanceof HTMLUnknownElement, true, "It should be a HTMLUnknownElement when uncatchable exception throws in constructor");
+ ok(true, "Uncatchable exception should not report");
+ SimpleTest.finish();
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/test_document_register.html b/dom/tests/mochitest/webcomponents/test_document_register.html
index a9c194b60..aa80fef5f 100644
--- a/dom/tests/mochitest/webcomponents/test_document_register.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register.html
@@ -103,52 +103,12 @@ function startTest() {
is(extendedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
is(extendedButton.type, "submit", "Created element should be a button with type of \"submit\"");
- // document.createElementNS with different namespace than definition.
- try {
- var svgButton = document.createElementNS("http://www.w3.org/2000/svg", "button", {is: "x-extended-button"});
- ok(false, "An exception should've been thrown");
- } catch(err) {
- is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
- }
-
- // document.createElementNS with no namespace.
- try {
- var noNamespaceButton = document.createElementNS("", "button", {is: "x-extended-button"});
- ok(false, "An exception should've been thrown");
- } catch(err) {
- is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
- }
-
- // document.createElement with non-existant extended type.
- try {
- var normalButton = document.createElement("button", {is: "x-non-existant"});
- ok(false, "An exception should've been thrown");
- } catch(err) {
- is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
- }
-
- // document.createElement with exteneded type that does not match with local name of element.
- try {
- var normalDiv = document.createElement("div", {is: "x-extended-button"});
- ok(false, "An exception should've been thrown");
- } catch(err) {
- is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
- }
-
// Custom element constructor.
var constructedButton = new buttonConstructor();
is(constructedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
is(constructedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
is(constructedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
- // document.createElement with different namespace than definition for extended element.
- try {
- var htmlText = document.createElement("text", {is: "x-extended-text"});
- ok(false, "An exception should've been thrown");
- } catch(err) {
- is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
- }
-
// Try creating an element with a custom element name, but not in the html namespace.
var htmlNamespaceProto = Object.create(HTMLElement.prototype);
document.registerElement("x-in-html-namespace", { prototype: htmlNamespaceProto });
diff --git a/dom/tests/mochitest/webcomponents/test_document_register_base_queue.html b/dom/tests/mochitest/webcomponents/test_document_register_base_queue.html
deleted file mode 100644
index c839857b4..000000000
--- a/dom/tests/mochitest/webcomponents/test_document_register_base_queue.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=783129
--->
-<head>
- <title>Test for document.registerElement lifecycle callback</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-<script>
-var p = Object.create(HTMLElement.prototype);
-
-var createdCallbackCallCount = 0;
-
-// By the time the base element queue is processed via the microtask,
-// both x-hello elements should be in the document.
-p.createdCallback = function() {
- var one = document.getElementById("one");
- var two = document.getElementById("two");
- isnot(one, null, "First x-hello element should be in the tree.");
- isnot(two, null, "Second x-hello element should be in the tree.");
- createdCallbackCallCount++;
- if (createdCallbackCallCount == 2) {
- SimpleTest.finish();
- }
-
- if (createdCallbackCallCount > 2) {
- ok(false, "Created callback called too much.");
- }
-};
-
-p.attributeChangedCallback = function(name, oldValue, newValue) {
- ok(false, "Attribute changed callback should not be called because callbacks should not be queued until created callback invoked.");
-};
-
-document.registerElement("x-hello", { prototype: p });
-
-SimpleTest.waitForExplicitFinish();
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
-<x-hello id="one"></x-hello>
-<x-hello id="two"></x-hello>
-<script>
-</script>
-</body>
-</html>
diff --git a/dom/tests/mochitest/webcomponents/test_document_register_parser.html b/dom/tests/mochitest/webcomponents/test_document_register_parser.html
index bc4cdcbac..a4fb63139 100644
--- a/dom/tests/mochitest/webcomponents/test_document_register_parser.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register_parser.html
@@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=783129
var extendedButtonProto = Object.create(HTMLButtonElement.prototype);
var buttonCallbackCalled = false;
-extendedButtonProto.createdCallback = function() {
+extendedButtonProto.connectedCallback = function() {
is(buttonCallbackCalled, false, "created callback for x-button should only be called once.");
is(this.tagName, "BUTTON", "Only the <button> element should be upgraded.");
buttonCallbackCalled = true;
@@ -21,7 +21,7 @@ document.registerElement("x-button", { prototype: extendedButtonProto, extends:
var divProto = Object.create(HTMLDivElement.prototype);
var divCallbackCalled = false;
-divProto.createdCallback = function() {
+divProto.connectedCallback = function() {
is(divCallbackCalled, false, "created callback for x-div should only be called once.");
is(buttonCallbackCalled, true, "crated callback should be called for x-button before x-div.");
is(this.tagName, "X-DIV", "Only the <x-div> element should be upgraded.");
diff --git a/dom/tests/mochitest/webcomponents/test_document_register_stack.html b/dom/tests/mochitest/webcomponents/test_document_register_stack.html
index 34f108654..b1c61af11 100644
--- a/dom/tests/mochitest/webcomponents/test_document_register_stack.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register_stack.html
@@ -28,7 +28,8 @@ function testChangeAttributeInCreatedCallback() {
createdCallbackCalled = true;
is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
this.setAttribute("foo", "bar");
- is(attributeChangedCallbackCalled, false, "While element is being created, element should not be added to the current element callback queue.");
+ is(attributeChangedCallbackCalled, true, "While element is being created, element should be added to the current element callback queue.");
+ runNextTest();
};
p.attributeChangedCallback = function(name, oldValue, newValue) {
@@ -36,7 +37,6 @@ function testChangeAttributeInCreatedCallback() {
is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
is(newValue, "bar", "The new value should be 'bar'");
attributeChangedCallbackCalled = true;
- runNextTest();
};
document.registerElement("x-one", { prototype: p });
diff --git a/dom/tests/mochitest/webcomponents/test_document_shared_registry.html b/dom/tests/mochitest/webcomponents/test_document_shared_registry.html
index 76c2ea8ec..db72e1e6c 100644
--- a/dom/tests/mochitest/webcomponents/test_document_shared_registry.html
+++ b/dom/tests/mochitest/webcomponents/test_document_shared_registry.html
@@ -14,37 +14,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=783129
<script>
var container = document.getElementById("container");
-function createdCallbackFromMainDoc() {
- var createdCallbackCalled = false;
- var assocDoc = document.implementation.createHTMLDocument();
-
- var proto = Object.create(HTMLElement.prototype);
- proto.createdCallback = function() {
- is(createdCallbackCalled, false, "created callback should only be called once in this tests.");
- createdCallbackCalled = true;
- runNextTest();
- };
-
- assocDoc.registerElement("x-associated-doc-callback-elem", { prototype: proto });
- document.createElement("x-associated-doc-callback-elem");
-}
-
-function createdCallbackFromDocHTMLNamespace() {
- var createdCallbackCalled = false;
- var assocDoc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
- var somediv = assocDoc.createElement("div");
-
- var proto = Object.create(HTMLElement.prototype);
- proto.createdCallback = function() {
- is(createdCallbackCalled, false, "created callback should only be called once in this tests.");
- createdCallbackCalled = true;
- runNextTest();
- };
-
- assocDoc.registerElement("x-assoc-doc-with-ns-callback-elem", { prototype: proto });
- document.createElement("x-assoc-doc-with-ns-callback-elem");
-}
-
function registerNoRegistryDoc() {
var assocDoc = document.implementation.createDocument(null, "html");
try {
@@ -65,8 +34,6 @@ function runNextTest() {
}
var testFunctions = [
- createdCallbackFromMainDoc,
- createdCallbackFromDocHTMLNamespace,
registerNoRegistryDoc,
SimpleTest.finish
];
diff --git a/dom/tests/moz.build b/dom/tests/moz.build
index f7c3e2437..7fc81abbd 100644
--- a/dom/tests/moz.build
+++ b/dom/tests/moz.build
@@ -37,6 +37,7 @@ MOCHITEST_CHROME_MANIFESTS += [
'mochitest/geolocation/chrome.ini',
'mochitest/localstorage/chrome.ini',
'mochitest/sessionstorage/chrome.ini',
+ 'mochitest/webcomponents/chrome.ini',
'mochitest/whatwg/chrome.ini',
]
diff --git a/dom/webidl/Attr.webidl b/dom/webidl/Attr.webidl
index c836afd9b..763ed02ef 100644
--- a/dom/webidl/Attr.webidl
+++ b/dom/webidl/Attr.webidl
@@ -12,7 +12,7 @@
interface Attr : Node {
readonly attribute DOMString localName;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString value;
[Constant]
diff --git a/dom/webidl/CSSStyleDeclaration.webidl b/dom/webidl/CSSStyleDeclaration.webidl
index d9b2511de..561e5cce1 100644
--- a/dom/webidl/CSSStyleDeclaration.webidl
+++ b/dom/webidl/CSSStyleDeclaration.webidl
@@ -10,7 +10,7 @@
interface CSSRule;
interface CSSStyleDeclaration {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString cssText;
readonly attribute unsigned long length;
@@ -22,9 +22,9 @@ interface CSSStyleDeclaration {
[Throws]
CSSValue? getPropertyCSSValue(DOMString property);
DOMString getPropertyPriority(DOMString property);
- [Throws]
+ [CEReactions, Throws]
void setProperty(DOMString property, [TreatNullAs=EmptyString] DOMString value, [TreatNullAs=EmptyString] optional DOMString priority = "");
- [Throws]
+ [CEReactions, Throws]
DOMString removeProperty(DOMString property);
readonly attribute CSSRule? parentRule;
diff --git a/dom/webidl/ChildNode.webidl b/dom/webidl/ChildNode.webidl
index fcf388059..ae36cd93e 100644
--- a/dom/webidl/ChildNode.webidl
+++ b/dom/webidl/ChildNode.webidl
@@ -9,13 +9,13 @@
[NoInterfaceObject]
interface ChildNode {
- [Throws, Unscopable]
+ [CEReactions, Throws, Unscopable]
void before((Node or DOMString)... nodes);
- [Throws, Unscopable]
+ [CEReactions, Throws, Unscopable]
void after((Node or DOMString)... nodes);
- [Throws, Unscopable]
+ [CEReactions, Throws, Unscopable]
void replaceWith((Node or DOMString)... nodes);
- [Unscopable]
+ [CEReactions, Unscopable]
void remove();
};
diff --git a/dom/webidl/CustomElementRegistry.webidl b/dom/webidl/CustomElementRegistry.webidl
index dff612174..788b6a4ed 100644
--- a/dom/webidl/CustomElementRegistry.webidl
+++ b/dom/webidl/CustomElementRegistry.webidl
@@ -5,7 +5,7 @@
// https://html.spec.whatwg.org/#dom-window-customelements
[Func="CustomElementRegistry::IsCustomElementEnabled"]
interface CustomElementRegistry {
- [Throws]
+ [CEReactions, Throws]
void define(DOMString name, Function functionConstructor,
optional ElementDefinitionOptions options);
any get(DOMString name);
diff --git a/dom/webidl/DOMStringMap.webidl b/dom/webidl/DOMStringMap.webidl
index 0ed98e148..a59910e0b 100644
--- a/dom/webidl/DOMStringMap.webidl
+++ b/dom/webidl/DOMStringMap.webidl
@@ -14,7 +14,8 @@
[OverrideBuiltins]
interface DOMStringMap {
getter DOMString (DOMString name);
- [Throws]
+ [CEReactions, Throws]
setter creator void (DOMString name, DOMString value);
+ [CEReactions]
deleter void (DOMString name);
};
diff --git a/dom/webidl/DOMTokenList.webidl b/dom/webidl/DOMTokenList.webidl
index a1ea243b3..69663d055 100644
--- a/dom/webidl/DOMTokenList.webidl
+++ b/dom/webidl/DOMTokenList.webidl
@@ -14,17 +14,17 @@ interface DOMTokenList {
readonly attribute unsigned long length;
getter DOMString? item(unsigned long index);
boolean contains(DOMString token);
- [Throws]
+ [CEReactions, Throws]
void add(DOMString... tokens);
- [Throws]
+ [CEReactions, Throws]
void remove(DOMString... tokens);
- [Throws]
+ [CEReactions, Throws]
void replace(DOMString token, DOMString newToken);
- [Throws]
+ [CEReactions, Throws]
boolean toggle(DOMString token, optional boolean force);
- [Throws]
+ [CEReactions, Throws]
boolean supports(DOMString token);
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString value;
stringifier DOMString ();
iterable<DOMString?>;
diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
index 904b1fb77..b28903ae2 100644
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -65,9 +65,9 @@ interface Document : Node {
[NewObject, Throws]
ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
- [Throws]
+ [CEReactions, Throws]
Node importNode(Node node, optional boolean deep = false);
- [Throws]
+ [CEReactions, Throws]
Node adoptNode(Node node);
[NewObject, Throws]
@@ -108,9 +108,9 @@ partial interface Document {
// DOM tree accessors
//(Not proxy yet)getter object (DOMString name);
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString title;
- [Pure]
+ [CEReactions, Pure]
attribute DOMString dir;
//(HTML only) attribute HTMLElement? body;
//(HTML only)readonly attribute HTMLHeadElement? head;
diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl
index cf17523a5..a6b2bfdd5 100644
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -25,9 +25,9 @@ interface Element : Node {
[Pure]
readonly attribute DOMString tagName;
- [Pure]
+ [CEReactions, Pure]
attribute DOMString id;
- [Pure]
+ [CEReactions, Pure]
attribute DOMString className;
[Constant, PutForwards=value]
readonly attribute DOMTokenList classList;
@@ -40,15 +40,15 @@ interface Element : Node {
DOMString? getAttribute(DOMString name);
[Pure]
DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
- [Throws]
+ [CEReactions, Throws]
boolean toggleAttribute(DOMString name, optional boolean force);
- [Throws]
+ [CEReactions, Throws]
void setAttribute(DOMString name, DOMString value);
- [Throws]
+ [CEReactions, Throws]
void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
- [Throws]
+ [CEReactions, Throws]
void removeAttribute(DOMString name);
- [Throws]
+ [CEReactions, Throws]
void removeAttributeNS(DOMString? namespace, DOMString localName);
[Pure]
boolean hasAttribute(DOMString name);
@@ -72,7 +72,7 @@ interface Element : Node {
[Pure]
HTMLCollection getElementsByClassName(DOMString classNames);
- [Throws, Pure]
+ [CEReactions, Throws, Pure]
Element? insertAdjacentElement(DOMString where, Element element); // historical
[Throws]
@@ -137,12 +137,12 @@ interface Element : Node {
// Obsolete methods.
Attr? getAttributeNode(DOMString name);
- [Throws]
+ [CEReactions, Throws]
Attr? setAttributeNode(Attr newAttr);
- [Throws]
+ [CEReactions, Throws]
Attr? removeAttributeNode(Attr oldAttr);
Attr? getAttributeNodeNS(DOMString? namespaceURI, DOMString localName);
- [Throws]
+ [CEReactions, Throws]
Attr? setAttributeNodeNS(Attr newAttr);
[ChromeOnly]
@@ -212,11 +212,11 @@ partial interface Element {
// http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
partial interface Element {
- [Pure,SetterThrows,TreatNullAs=EmptyString]
+ [CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
attribute DOMString innerHTML;
- [Pure,SetterThrows,TreatNullAs=EmptyString]
+ [CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
attribute DOMString outerHTML;
- [Throws]
+ [CEReactions, Throws]
void insertAdjacentHTML(DOMString position, DOMString text);
};
diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl
index b92e3a2bb..484a8e95c 100644
--- a/dom/webidl/EventHandler.webidl
+++ b/dom/webidl/EventHandler.webidl
@@ -94,7 +94,6 @@ interface GlobalEventHandlers {
[Pref="dom.select_events.enabled"]
attribute EventHandler onselectstart;
- [Pref="dom.details_element.enabled"]
attribute EventHandler ontoggle;
// Pointer events handlers
diff --git a/dom/webidl/HTMLAnchorElement.webidl b/dom/webidl/HTMLAnchorElement.webidl
index 0b8ded6d7..0326dff6a 100644
--- a/dom/webidl/HTMLAnchorElement.webidl
+++ b/dom/webidl/HTMLAnchorElement.webidl
@@ -12,25 +12,26 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-a-element
+[HTMLConstructor]
interface HTMLAnchorElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString target;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString download;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ping;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString rel;
- [SetterThrows, Pref="network.http.enablePerElementReferrer"]
+ [CEReactions, SetterThrows, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
[PutForwards=value]
readonly attribute DOMTokenList relList;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString hreflang;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString text;
};
@@ -38,14 +39,14 @@ HTMLAnchorElement implements HTMLHyperlinkElementUtils;
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLAnchorElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString coords;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString charset;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString name;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString rev;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString shape;
};
diff --git a/dom/webidl/HTMLAreaElement.webidl b/dom/webidl/HTMLAreaElement.webidl
index be3f37885..0980d178a 100644
--- a/dom/webidl/HTMLAreaElement.webidl
+++ b/dom/webidl/HTMLAreaElement.webidl
@@ -13,20 +13,21 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-area-element
+[HTMLConstructor]
interface HTMLAreaElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString alt;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString coords;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString shape;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString target;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString download;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ping;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString rel;
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
@@ -38,6 +39,6 @@ HTMLAreaElement implements HTMLHyperlinkElementUtils;
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLAreaElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean noHref;
};
diff --git a/dom/webidl/HTMLAudioElement.webidl b/dom/webidl/HTMLAudioElement.webidl
index 8537453c0..725669839 100644
--- a/dom/webidl/HTMLAudioElement.webidl
+++ b/dom/webidl/HTMLAudioElement.webidl
@@ -11,6 +11,6 @@
* and create derivative works of this document.
*/
-[NamedConstructor=Audio(optional DOMString src)]
+[HTMLConstructor, NamedConstructor=Audio(optional DOMString src)]
interface HTMLAudioElement : HTMLMediaElement {};
diff --git a/dom/webidl/HTMLBRElement.webidl b/dom/webidl/HTMLBRElement.webidl
index cf5cb8a67..b0b0f80ed 100644
--- a/dom/webidl/HTMLBRElement.webidl
+++ b/dom/webidl/HTMLBRElement.webidl
@@ -13,11 +13,12 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-br-element
+[HTMLConstructor]
interface HTMLBRElement : HTMLElement {};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLBRElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString clear;
};
diff --git a/dom/webidl/HTMLBaseElement.webidl b/dom/webidl/HTMLBaseElement.webidl
index d982f4654..ed86f8c77 100644
--- a/dom/webidl/HTMLBaseElement.webidl
+++ b/dom/webidl/HTMLBaseElement.webidl
@@ -12,10 +12,11 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-base-element
+[HTMLConstructor]
interface HTMLBaseElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString href;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString target;
};
diff --git a/dom/webidl/HTMLBodyElement.webidl b/dom/webidl/HTMLBodyElement.webidl
index 95df2d43a..f89c287d7 100644
--- a/dom/webidl/HTMLBodyElement.webidl
+++ b/dom/webidl/HTMLBodyElement.webidl
@@ -11,16 +11,23 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLBodyElement : HTMLElement {
};
partial interface HTMLBodyElement {
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString text;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString link;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString vLink;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString aLink;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString bgColor;
- [SetterThrows] attribute DOMString background;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString text;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString link;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString vLink;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString aLink;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString bgColor;
+ [CEReactions, SetterThrows]
+ attribute DOMString background;
};
HTMLBodyElement implements WindowEventHandlers;
diff --git a/dom/webidl/HTMLButtonElement.webidl b/dom/webidl/HTMLButtonElement.webidl
index 579efa39c..f129dbd7b 100644
--- a/dom/webidl/HTMLButtonElement.webidl
+++ b/dom/webidl/HTMLButtonElement.webidl
@@ -11,28 +11,29 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-button-element
+[HTMLConstructor]
interface HTMLButtonElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean autofocus;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean disabled;
[Pure]
readonly attribute HTMLFormElement? form;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString formAction;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString formEnctype;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString formMethod;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean formNoValidate;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString formTarget;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString type;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString value;
// Not yet implemented:
// attribute HTMLMenuElement? menu;
diff --git a/dom/webidl/HTMLCanvasElement.webidl b/dom/webidl/HTMLCanvasElement.webidl
index 15e94f154..b567c69eb 100644
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -13,10 +13,11 @@
interface nsISupports;
interface Variant;
+[HTMLConstructor]
interface HTMLCanvasElement : HTMLElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long width;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long height;
[Throws]
diff --git a/dom/webidl/HTMLDListElement.webidl b/dom/webidl/HTMLDListElement.webidl
index 08020a497..4cf1c2183 100644
--- a/dom/webidl/HTMLDListElement.webidl
+++ b/dom/webidl/HTMLDListElement.webidl
@@ -13,11 +13,12 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-dl-element
+[HTMLConstructor]
interface HTMLDListElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLDListElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean compact;
};
diff --git a/dom/webidl/HTMLDataElement.webidl b/dom/webidl/HTMLDataElement.webidl
index 821b8b483..d24537871 100644
--- a/dom/webidl/HTMLDataElement.webidl
+++ b/dom/webidl/HTMLDataElement.webidl
@@ -7,7 +7,8 @@
* http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-data-element
*/
+[HTMLConstructor]
interface HTMLDataElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString value;
};
diff --git a/dom/webidl/HTMLDataListElement.webidl b/dom/webidl/HTMLDataListElement.webidl
index 83b20cd2b..4c38fddf3 100644
--- a/dom/webidl/HTMLDataListElement.webidl
+++ b/dom/webidl/HTMLDataListElement.webidl
@@ -11,6 +11,7 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLDataListElement : HTMLElement {
readonly attribute HTMLCollection options;
};
diff --git a/dom/webidl/HTMLDetailsElement.webidl b/dom/webidl/HTMLDetailsElement.webidl
index 133ecf125..04df82e30 100644
--- a/dom/webidl/HTMLDetailsElement.webidl
+++ b/dom/webidl/HTMLDetailsElement.webidl
@@ -11,8 +11,8 @@
* and create derivative works of this document.
*/
-[Pref="dom.details_element.enabled"]
+[HTMLConstructor]
interface HTMLDetailsElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean open;
};
diff --git a/dom/webidl/HTMLDialogElement.webidl b/dom/webidl/HTMLDialogElement.webidl
index b6cdbacf6..563740c87 100644
--- a/dom/webidl/HTMLDialogElement.webidl
+++ b/dom/webidl/HTMLDialogElement.webidl
@@ -13,11 +13,13 @@
[Pref="dom.dialog_element.enabled"]
interface HTMLDialogElement : HTMLElement {
- [SetterThrows] attribute boolean open;
+ [CEReactions, SetterThrows]
+ attribute boolean open;
attribute DOMString returnValue;
-
+ [CEReactions]
void show();
- [Throws] void showModal();
-
+ [CEReactions, Throws]
+ void showModal();
+ [CEReactions]
void close(optional DOMString returnValue);
};
diff --git a/dom/webidl/HTMLDirectoryElement.webidl b/dom/webidl/HTMLDirectoryElement.webidl
index 9d5160af1..65becbb60 100644
--- a/dom/webidl/HTMLDirectoryElement.webidl
+++ b/dom/webidl/HTMLDirectoryElement.webidl
@@ -12,8 +12,9 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
+[HTMLConstructor]
interface HTMLDirectoryElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean compact;
};
diff --git a/dom/webidl/HTMLDivElement.webidl b/dom/webidl/HTMLDivElement.webidl
index f50e2aad0..2b762c6fa 100644
--- a/dom/webidl/HTMLDivElement.webidl
+++ b/dom/webidl/HTMLDivElement.webidl
@@ -11,9 +11,10 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLDivElement : HTMLElement {};
partial interface HTMLDivElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
};
diff --git a/dom/webidl/HTMLDocument.webidl b/dom/webidl/HTMLDocument.webidl
index ffb61ccdd..ffa38d97d 100644
--- a/dom/webidl/HTMLDocument.webidl
+++ b/dom/webidl/HTMLDocument.webidl
@@ -13,7 +13,7 @@ interface HTMLDocument : Document {
// DOM tree accessors
[Throws]
getter object (DOMString name);
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute HTMLElement? body;
[Pure]
readonly attribute HTMLHeadElement? head;
@@ -32,20 +32,20 @@ interface HTMLDocument : Document {
NodeList getElementsByName(DOMString elementName);
// dynamic markup insertion
- [Throws]
+ [CEReactions, Throws]
Document open(optional DOMString type = "text/html", optional DOMString replace = "");
- [Throws]
+ [CEReactions, Throws]
WindowProxy? open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
- [Throws]
+ [CEReactions, Throws]
void close();
- [Throws]
+ [CEReactions, Throws]
void write(DOMString... text);
- [Throws]
+ [CEReactions, Throws]
void writeln(DOMString... text);
- [SetterThrows, NeedsSubjectPrincipal]
+ [CEReactions, SetterThrows, NeedsSubjectPrincipal]
attribute DOMString designMode;
- [Throws]
+ [CEReactions, Throws]
boolean execCommand(DOMString commandId, optional boolean showUI = false,
optional DOMString value = "");
[Throws]
@@ -58,11 +58,11 @@ interface HTMLDocument : Document {
[Throws]
DOMString queryCommandValue(DOMString commandId);
- [TreatNullAs=EmptyString] attribute DOMString fgColor;
- [TreatNullAs=EmptyString] attribute DOMString linkColor;
- [TreatNullAs=EmptyString] attribute DOMString vlinkColor;
- [TreatNullAs=EmptyString] attribute DOMString alinkColor;
- [TreatNullAs=EmptyString] attribute DOMString bgColor;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString fgColor;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString linkColor;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString vlinkColor;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString alinkColor;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString bgColor;
[Pure]
readonly attribute HTMLCollection anchors;
diff --git a/dom/webidl/HTMLElement.webidl b/dom/webidl/HTMLElement.webidl
index 5ce5024e6..815f4a3bd 100644
--- a/dom/webidl/HTMLElement.webidl
+++ b/dom/webidl/HTMLElement.webidl
@@ -12,34 +12,37 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLElement : Element {
// metadata attributes
+ [CEReactions]
attribute DOMString title;
+ [CEReactions]
attribute DOMString lang;
// attribute boolean translate;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString dir;
[Constant]
readonly attribute DOMStringMap dataset;
- [GetterThrows, Pure, TreatNullAs=EmptyString]
+ [CEReactions, GetterThrows, Pure, TreatNullAs=EmptyString]
attribute DOMString innerText;
// user interaction
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean hidden;
void click();
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute long tabIndex;
[Throws]
void focus();
[Throws]
void blur();
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString accessKey;
[Pure]
readonly attribute DOMString accessKeyLabel;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean draggable;
//[PutForwards=value] readonly attribute DOMTokenList dropzone;
[SetterThrows, Pure]
@@ -50,7 +53,7 @@ interface HTMLElement : Element {
readonly attribute HTMLMenuElement? contextMenu;
//[SetterThrows]
// attribute HTMLMenuElement? contextMenu;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean spellcheck;
// command API
diff --git a/dom/webidl/HTMLEmbedElement.webidl b/dom/webidl/HTMLEmbedElement.webidl
index 36668595b..9c5361221 100644
--- a/dom/webidl/HTMLEmbedElement.webidl
+++ b/dom/webidl/HTMLEmbedElement.webidl
@@ -13,15 +13,15 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-embed-element
-[NeedResolve]
+[HTMLConstructor, NeedResolve]
interface HTMLEmbedElement : HTMLElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString src;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString type;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString width;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString height;
[Throws]
legacycaller any (any... arguments);
@@ -29,9 +29,9 @@ interface HTMLEmbedElement : HTMLElement {
// http://www.whatwg.org/specs/web-apps/current-work/#HTMLEmbedElement-partial
partial interface HTMLEmbedElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString align;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString name;
};
diff --git a/dom/webidl/HTMLFieldSetElement.webidl b/dom/webidl/HTMLFieldSetElement.webidl
index 6c9eee52b..63393bf42 100644
--- a/dom/webidl/HTMLFieldSetElement.webidl
+++ b/dom/webidl/HTMLFieldSetElement.webidl
@@ -11,11 +11,12 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLFieldSetElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean disabled;
readonly attribute HTMLFormElement? form;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString name;
readonly attribute DOMString type;
diff --git a/dom/webidl/HTMLFontElement.webidl b/dom/webidl/HTMLFontElement.webidl
index 781dabb88..8db6d3246 100644
--- a/dom/webidl/HTMLFontElement.webidl
+++ b/dom/webidl/HTMLFontElement.webidl
@@ -11,8 +11,9 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLFontElement : HTMLElement {
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString color;
- [SetterThrows] attribute DOMString face;
- [SetterThrows] attribute DOMString size;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows] attribute DOMString color;
+ [CEReactions, SetterThrows] attribute DOMString face;
+ [CEReactions, SetterThrows] attribute DOMString size;
};
diff --git a/dom/webidl/HTMLFormElement.webidl b/dom/webidl/HTMLFormElement.webidl
index 8d248e1a5..064fe9fad 100644
--- a/dom/webidl/HTMLFormElement.webidl
+++ b/dom/webidl/HTMLFormElement.webidl
@@ -11,25 +11,25 @@
* and create derivative works of this document.
*/
-[OverrideBuiltins, LegacyUnenumerableNamedProperties]
+[OverrideBuiltins, LegacyUnenumerableNamedProperties, HTMLConstructor]
interface HTMLFormElement : HTMLElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString acceptCharset;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString action;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString autocomplete;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString enctype;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString encoding;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString method;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString name;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean noValidate;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString target;
[Constant]
@@ -43,6 +43,7 @@ interface HTMLFormElement : HTMLElement {
[Throws]
void submit();
+ [CEReactions]
void reset();
boolean checkValidity();
boolean reportValidity();
diff --git a/dom/webidl/HTMLFrameElement.webidl b/dom/webidl/HTMLFrameElement.webidl
index 9c5aca7c4..c3ba0de63 100644
--- a/dom/webidl/HTMLFrameElement.webidl
+++ b/dom/webidl/HTMLFrameElement.webidl
@@ -11,25 +11,28 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#htmlframeelement
+[HTMLConstructor]
interface HTMLFrameElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString name;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString scrolling;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString src;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString frameBorder;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString longDesc;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean noResize;
[NeedsSubjectPrincipal]
readonly attribute Document? contentDocument;
readonly attribute WindowProxy? contentWindow;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString marginHeight;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString marginWidth;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString marginHeight;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString marginWidth;
};
HTMLFrameElement implements MozFrameLoaderOwner;
diff --git a/dom/webidl/HTMLFrameSetElement.webidl b/dom/webidl/HTMLFrameSetElement.webidl
index ce00d487f..afc4465d1 100644
--- a/dom/webidl/HTMLFrameSetElement.webidl
+++ b/dom/webidl/HTMLFrameSetElement.webidl
@@ -11,10 +11,11 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLFrameSetElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString cols;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString rows;
};
diff --git a/dom/webidl/HTMLHRElement.webidl b/dom/webidl/HTMLHRElement.webidl
index 0495e43b3..24ba3112a 100644
--- a/dom/webidl/HTMLHRElement.webidl
+++ b/dom/webidl/HTMLHRElement.webidl
@@ -12,19 +12,20 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-hr-element
+[HTMLConstructor]
interface HTMLHRElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLHRElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString color;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean noShade;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString size;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString width;
};
diff --git a/dom/webidl/HTMLHeadElement.webidl b/dom/webidl/HTMLHeadElement.webidl
index 0ad45e384..b649712a6 100644
--- a/dom/webidl/HTMLHeadElement.webidl
+++ b/dom/webidl/HTMLHeadElement.webidl
@@ -12,5 +12,6 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-head-element
+[HTMLConstructor]
interface HTMLHeadElement : HTMLElement {};
diff --git a/dom/webidl/HTMLHeadingElement.webidl b/dom/webidl/HTMLHeadingElement.webidl
index c07e5cb99..a39e24cfb 100644
--- a/dom/webidl/HTMLHeadingElement.webidl
+++ b/dom/webidl/HTMLHeadingElement.webidl
@@ -12,11 +12,12 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
+[HTMLConstructor]
interface HTMLHeadingElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLHeadingElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
};
diff --git a/dom/webidl/HTMLHtmlElement.webidl b/dom/webidl/HTMLHtmlElement.webidl
index b06de7761..5b2a9a926 100644
--- a/dom/webidl/HTMLHtmlElement.webidl
+++ b/dom/webidl/HTMLHtmlElement.webidl
@@ -13,10 +13,11 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-html-element
+[HTMLConstructor]
interface HTMLHtmlElement : HTMLElement {};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLHtmlElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString version;
};
diff --git a/dom/webidl/HTMLHyperlinkElementUtils.webidl b/dom/webidl/HTMLHyperlinkElementUtils.webidl
index 25f175db9..ae53fd75e 100644
--- a/dom/webidl/HTMLHyperlinkElementUtils.webidl
+++ b/dom/webidl/HTMLHyperlinkElementUtils.webidl
@@ -18,17 +18,26 @@ interface HTMLHyperlinkElementUtils {
// Bug 824857 should remove this.
stringifier;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute USVString href;
readonly attribute USVString origin;
+ [CEReactions]
attribute USVString protocol;
+ [CEReactions]
attribute USVString username;
+ [CEReactions]
attribute USVString password;
+ [CEReactions]
attribute USVString host;
+ [CEReactions]
attribute USVString hostname;
+ [CEReactions]
attribute USVString port;
+ [CEReactions]
attribute USVString pathname;
+ [CEReactions]
attribute USVString search;
+ [CEReactions]
attribute USVString hash;
};
diff --git a/dom/webidl/HTMLIFrameElement.webidl b/dom/webidl/HTMLIFrameElement.webidl
index 0a1b49aff..d2859c6db 100644
--- a/dom/webidl/HTMLIFrameElement.webidl
+++ b/dom/webidl/HTMLIFrameElement.webidl
@@ -11,22 +11,23 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLIFrameElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString src;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString srcdoc;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
[PutForwards=value] readonly attribute DOMTokenList sandbox;
// attribute boolean seamless;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean allowFullscreen;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString width;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString height;
- [SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"]
+ [CEReactions, SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
[NeedsSubjectPrincipal]
readonly attribute Document? contentDocument;
@@ -35,17 +36,19 @@ interface HTMLIFrameElement : HTMLElement {
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLIFrameElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString align;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString scrolling;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString frameBorder;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString longDesc;
- [TreatNullAs=EmptyString,SetterThrows,Pure] attribute DOMString marginHeight;
- [TreatNullAs=EmptyString,SetterThrows,Pure] attribute DOMString marginWidth;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows, Pure]
+ attribute DOMString marginHeight;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows, Pure]
+ attribute DOMString marginWidth;
};
partial interface HTMLIFrameElement {
diff --git a/dom/webidl/HTMLImageElement.webidl b/dom/webidl/HTMLImageElement.webidl
index 243c65509..e50a9ef8e 100644
--- a/dom/webidl/HTMLImageElement.webidl
+++ b/dom/webidl/HTMLImageElement.webidl
@@ -16,25 +16,26 @@ interface imgIRequest;
interface URI;
interface nsIStreamListener;
-[NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
+[HTMLConstructor,
+ NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
interface HTMLImageElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString alt;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString src;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString srcset;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString? crossOrigin;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString useMap;
- [SetterThrows, Pref="network.http.enablePerElementReferrer"]
+ [CEReactions, SetterThrows, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean isMap;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long width;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long height;
readonly attribute unsigned long naturalWidth;
readonly attribute unsigned long naturalHeight;
@@ -43,30 +44,31 @@ interface HTMLImageElement : HTMLElement {
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLImageElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString name;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long hspace;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long vspace;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString longDesc;
- [TreatNullAs=EmptyString,SetterThrows] attribute DOMString border;
+ [CEReactions, TreatNullAs=EmptyString,SetterThrows] attribute DOMString border;
};
// [Update me: not in whatwg spec yet]
// http://picture.responsiveimages.org/#the-img-element
partial interface HTMLImageElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString sizes;
readonly attribute DOMString currentSrc;
};
// Mozilla extensions.
partial interface HTMLImageElement {
+ [CEReactions]
attribute DOMString lowsrc;
// These attributes are offsets from the closest view (to mimic
diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl
index cf3e9a4c7..93ad90f45 100644
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -21,79 +21,81 @@ enum SelectionMode {
interface nsIControllers;
+[HTMLConstructor]
interface HTMLInputElement : HTMLElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString accept;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString alt;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString autocomplete;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean autofocus;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean defaultChecked;
[Pure]
attribute boolean checked;
// Bug 850337 - attribute DOMString dirName;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean disabled;
readonly attribute HTMLFormElement? form;
[Pure]
readonly attribute FileList? files;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString formAction;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString formEnctype;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString formMethod;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean formNoValidate;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString formTarget;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long height;
[Pure]
attribute boolean indeterminate;
- [Pure, SetterThrows, Pref="dom.forms.inputmode"]
+ [CEReactions, Pure, SetterThrows, Pref="dom.forms.inputmode"]
attribute DOMString inputMode;
[Pure]
readonly attribute HTMLElement? list;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString max;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute long maxLength;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString min;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute long minLength;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean multiple;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString name;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString pattern;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString placeholder;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean readOnly;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean required;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long size;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString src;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString step;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString type;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString defaultValue;
- [Pure, TreatNullAs=EmptyString, Throws]
+ [CEReactions, Pure, TreatNullAs=EmptyString, Throws]
attribute DOMString value;
[Throws, Func="HTMLInputElement::ValueAsDateEnabled"]
attribute Date? valueAsDate;
[Pure, SetterThrows]
attribute unrestricted double valueAsNumber;
+ [CEReactions]
attribute unsigned long width;
[Throws]
@@ -132,9 +134,9 @@ interface HTMLInputElement : HTMLElement {
};
partial interface HTMLInputElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString align;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString useMap;
};
diff --git a/dom/webidl/HTMLLIElement.webidl b/dom/webidl/HTMLLIElement.webidl
index c20e00846..3f104d09e 100644
--- a/dom/webidl/HTMLLIElement.webidl
+++ b/dom/webidl/HTMLLIElement.webidl
@@ -13,13 +13,14 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-li-element
+[HTMLConstructor]
interface HTMLLIElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute long value;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLLIElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString type;
};
diff --git a/dom/webidl/HTMLLabelElement.webidl b/dom/webidl/HTMLLabelElement.webidl
index f44a56219..4b624dfaf 100644
--- a/dom/webidl/HTMLLabelElement.webidl
+++ b/dom/webidl/HTMLLabelElement.webidl
@@ -11,8 +11,10 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLLabelElement : HTMLElement {
readonly attribute HTMLFormElement? form;
+ [CEReactions]
attribute DOMString htmlFor;
readonly attribute HTMLElement? control;
};
diff --git a/dom/webidl/HTMLLegendElement.webidl b/dom/webidl/HTMLLegendElement.webidl
index 0ce4ae88b..6f03ecf1b 100644
--- a/dom/webidl/HTMLLegendElement.webidl
+++ b/dom/webidl/HTMLLegendElement.webidl
@@ -13,12 +13,13 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-legend-element
+[HTMLConstructor]
interface HTMLLegendElement : HTMLElement {
readonly attribute HTMLFormElement? form;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLLegendElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
};
diff --git a/dom/webidl/HTMLLinkElement.webidl b/dom/webidl/HTMLLinkElement.webidl
index ec094e55e..eb83deab1 100644
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -12,24 +12,25 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-link-element
+[HTMLConstructor]
interface HTMLLinkElement : HTMLElement {
[Pure]
attribute boolean disabled;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString href;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString? crossOrigin;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString rel;
[PutForwards=value]
readonly attribute DOMTokenList relList;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString media;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString hreflang;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString type;
- [SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"]
+ [CEReactions, SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
[PutForwards=value] readonly attribute DOMTokenList sizes;
};
@@ -37,11 +38,11 @@ HTMLLinkElement implements LinkStyle;
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLLinkElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString charset;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString rev;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString target;
};
@@ -53,6 +54,6 @@ partial interface HTMLLinkElement {
// https://w3c.github.io/webappsec/specs/subresourceintegrity/#htmllinkelement-1
partial interface HTMLLinkElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString integrity;
};
diff --git a/dom/webidl/HTMLMapElement.webidl b/dom/webidl/HTMLMapElement.webidl
index 88fe4e54c..199c70876 100644
--- a/dom/webidl/HTMLMapElement.webidl
+++ b/dom/webidl/HTMLMapElement.webidl
@@ -11,8 +11,9 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-map-element
+[HTMLConstructor]
interface HTMLMapElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
[Constant]
readonly attribute HTMLCollection areas;
diff --git a/dom/webidl/HTMLMediaElement.webidl b/dom/webidl/HTMLMediaElement.webidl
index be79d8679..ad31f38cb 100644
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -17,18 +17,18 @@ interface HTMLMediaElement : HTMLElement {
readonly attribute MediaError? error;
// network state
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString src;
readonly attribute DOMString currentSrc;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString? crossOrigin;
const unsigned short NETWORK_EMPTY = 0;
const unsigned short NETWORK_IDLE = 1;
const unsigned short NETWORK_LOADING = 2;
const unsigned short NETWORK_NO_SOURCE = 3;
readonly attribute unsigned short networkState;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString preload;
[NewObject]
readonly attribute TimeRanges buffered;
@@ -63,9 +63,9 @@ interface HTMLMediaElement : HTMLElement {
[NewObject]
readonly attribute TimeRanges seekable;
readonly attribute boolean ended;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean autoplay;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean loop;
[Throws]
Promise<void> play();
@@ -78,12 +78,12 @@ interface HTMLMediaElement : HTMLElement {
// attribute MediaController? controller;
// controls
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean controls;
[SetterThrows]
attribute double volume;
attribute boolean muted;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean defaultMuted;
// TODO: Bug 847379
diff --git a/dom/webidl/HTMLMenuElement.webidl b/dom/webidl/HTMLMenuElement.webidl
index ff81a7c80..1194226c5 100644
--- a/dom/webidl/HTMLMenuElement.webidl
+++ b/dom/webidl/HTMLMenuElement.webidl
@@ -15,16 +15,17 @@
interface MenuBuilder;
// http://www.whatwg.org/specs/web-apps/current-work/#the-menu-element
+[HTMLConstructor]
interface HTMLMenuElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString label;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLMenuElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean compact;
};
diff --git a/dom/webidl/HTMLMenuItemElement.webidl b/dom/webidl/HTMLMenuItemElement.webidl
index 7064885a1..f09104501 100644
--- a/dom/webidl/HTMLMenuItemElement.webidl
+++ b/dom/webidl/HTMLMenuItemElement.webidl
@@ -12,23 +12,24 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-menuitem-element
+[HTMLConstructor]
interface HTMLMenuItemElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString label;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString icon;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean disabled;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean checked;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString radiogroup;
// This should be 'default' but in the IDL implementation
// this has been renamed 'defaultChecked'.
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean defaultChecked;
// Currently not implemented.
diff --git a/dom/webidl/HTMLMetaElement.webidl b/dom/webidl/HTMLMetaElement.webidl
index 5b7b0f92c..30014a955 100644
--- a/dom/webidl/HTMLMetaElement.webidl
+++ b/dom/webidl/HTMLMetaElement.webidl
@@ -12,17 +12,18 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-meta-element
+[HTMLConstructor]
interface HTMLMetaElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString httpEquiv;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString content;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLMetaElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString scheme;
};
diff --git a/dom/webidl/HTMLMeterElement.webidl b/dom/webidl/HTMLMeterElement.webidl
index 104e00353..8f93bd71e 100644
--- a/dom/webidl/HTMLMeterElement.webidl
+++ b/dom/webidl/HTMLMeterElement.webidl
@@ -12,18 +12,19 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-meter-element
+[HTMLConstructor]
interface HTMLMeterElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double value;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double min;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double max;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double low;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double high;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double optimum;
readonly attribute NodeList labels;
diff --git a/dom/webidl/HTMLModElement.webidl b/dom/webidl/HTMLModElement.webidl
index 45086cceb..8ed8b994b 100644
--- a/dom/webidl/HTMLModElement.webidl
+++ b/dom/webidl/HTMLModElement.webidl
@@ -11,9 +11,10 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#attributes-common-to-ins-and-del-elements
+[HTMLConstructor]
interface HTMLModElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString cite;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString dateTime;
};
diff --git a/dom/webidl/HTMLOListElement.webidl b/dom/webidl/HTMLOListElement.webidl
index f41abf3ea..93084c227 100644
--- a/dom/webidl/HTMLOListElement.webidl
+++ b/dom/webidl/HTMLOListElement.webidl
@@ -13,17 +13,18 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-ol-element
+[HTMLConstructor]
interface HTMLOListElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean reversed;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute long start;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLOListElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean compact;
};
diff --git a/dom/webidl/HTMLObjectElement.webidl b/dom/webidl/HTMLObjectElement.webidl
index ebb95ab09..7c9f7f8bc 100644
--- a/dom/webidl/HTMLObjectElement.webidl
+++ b/dom/webidl/HTMLObjectElement.webidl
@@ -13,23 +13,23 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-object-element
-[NeedResolve, UnsafeInPrerendering]
+[HTMLConstructor, NeedResolve, UnsafeInPrerendering]
interface HTMLObjectElement : HTMLElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString data;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString type;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean typeMustMatch;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString name;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString useMap;
[Pure]
readonly attribute HTMLFormElement? form;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString width;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString height;
// Not pure: can trigger about:blank instantiation
[NeedsSubjectPrincipal]
@@ -51,26 +51,26 @@ interface HTMLObjectElement : HTMLElement {
// http://www.whatwg.org/specs/web-apps/current-work/#HTMLObjectElement-partial
partial interface HTMLObjectElement {
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString align;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString archive;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString code;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute boolean declare;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long hspace;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString standby;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute unsigned long vspace;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString codeBase;
- [Pure, SetterThrows]
+ [CEReactions, Pure, SetterThrows]
attribute DOMString codeType;
- [TreatNullAs=EmptyString, Pure, SetterThrows]
+ [CEReactions, TreatNullAs=EmptyString, Pure, SetterThrows]
attribute DOMString border;
};
diff --git a/dom/webidl/HTMLOptGroupElement.webidl b/dom/webidl/HTMLOptGroupElement.webidl
index a23aee30d..d46fb869d 100644
--- a/dom/webidl/HTMLOptGroupElement.webidl
+++ b/dom/webidl/HTMLOptGroupElement.webidl
@@ -11,9 +11,10 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLOptGroupElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean disabled;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString label;
};
diff --git a/dom/webidl/HTMLOptionElement.webidl b/dom/webidl/HTMLOptionElement.webidl
index c80bedeef..b94afa3e9 100644
--- a/dom/webidl/HTMLOptionElement.webidl
+++ b/dom/webidl/HTMLOptionElement.webidl
@@ -11,21 +11,21 @@
* and create derivative works of this document.
*/
-[NamedConstructor=Option(optional DOMString text, optional DOMString value, optional boolean defaultSelected, optional boolean selected)]
+[HTMLConstructor, NamedConstructor=Option(optional DOMString text, optional DOMString value, optional boolean defaultSelected, optional boolean selected)]
interface HTMLOptionElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean disabled;
readonly attribute HTMLFormElement? form;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString label;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean defaultSelected;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean selected;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString value;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString text;
readonly attribute long index;
};
diff --git a/dom/webidl/HTMLOptionsCollection.webidl b/dom/webidl/HTMLOptionsCollection.webidl
index 4d4385d82..d8d1046ad 100644
--- a/dom/webidl/HTMLOptionsCollection.webidl
+++ b/dom/webidl/HTMLOptionsCollection.webidl
@@ -11,13 +11,14 @@
*/
interface HTMLOptionsCollection : HTMLCollection {
+ [CEReactions]
attribute unsigned long length;
- [Throws]
+ [CEReactions, Throws]
setter creator void (unsigned long index, HTMLOptionElement? option);
- [Throws]
+ [CEReactions, Throws]
void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
- [Throws]
+ [CEReactions, Throws]
void remove(long index);
- [Throws]
+ [CEReactions, Throws]
attribute long selectedIndex;
};
diff --git a/dom/webidl/HTMLOutputElement.webidl b/dom/webidl/HTMLOutputElement.webidl
index d0e4ecbe6..4d65209a9 100644
--- a/dom/webidl/HTMLOutputElement.webidl
+++ b/dom/webidl/HTMLOutputElement.webidl
@@ -12,18 +12,19 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
+[HTMLConstructor]
interface HTMLOutputElement : HTMLElement {
[PutForwards=value, Constant]
readonly attribute DOMTokenList htmlFor;
readonly attribute HTMLFormElement? form;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
[Constant]
readonly attribute DOMString type;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString defaultValue;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString value;
readonly attribute boolean willValidate;
diff --git a/dom/webidl/HTMLParagraphElement.webidl b/dom/webidl/HTMLParagraphElement.webidl
index 2a626d257..289af4c9f 100644
--- a/dom/webidl/HTMLParagraphElement.webidl
+++ b/dom/webidl/HTMLParagraphElement.webidl
@@ -12,11 +12,12 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-p-element
+[HTMLConstructor]
interface HTMLParagraphElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLParagraphElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
};
diff --git a/dom/webidl/HTMLParamElement.webidl b/dom/webidl/HTMLParamElement.webidl
index e2c7e8d7f..cf6b5a35a 100644
--- a/dom/webidl/HTMLParamElement.webidl
+++ b/dom/webidl/HTMLParamElement.webidl
@@ -13,17 +13,18 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-param-element
+[HTMLConstructor]
interface HTMLParamElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString value;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLParamElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString type;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString valueType;
};
diff --git a/dom/webidl/HTMLPictureElement.webidl b/dom/webidl/HTMLPictureElement.webidl
index eff30f750..387eee78d 100644
--- a/dom/webidl/HTMLPictureElement.webidl
+++ b/dom/webidl/HTMLPictureElement.webidl
@@ -4,5 +4,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+[HTMLConstructor]
interface HTMLPictureElement : HTMLElement {
};
diff --git a/dom/webidl/HTMLPreElement.webidl b/dom/webidl/HTMLPreElement.webidl
index db220b74c..6929cd533 100644
--- a/dom/webidl/HTMLPreElement.webidl
+++ b/dom/webidl/HTMLPreElement.webidl
@@ -12,11 +12,12 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-pre-element
+[HTMLConstructor]
interface HTMLPreElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLPreElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute long width;
};
diff --git a/dom/webidl/HTMLProgressElement.webidl b/dom/webidl/HTMLProgressElement.webidl
index 028728e22..564b9f2a4 100644
--- a/dom/webidl/HTMLProgressElement.webidl
+++ b/dom/webidl/HTMLProgressElement.webidl
@@ -11,10 +11,11 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLProgressElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double value;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute double max;
readonly attribute double position;
readonly attribute NodeList labels;
diff --git a/dom/webidl/HTMLQuoteElement.webidl b/dom/webidl/HTMLQuoteElement.webidl
index a266dd353..c999b1478 100644
--- a/dom/webidl/HTMLQuoteElement.webidl
+++ b/dom/webidl/HTMLQuoteElement.webidl
@@ -12,8 +12,9 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-blockquote-element
+[HTMLConstructor]
interface HTMLQuoteElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString cite;
};
diff --git a/dom/webidl/HTMLScriptElement.webidl b/dom/webidl/HTMLScriptElement.webidl
index 5b64c42d7..286c0673d 100644
--- a/dom/webidl/HTMLScriptElement.webidl
+++ b/dom/webidl/HTMLScriptElement.webidl
@@ -8,35 +8,36 @@
* http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
*/
+[HTMLConstructor]
interface HTMLScriptElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString src;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
- [SetterThrows, Pref="dom.moduleScripts.enabled"]
+ [CEReactions, SetterThrows, Pref="dom.moduleScripts.enabled"]
attribute boolean noModule;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString charset;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean async;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean defer;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString? crossOrigin;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString text;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLScriptElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString event;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString htmlFor;
};
// https://w3c.github.io/webappsec/specs/subresourceintegrity/#htmlscriptelement-1
partial interface HTMLScriptElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString integrity;
};
diff --git a/dom/webidl/HTMLSelectElement.webidl b/dom/webidl/HTMLSelectElement.webidl
index b18ca3634..537e9d84f 100644
--- a/dom/webidl/HTMLSelectElement.webidl
+++ b/dom/webidl/HTMLSelectElement.webidl
@@ -7,22 +7,23 @@
* http://www.whatwg.org/html/#the-select-element
*/
+[HTMLConstructor]
interface HTMLSelectElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean autofocus;
- [Pref="dom.forms.autocomplete.experimental", SetterThrows, Pure]
+ [CEReactions, Pref="dom.forms.autocomplete.experimental", SetterThrows, Pure]
attribute DOMString autocomplete;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean disabled;
[Pure]
readonly attribute HTMLFormElement? form;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean multiple;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean required;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute unsigned long size;
[Pure]
@@ -30,14 +31,15 @@ interface HTMLSelectElement : HTMLElement {
[Constant]
readonly attribute HTMLOptionsCollection options;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute unsigned long length;
getter Element? item(unsigned long index);
HTMLOptionElement? namedItem(DOMString name);
- [Throws]
+ [CEReactions, Throws]
void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
+ [CEReactions]
void remove(long index);
- [Throws]
+ [CEReactions, Throws]
setter creator void (unsigned long index, HTMLOptionElement? option);
readonly attribute HTMLCollection selectedOptions;
@@ -56,6 +58,7 @@ interface HTMLSelectElement : HTMLElement {
readonly attribute NodeList labels;
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20720
+ [CEReactions]
void remove();
};
diff --git a/dom/webidl/HTMLSourceElement.webidl b/dom/webidl/HTMLSourceElement.webidl
index 10b8e6fd5..55f25e469 100644
--- a/dom/webidl/HTMLSourceElement.webidl
+++ b/dom/webidl/HTMLSourceElement.webidl
@@ -11,18 +11,19 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLSourceElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString src;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
};
partial interface HTMLSourceElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString srcset;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString sizes;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString media;
};
diff --git a/dom/webidl/HTMLSpanElement.webidl b/dom/webidl/HTMLSpanElement.webidl
index 43a2d97f2..6f65cdfb3 100644
--- a/dom/webidl/HTMLSpanElement.webidl
+++ b/dom/webidl/HTMLSpanElement.webidl
@@ -12,4 +12,5 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-span-element
+[HTMLConstructor]
interface HTMLSpanElement : HTMLElement {};
diff --git a/dom/webidl/HTMLStyleElement.webidl b/dom/webidl/HTMLStyleElement.webidl
index 7ed01a8f1..3cacbf62f 100644
--- a/dom/webidl/HTMLStyleElement.webidl
+++ b/dom/webidl/HTMLStyleElement.webidl
@@ -8,12 +8,13 @@
* http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
*/
+[HTMLConstructor]
interface HTMLStyleElement : HTMLElement {
[Pure]
attribute boolean disabled;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString media;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString type;
[SetterThrows, Pure]
attribute boolean scoped;
diff --git a/dom/webidl/HTMLTableCaptionElement.webidl b/dom/webidl/HTMLTableCaptionElement.webidl
index 688b9f925..48c9d354a 100644
--- a/dom/webidl/HTMLTableCaptionElement.webidl
+++ b/dom/webidl/HTMLTableCaptionElement.webidl
@@ -11,9 +11,10 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableCaptionElement : HTMLElement {};
partial interface HTMLTableCaptionElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
};
diff --git a/dom/webidl/HTMLTableCellElement.webidl b/dom/webidl/HTMLTableCellElement.webidl
index e970a5040..aff94914f 100644
--- a/dom/webidl/HTMLTableCellElement.webidl
+++ b/dom/webidl/HTMLTableCellElement.webidl
@@ -11,41 +11,43 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableCellElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long colSpan;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long rowSpan;
//[PutForwards=value] readonly attribute DOMTokenList headers;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString headers;
readonly attribute long cellIndex;
// Mozilla-specific extensions
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString abbr;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString scope;
};
partial interface HTMLTableCellElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString axis;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString height;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString width;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ch;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString chOff;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean noWrap;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString vAlign;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString bgColor;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString bgColor;
};
diff --git a/dom/webidl/HTMLTableColElement.webidl b/dom/webidl/HTMLTableColElement.webidl
index c927541a3..02be4590a 100644
--- a/dom/webidl/HTMLTableColElement.webidl
+++ b/dom/webidl/HTMLTableColElement.webidl
@@ -11,20 +11,21 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableColElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long span;
};
partial interface HTMLTableColElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ch;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString chOff;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString vAlign;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString width;
};
diff --git a/dom/webidl/HTMLTableElement.webidl b/dom/webidl/HTMLTableElement.webidl
index a06f590e0..f81e00041 100644
--- a/dom/webidl/HTMLTableElement.webidl
+++ b/dom/webidl/HTMLTableElement.webidl
@@ -11,45 +11,52 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute HTMLTableCaptionElement? caption;
HTMLElement createCaption();
+ [CEReactions]
void deleteCaption();
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute HTMLTableSectionElement? tHead;
HTMLElement createTHead();
+ [CEReactions]
void deleteTHead();
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute HTMLTableSectionElement? tFoot;
HTMLElement createTFoot();
+ [CEReactions]
void deleteTFoot();
readonly attribute HTMLCollection tBodies;
HTMLElement createTBody();
readonly attribute HTMLCollection rows;
[Throws]
HTMLElement insertRow(optional long index = -1);
- [Throws]
+ [CEReactions, Throws]
void deleteRow(long index);
// attribute boolean sortable;
//void stopSorting();
};
partial interface HTMLTableElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString border;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString frame;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString rules;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString summary;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString width;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString bgColor;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString cellPadding;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString cellSpacing;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString bgColor;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString cellPadding;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString cellSpacing;
};
diff --git a/dom/webidl/HTMLTableRowElement.webidl b/dom/webidl/HTMLTableRowElement.webidl
index 2a356a20e..153d271f1 100644
--- a/dom/webidl/HTMLTableRowElement.webidl
+++ b/dom/webidl/HTMLTableRowElement.webidl
@@ -11,25 +11,27 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableRowElement : HTMLElement {
readonly attribute long rowIndex;
readonly attribute long sectionRowIndex;
readonly attribute HTMLCollection cells;
- [Throws]
+ [CEReactions, Throws]
HTMLElement insertCell(optional long index = -1);
[Throws]
void deleteCell(long index);
};
partial interface HTMLTableRowElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ch;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString chOff;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString vAlign;
- [TreatNullAs=EmptyString, SetterThrows] attribute DOMString bgColor;
+ [CEReactions, TreatNullAs=EmptyString, SetterThrows]
+ attribute DOMString bgColor;
};
diff --git a/dom/webidl/HTMLTableSectionElement.webidl b/dom/webidl/HTMLTableSectionElement.webidl
index 310d0ece6..a71682fc1 100644
--- a/dom/webidl/HTMLTableSectionElement.webidl
+++ b/dom/webidl/HTMLTableSectionElement.webidl
@@ -11,21 +11,22 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLTableSectionElement : HTMLElement {
readonly attribute HTMLCollection rows;
[Throws]
HTMLElement insertRow(optional long index = -1);
- [Throws]
+ [CEReactions, Throws]
void deleteRow(long index);
};
partial interface HTMLTableSectionElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString align;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString ch;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString chOff;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString vAlign;
};
diff --git a/dom/webidl/HTMLTemplateElement.webidl b/dom/webidl/HTMLTemplateElement.webidl
index c518995f6..f77eeaa42 100644
--- a/dom/webidl/HTMLTemplateElement.webidl
+++ b/dom/webidl/HTMLTemplateElement.webidl
@@ -9,6 +9,7 @@
* liability, trademark and document use rules apply.
*/
+[HTMLConstructor]
interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
};
diff --git a/dom/webidl/HTMLTextAreaElement.webidl b/dom/webidl/HTMLTextAreaElement.webidl
index 4df687a0b..7a181bf39 100644
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -14,40 +14,41 @@
interface nsIEditor;
interface MozControllers;
+[HTMLConstructor]
interface HTMLTextAreaElement : HTMLElement {
// attribute DOMString autocomplete;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean autofocus;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute unsigned long cols;
// attribute DOMString dirName;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean disabled;
[Pure]
readonly attribute HTMLFormElement? form;
// attribute DOMString inputMode;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute long maxLength;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute long minLength;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString name;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString placeholder;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean readOnly;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean required;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute unsigned long rows;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString wrap;
[Constant]
readonly attribute DOMString type;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString defaultValue;
- [TreatNullAs=EmptyString] attribute DOMString value;
+ [CEReactions, TreatNullAs=EmptyString] attribute DOMString value;
readonly attribute unsigned long textLength;
readonly attribute boolean willValidate;
diff --git a/dom/webidl/HTMLTimeElement.webidl b/dom/webidl/HTMLTimeElement.webidl
index 517ca9981..35c06fef3 100644
--- a/dom/webidl/HTMLTimeElement.webidl
+++ b/dom/webidl/HTMLTimeElement.webidl
@@ -7,7 +7,8 @@
* http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-time-element
*/
+[HTMLConstructor]
interface HTMLTimeElement : HTMLElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString dateTime;
};
diff --git a/dom/webidl/HTMLTitleElement.webidl b/dom/webidl/HTMLTitleElement.webidl
index e6c8f2c61..bbce70bb2 100644
--- a/dom/webidl/HTMLTitleElement.webidl
+++ b/dom/webidl/HTMLTitleElement.webidl
@@ -7,7 +7,8 @@
* http://www.whatwg.org/specs/web-apps/current-work/#the-title-element
*/
+[HTMLConstructor]
interface HTMLTitleElement : HTMLElement {
- [Throws]
+ [CEReactions, Throws]
attribute DOMString text;
};
diff --git a/dom/webidl/HTMLTrackElement.webidl b/dom/webidl/HTMLTrackElement.webidl
index dd88e9beb..cbb70db2a 100644
--- a/dom/webidl/HTMLTrackElement.webidl
+++ b/dom/webidl/HTMLTrackElement.webidl
@@ -7,16 +7,17 @@
* http://www.whatwg.org/specs/web-apps/current-work/#the-track-element
*/
+[HTMLConstructor]
interface HTMLTrackElement : HTMLElement {
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString kind;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString src;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString srclang;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString label;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean default;
const unsigned short NONE = 0;
diff --git a/dom/webidl/HTMLUListElement.webidl b/dom/webidl/HTMLUListElement.webidl
index 0528198c9..725437494 100644
--- a/dom/webidl/HTMLUListElement.webidl
+++ b/dom/webidl/HTMLUListElement.webidl
@@ -13,13 +13,14 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-ul-element
+[HTMLConstructor]
interface HTMLUListElement : HTMLElement {
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLUListElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute boolean compact;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString type;
};
diff --git a/dom/webidl/HTMLVideoElement.webidl b/dom/webidl/HTMLVideoElement.webidl
index af28d5418..5ae4c016f 100644
--- a/dom/webidl/HTMLVideoElement.webidl
+++ b/dom/webidl/HTMLVideoElement.webidl
@@ -11,14 +11,15 @@
* and create derivative works of this document.
*/
+[HTMLConstructor]
interface HTMLVideoElement : HTMLMediaElement {
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long width;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute unsigned long height;
readonly attribute unsigned long videoWidth;
readonly attribute unsigned long videoHeight;
- [SetterThrows]
+ [CEReactions, SetterThrows]
attribute DOMString poster;
};
diff --git a/dom/webidl/NamedNodeMap.webidl b/dom/webidl/NamedNodeMap.webidl
index 41fbfcbb4..88e2ff51f 100644
--- a/dom/webidl/NamedNodeMap.webidl
+++ b/dom/webidl/NamedNodeMap.webidl
@@ -6,17 +6,17 @@
[LegacyUnenumerableNamedProperties]
interface NamedNodeMap {
getter Attr? getNamedItem(DOMString name);
- [Throws, BinaryName="setNamedItemNS"]
+ [CEReactions, Throws, BinaryName="setNamedItemNS"]
Attr? setNamedItem(Attr arg);
- [Throws]
+ [CEReactions, Throws]
Attr removeNamedItem(DOMString name);
getter Attr? item(unsigned long index);
readonly attribute unsigned long length;
Attr? getNamedItemNS(DOMString? namespaceURI, DOMString localName);
- [Throws]
+ [CEReactions, Throws]
Attr? setNamedItemNS(Attr arg);
- [Throws]
+ [CEReactions, Throws]
Attr removeNamedItemNS(DOMString? namespaceURI, DOMString localName);
};
diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl
index 7d18899b0..8b6dca788 100644
--- a/dom/webidl/Node.webidl
+++ b/dom/webidl/Node.webidl
@@ -57,21 +57,21 @@ interface Node : EventTarget {
[Pure]
readonly attribute Node? nextSibling;
- [SetterThrows, Pure]
+ [CEReactions, SetterThrows, Pure]
attribute DOMString? nodeValue;
- [Throws, Pure]
+ [CEReactions, Throws, Pure]
attribute DOMString? textContent;
- [Throws]
+ [CEReactions, Throws]
Node insertBefore(Node node, Node? child);
- [Throws]
+ [CEReactions, Throws]
Node appendChild(Node node);
- [Throws]
+ [CEReactions, Throws]
Node replaceChild(Node node, Node child);
- [Throws]
+ [CEReactions, Throws]
Node removeChild(Node child);
void normalize();
- [Throws]
+ [CEReactions, Throws]
Node cloneNode(optional boolean deep = false);
[Pure]
boolean isSameNode(Node? node);
diff --git a/dom/webidl/ParentNode.webidl b/dom/webidl/ParentNode.webidl
index 5834b9be3..aa6ca5db2 100644
--- a/dom/webidl/ParentNode.webidl
+++ b/dom/webidl/ParentNode.webidl
@@ -18,8 +18,8 @@ interface ParentNode {
[Pure]
readonly attribute unsigned long childElementCount;
- [Throws, Unscopable]
+ [CEReactions, Throws, Unscopable]
void prepend((Node or DOMString)... nodes);
- [Throws, Unscopable]
+ [CEReactions, Throws, Unscopable]
void append((Node or DOMString)... nodes);
};
diff --git a/dom/webidl/Range.webidl b/dom/webidl/Range.webidl
index ac8e1ebf0..6b8be970b 100644
--- a/dom/webidl/Range.webidl
+++ b/dom/webidl/Range.webidl
@@ -50,15 +50,15 @@ interface Range {
const unsigned short END_TO_START = 3;
[Throws]
short compareBoundaryPoints(unsigned short how, Range sourceRange);
- [Throws]
+ [CEReactions, Throws]
void deleteContents();
- [Throws]
+ [CEReactions, Throws]
DocumentFragment extractContents();
- [Throws]
+ [CEReactions, Throws]
DocumentFragment cloneContents();
- [Throws]
+ [CEReactions, Throws]
void insertNode(Node node);
- [Throws]
+ [CEReactions, Throws]
void surroundContents(Node newParent);
Range cloneRange();
@@ -77,7 +77,7 @@ interface Range {
// http://domparsing.spec.whatwg.org/#dom-range-createcontextualfragment
partial interface Range {
- [Throws]
+ [CEReactions, Throws]
DocumentFragment createContextualFragment(DOMString fragment);
};
diff --git a/dom/webidl/ShadowRoot.webidl b/dom/webidl/ShadowRoot.webidl
index a6c6de254..8dd069244 100644
--- a/dom/webidl/ShadowRoot.webidl
+++ b/dom/webidl/ShadowRoot.webidl
@@ -17,7 +17,7 @@ interface ShadowRoot : DocumentFragment
HTMLCollection getElementsByTagName(DOMString localName);
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
HTMLCollection getElementsByClassName(DOMString classNames);
- [SetterThrows,TreatNullAs=EmptyString]
+ [CEReactions, SetterThrows, TreatNullAs=EmptyString]
attribute DOMString innerHTML;
readonly attribute Element host;
readonly attribute ShadowRoot? olderShadowRoot;
diff --git a/dom/webidl/WebComponents.webidl b/dom/webidl/WebComponents.webidl
index 3dfb960bc..f9bb8214a 100644
--- a/dom/webidl/WebComponents.webidl
+++ b/dom/webidl/WebComponents.webidl
@@ -10,15 +10,19 @@
* liability, trademark and document use rules apply.
*/
-callback LifecycleCreatedCallback = void();
-callback LifecycleAttachedCallback = void();
-callback LifecycleDetachedCallback = void();
-callback LifecycleAttributeChangedCallback = void(DOMString attrName, DOMString? oldValue, DOMString? newValue);
+callback LifecycleConnectedCallback = void();
+callback LifecycleDisconnectedCallback = void();
+callback LifecycleAdoptedCallback = void(Document? oldDocument,
+ Document? newDocment);
+callback LifecycleAttributeChangedCallback = void(DOMString attrName,
+ DOMString? oldValue,
+ DOMString? newValue,
+ DOMString? namespaceURI);
dictionary LifecycleCallbacks {
- LifecycleCreatedCallback? createdCallback;
- LifecycleAttachedCallback? attachedCallback;
- LifecycleDetachedCallback? detachedCallback;
+ LifecycleConnectedCallback? connectedCallback;
+ LifecycleDisconnectedCallback? disconnectedCallback;
+ LifecycleAdoptedCallback? adoptedCallback;
LifecycleAttributeChangedCallback? attributeChangedCallback;
};
diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl
index 468f1cc8a..ab03bf40b 100644
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -78,9 +78,6 @@ typedef any Transferable;
[Throws, UnsafeInPrerendering, NeedsSubjectPrincipal] boolean confirm(optional DOMString message = "");
[Throws, UnsafeInPrerendering, NeedsSubjectPrincipal] DOMString? prompt(optional DOMString message = "", optional DOMString default = "");
[Throws, UnsafeInPrerendering] void print();
- //[Throws] any showModalDialog(DOMString url, optional any argument);
- [Throws, Func="nsGlobalWindow::IsShowModalDialogEnabled", UnsafeInPrerendering, NeedsSubjectPrincipal]
- any showModalDialog(DOMString url, optional any argument, optional DOMString options = "");
[Throws, CrossOriginCallable, NeedsSubjectPrincipal]
void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
@@ -240,17 +237,6 @@ interface SpeechSynthesisGetter {
Window implements SpeechSynthesisGetter;
#endif
-// http://www.whatwg.org/specs/web-apps/current-work/
-[NoInterfaceObject]
-interface WindowModal {
- [Throws, Func="nsGlobalWindow::IsModalContentWindow", NeedsSubjectPrincipal]
- readonly attribute any dialogArguments;
-
- [Throws, Func="nsGlobalWindow::IsModalContentWindow", NeedsSubjectPrincipal]
- attribute any returnValue;
-};
-Window implements WindowModal;
-
// Mozilla-specific stuff
partial interface Window {
//[NewObject, Throws] CSSStyleDeclaration getDefaultComputedStyle(Element elt, optional DOMString pseudoElt = "");
diff --git a/dom/webidl/XSLTProcessor.webidl b/dom/webidl/XSLTProcessor.webidl
index ce9ed846f..276e1b3fa 100644
--- a/dom/webidl/XSLTProcessor.webidl
+++ b/dom/webidl/XSLTProcessor.webidl
@@ -30,7 +30,7 @@ interface XSLTProcessor {
* @param output This document is used to generate the output
* @return DocumentFragment The result of the transformation
*/
- [Throws]
+ [CEReactions, Throws]
DocumentFragment transformToFragment(Node source,
Document output);
@@ -41,7 +41,7 @@ interface XSLTProcessor {
* @param source The node to be transformed
* @return Document The result of the transformation
*/
- [Throws]
+ [CEReactions, Throws]
Document transformToDocument(Node source);
/**
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp
index e351a46eb..a854f53ec 100644
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -174,33 +174,6 @@ nsXULElement::~nsXULElement()
{
}
-nsXULElement::nsXULSlots::nsXULSlots()
- : nsXULElement::nsDOMSlots()
-{
-}
-
-nsXULElement::nsXULSlots::~nsXULSlots()
-{
- NS_IF_RELEASE(mControllers); // Forces release
- nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
- if (frameLoader) {
- static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
- }
-}
-
-void
-nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
-{
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoaderOrOpener");
- cb.NoteXPCOMChild(mFrameLoaderOrOpener);
-}
-
-nsINode::nsSlots*
-nsXULElement::CreateSlots()
-{
- return new nsXULSlots();
-}
-
void
nsXULElement::MaybeUpdatePrivateLifetime()
{
@@ -326,12 +299,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
nsStyledElement)
- {
- nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
- if (slots) {
- slots->Traverse(cb);
- }
- }
+
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULElement,
@@ -895,9 +863,9 @@ nsXULElement::UnbindFromTree(bool aDeep, bool aNullParent)
// mDocument in nsGlobalWindow::SetDocShell, but I'm not
// sure whether that would fix all possible cycles through
// mControllers.)
- nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
- NS_IF_RELEASE(slots->mControllers);
+ slots->mControllers = nullptr;
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader) {
frameLoader->Destroy();
@@ -1241,9 +1209,9 @@ nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
void
nsXULElement::DestroyContent()
{
- nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
- NS_IF_RELEASE(slots->mControllers);
+ slots->mControllers = nullptr;
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader) {
frameLoader->Destroy();
@@ -1473,7 +1441,7 @@ nsIControllers*
nsXULElement::GetControllers(ErrorResult& rv)
{
if (! Controllers()) {
- nsDOMSlots* slots = DOMSlots();
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers),
reinterpret_cast<void**>(&slots->mControllers));
@@ -1578,7 +1546,7 @@ nsXULElement::LoadSrc()
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (!frameLoader) {
// Check if we have an opener we need to be setting
- nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryInterface(slots->mFrameLoaderOrOpener);
if (!opener) {
// If we are a content-primary xul-browser, we want to take the opener property!
@@ -1624,7 +1592,7 @@ nsXULElement::GetFrameLoaderXPCOM(nsIFrameLoader **aFrameLoader)
already_AddRefed<nsFrameLoader>
nsXULElement::GetFrameLoader()
{
- nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingSlots());
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (!slots)
return nullptr;
@@ -1646,7 +1614,7 @@ nsXULElement::GetParentApplication(mozIApplication** aApplication)
void
nsXULElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
{
- nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
+ nsExtendedDOMSlots* slots = ExtendedDOMSlots();
MOZ_ASSERT(!slots->mFrameLoaderOrOpener, "A frameLoader or opener is present when calling PresetOpenerWindow");
slots->mFrameLoaderOrOpener = aWindow;
@@ -1662,7 +1630,7 @@ nsXULElement::SetIsPrerendered()
void
nsXULElement::InternalSetFrameLoader(nsIFrameLoader* aNewFrameLoader)
{
- nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
MOZ_ASSERT(slots);
slots->mFrameLoaderOrOpener = aNewFrameLoader;
diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h
index 164afacd3..80424412f 100644
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -609,19 +609,6 @@ protected:
nsresult AddPopupListener(nsIAtom* aName);
- class nsXULSlots : public mozilla::dom::Element::nsDOMSlots
- {
- public:
- nsXULSlots();
- virtual ~nsXULSlots();
-
- void Traverse(nsCycleCollectionTraversalCallback &cb);
-
- nsCOMPtr<nsISupports> mFrameLoaderOrOpener;
- };
-
- virtual nsINode::nsSlots* CreateSlots() override;
-
nsresult LoadSrc();
/**
@@ -677,8 +664,8 @@ protected:
// Internal accessor. This shadows the 'Slots', and returns
// appropriate value.
nsIControllers *Controllers() {
- nsDOMSlots* slots = GetExistingDOMSlots();
- return slots ? slots->mControllers : nullptr;
+ nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
+ return slots ? slots->mControllers.get() : nullptr;
}
void UnregisterAccessKey(const nsAString& aOldValue);