summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2020-01-20 20:14:59 -0500
committerGaming4JC <g4jc@hyperbola.info>2020-01-26 15:50:48 -0500
commit8db81508a1ffe1c3873503a1cb2082d664714776 (patch)
treedd1ef38691c25a80787dfcdca06038a7fac18c7e
parent4083a9abf76058d35f0277dd6857478fc6715137 (diff)
downloadUXP-8db81508a1ffe1c3873503a1cb2082d664714776.tar
UXP-8db81508a1ffe1c3873503a1cb2082d664714776.tar.gz
UXP-8db81508a1ffe1c3873503a1cb2082d664714776.tar.lz
UXP-8db81508a1ffe1c3873503a1cb2082d664714776.tar.xz
UXP-8db81508a1ffe1c3873503a1cb2082d664714776.zip
Bug 1415761 - Catch the exception and rethrow it after invoking custom elements reactions;
The spec was unclear on how CEReactions interact with thrown exceptions; see https://github.com/whatwg/html/issues/3217. The spec is now being clarified in https://github.com/whatwg/html/pull/3235. Tag UXP Issue #1344
-rw-r--r--dom/base/CustomElementRegistry.h13
-rw-r--r--dom/base/nsDocument.cpp3
-rw-r--r--dom/bindings/Codegen.py2
-rw-r--r--js/xpconnect/tests/mochitest/test_bug1094930.html6
-rw-r--r--parser/html/nsHtml5TreeOperation.cpp3
-rw-r--r--testing/web-platform/tests/custom-elements/reactions/with-exceptions.html31
6 files changed, 50 insertions, 8 deletions
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index c180a10af..51c97fd5e 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -472,15 +472,24 @@ public:
class MOZ_RAII AutoCEReaction final {
public:
- explicit AutoCEReaction(CustomElementReactionsStack* aReactionsStack)
- : mReactionsStack(aReactionsStack) {
+ // 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) {
mReactionsStack->CreateAndPushElementQueue();
}
~AutoCEReaction() {
+ Maybe<JS::AutoSaveExceptionState> ases;
+ if (mCx) {
+ ases.emplace(mCx);
+ }
mReactionsStack->PopAndInvokeElementQueue();
}
private:
RefPtr<CustomElementReactionsStack> mReactionsStack;
+ JSContext* mCx;
};
} // namespace dom
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 9043e409a..f3e492589 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5809,7 +5809,8 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
return;
}
- AutoCEReaction ceReaction(this->GetDocGroup()->CustomElementReactionsStack());
+ AutoCEReaction ceReaction(this->GetDocGroup()->CustomElementReactionsStack(),
+ aCx);
// Unconditionally convert TYPE to lowercase.
nsAutoString lcType;
nsContentUtils::ASCIIToLower(aType, lcType);
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 730465fee..8ee732cca 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7679,7 +7679,7 @@ class CGPerSignatureCall(CGThing):
CustomElementReactionsStack* reactionsStack = GetCustomElementReactionsStack(${obj});
Maybe<AutoCEReaction> ceReaction;
if (reactionsStack) {
- ceReaction.emplace(reactionsStack);
+ ceReaction.emplace(reactionsStack, cx);
}
""", obj=objectName)))
diff --git a/js/xpconnect/tests/mochitest/test_bug1094930.html b/js/xpconnect/tests/mochitest/test_bug1094930.html
index 434949360..674edfe47 100644
--- a/js/xpconnect/tests/mochitest/test_bug1094930.html
+++ b/js/xpconnect/tests/mochitest/test_bug1094930.html
@@ -16,14 +16,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094930
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var proto = {
- createdCallback: function() {
- ok(true, "createdCallback was called");
+ connectedCallback: function() {
+ ok(true, "connectedCallback was called");
SimpleTest.finish()
}
};
var f = document.registerElement.call(frames[0].document, "x-foo", { prototype: proto });
- var inst = new f();
+ frames[0].document.firstChild.appendChild(new f());
</script>
</body>
</html>
diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp
index d530cbba3..d747f80a8 100644
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -450,7 +450,8 @@ nsHtml5TreeOperation::CreateHTMLElement(
nsAutoMicroTask mt;
}
dom::AutoCEReaction
- autoCEReaction(document->GetDocGroup()->CustomElementReactionsStack());
+ autoCEReaction(document->GetDocGroup()->CustomElementReactionsStack(),
+ nullptr);
nsCOMPtr<dom::Element> newElement;
NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
diff --git a/testing/web-platform/tests/custom-elements/reactions/with-exceptions.html b/testing/web-platform/tests/custom-elements/reactions/with-exceptions.html
new file mode 100644
index 000000000..82e0f59c9
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/with-exceptions.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Custom Elements: CEReactions interaction with exceptions</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<meta name="help" content="https://html.spec.whatwg.org/multipage/#cereactions">
+<meta name="help" content="https://github.com/whatwg/html/pull/3235">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+
+<div id="log"></div>
+
+<script>
+"use strict";
+// Basically from https://github.com/whatwg/html/issues/3217#issuecomment-343633273
+test_with_window((contentWindow, contentDocument) => {
+ let reactionRan = false;
+ contentWindow.customElements.define("custom-element", class extends contentWindow.HTMLElement {
+ disconnectedCallback() {
+ reactionRan = true;
+ }
+ });
+ const text = contentDocument.createTextNode("");
+ contentDocument.documentElement.appendChild(text);
+ const element = contentDocument.createElement("custom-element");
+ contentDocument.documentElement.appendChild(element);
+ assert_throws("HierarchyRequestError", () => text.before("", contentDocument.documentElement));
+ assert_true(reactionRan);
+}, "Reaction must run even after the exception is thrown");
+</script>