mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-25 00:27:29 +09:00
Issue #1375 - Fix IsWebComponentsEnabled checks
This commit is contained in:
parent
a6f048fc42
commit
ca48752304
13 changed files with 154 additions and 137 deletions
|
|
@ -2242,6 +2242,29 @@ WarnIfSandboxIneffective(nsIDocShell* aDocShell,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||||
|
{
|
||||||
|
if (!nsContentUtils::IsWebComponentsEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||||
|
|
||||||
|
JSAutoCompartment ac(aCx, obj);
|
||||||
|
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||||
|
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
|
||||||
|
|
||||||
|
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
|
||||||
|
if (doc && doc->IsStyledByServo()) {
|
||||||
|
NS_WARNING("stylo: Web Components not supported yet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||||
nsILoadGroup* aLoadGroup,
|
nsILoadGroup* aLoadGroup,
|
||||||
|
|
@ -5581,65 +5604,12 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
|
||||||
return attribute.forget();
|
return attribute.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
|
||||||
{
|
|
||||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
|
||||||
|
|
||||||
if (nsContentUtils::IsWebComponentsEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for the webcomponents permission. See Bug 1181555.
|
|
||||||
JSAutoCompartment ac(aCx, obj);
|
|
||||||
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
||||||
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
|
|
||||||
|
|
||||||
return IsWebComponentsEnabled(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsDocument::IsWebComponentsEnabled(const nsINode* aNode)
|
nsDocument::IsWebComponentsEnabled(const nsINode* aNode)
|
||||||
{
|
{
|
||||||
return aNode->OwnerDoc()->IsWebComponentsEnabled();
|
return aNode->OwnerDoc()->IsWebComponentsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
|
|
||||||
{
|
|
||||||
if (nsContentUtils::IsWebComponentsEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIDocument* doc = aNodeInfo->GetDocument();
|
|
||||||
// Use GetScopeObject() here so that data documents work the same way as the
|
|
||||||
// main document they're associated with.
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
||||||
do_QueryInterface(doc->GetScopeObject());
|
|
||||||
return IsWebComponentsEnabled(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
|
|
||||||
{
|
|
||||||
if (aWindow) {
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
|
||||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
|
||||||
|
|
||||||
uint32_t perm;
|
|
||||||
rv = permMgr->TestPermissionFromWindow(
|
|
||||||
aWindow, "moz-extremely-unstable-and-will-change-webcomponents", &perm);
|
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
|
||||||
|
|
||||||
return perm == nsIPermissionManager::ALLOW_ACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocument::GetElementsByTagName(const nsAString& aTagname,
|
nsDocument::GetElementsByTagName(const nsAString& aTagname,
|
||||||
nsIDOMNodeList** aReturn)
|
nsIDOMNodeList** aReturn)
|
||||||
|
|
|
||||||
|
|
@ -755,6 +755,11 @@ public:
|
||||||
|
|
||||||
virtual void NotifyLayerManagerRecreated() override;
|
virtual void NotifyLayerManagerRecreated() override;
|
||||||
|
|
||||||
|
// Check whether web components are enabled for the global of aObject.
|
||||||
|
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||||
|
// Check whether web components are enabled for the document this node belongs
|
||||||
|
// to.
|
||||||
|
static bool IsWebComponentsEnabled(const nsINode* aNode);
|
||||||
private:
|
private:
|
||||||
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
|
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
|
||||||
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
|
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
|
||||||
|
|
@ -1341,17 +1346,6 @@ protected:
|
||||||
nsWeakPtr mFullscreenRoot;
|
nsWeakPtr mFullscreenRoot;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Check whether web components are enabled for the global of aObject.
|
|
||||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
|
||||||
// Check whether web components are enabled for the document this node belongs
|
|
||||||
// to.
|
|
||||||
static bool IsWebComponentsEnabled(const nsINode* aNode);
|
|
||||||
// Check whether web components are enabled for the global of the document
|
|
||||||
// this nodeinfo comes from.
|
|
||||||
static bool IsWebComponentsEnabled(mozilla::dom::NodeInfo* aNodeInfo);
|
|
||||||
// Check whether web components are enabled for the given window.
|
|
||||||
static bool IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow);
|
|
||||||
|
|
||||||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||||
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
||||||
RefPtr<nsScriptLoader> mScriptLoader;
|
RefPtr<nsScriptLoader> mScriptLoader;
|
||||||
|
|
|
||||||
|
|
@ -236,17 +236,17 @@ dictionary ShadowRootInit {
|
||||||
// https://dom.spec.whatwg.org/#element
|
// https://dom.spec.whatwg.org/#element
|
||||||
partial interface Element {
|
partial interface Element {
|
||||||
// Shadow DOM v1
|
// Shadow DOM v1
|
||||||
[Throws, Pref="nsDocument::IsWebComponentsEnabled"]
|
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
|
||||||
ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
|
ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
|
||||||
[BinaryName="shadowRootByMode", Func="nsDocument::IsWebComponentsEnabled"]
|
[BinaryName="shadowRootByMode", Func="nsDocument::IsWebComponentsEnabled"]
|
||||||
readonly attribute ShadowRoot? shadowRoot;
|
readonly attribute ShadowRoot? shadowRoot;
|
||||||
[BinaryName="assignedSlotByMode", Pref="nsDocument::IsWebComponentsEnabled"]
|
[BinaryName="assignedSlotByMode", Func="nsDocument::IsWebComponentsEnabled"]
|
||||||
readonly attribute HTMLSlotElement? assignedSlot;
|
readonly attribute HTMLSlotElement? assignedSlot;
|
||||||
[CEReactions, Unscopable, SetterThrows, Pref="nsDocument::IsWebComponentsEnabled"]
|
[CEReactions, Unscopable, SetterThrows, Func="nsDocument::IsWebComponentsEnabled"]
|
||||||
attribute DOMString slot;
|
attribute DOMString slot;
|
||||||
|
|
||||||
// [deprecated] Shadow DOM v0
|
// [deprecated] Shadow DOM v0
|
||||||
[Throws, Pref="nsDocument::IsWebComponentsEnabled"]
|
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
|
||||||
ShadowRoot createShadowRoot();
|
ShadowRoot createShadowRoot();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<script>
|
<script>
|
||||||
function insertShadowSVG() {
|
function insertShadowSVG() {
|
||||||
var x = document.getElementById("x");
|
var x = document.getElementById("x");
|
||||||
|
if (x.createShadowRoot) {
|
||||||
x.createShadowRoot();
|
x.createShadowRoot();
|
||||||
x.shadowRoot.innerHTML =
|
x.shadowRoot.innerHTML =
|
||||||
'<svg width="50px" height="10px"> \
|
'<svg width="50px" height="10px"> \
|
||||||
|
|
@ -16,6 +17,7 @@
|
||||||
</foreignObject> \
|
</foreignObject> \
|
||||||
</switch> \
|
</switch> \
|
||||||
</svg>';
|
</svg>';
|
||||||
|
}
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
window.addEventListener("MozReftestInvalidate", insertShadowSVG, false);
|
window.addEventListener("MozReftestInvalidate", insertShadowSVG, false);
|
||||||
|
|
|
||||||
|
|
@ -1851,7 +1851,7 @@ test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.htm
|
||||||
== 1062108-1.html 1062108-1-ref.html
|
== 1062108-1.html 1062108-1-ref.html
|
||||||
== 1062792-1.html 1062792-1-ref.html
|
== 1062792-1.html 1062792-1-ref.html
|
||||||
== 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
|
== 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
|
||||||
test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html
|
test-pref(dom.webcomponents.enabled,true) fails-if(stylo||styloVsGecko) == 1066554-1.html 1066554-1-ref.html
|
||||||
== 1069716-1.html 1069716-1-ref.html
|
== 1069716-1.html 1069716-1-ref.html
|
||||||
== 1078262-1.html about:blank
|
== 1078262-1.html about:blank
|
||||||
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
|
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ div.after::after {content: " Y";}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
document.body.offsetHeight;
|
document.body.offsetHeight;
|
||||||
|
|
||||||
shadow("host1").innerHTML = '<content></content> c';
|
shadow("host1").innerHTML = '<content></content> c';
|
||||||
|
|
@ -103,7 +104,10 @@ div.after::after {content: " Y";}
|
||||||
shadow("hostP").innerHTML = '<content select="b"></content><content select="i"></content>';
|
shadow("hostP").innerHTML = '<content select="b"></content><content select="i"></content>';
|
||||||
shadow("hostQ").innerHTML = '<content select="b"></content><content select="i"></content>';
|
shadow("hostQ").innerHTML = '<content select="b"></content><content select="i"></content>';
|
||||||
shadow("hostR").innerHTML = '<content select="span"></content>';
|
shadow("hostR").innerHTML = '<content select="span"></content>';
|
||||||
|
shadow("hostW").innerHTML = '<z style="color:red"><content select="b"></content></z>';
|
||||||
|
shadow("hostX").innerHTML = '<z style="color:red"><content select="b"></content></z>';
|
||||||
// TODO(bug 1021572?) shadow("hostY").innerHTML = '<content select="b"><style scoped>:scope{color:green}</style></content>';
|
// TODO(bug 1021572?) shadow("hostY").innerHTML = '<content select="b"><style scoped>:scope{color:green}</style></content>';
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
document.body.offsetHeight;
|
document.body.offsetHeight;
|
||||||
|
|
@ -224,7 +228,12 @@ div.after::after {content: " Y";}
|
||||||
},0);
|
},0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
window.addEventListener("MozReftestInvalidate", tweak, false);
|
window.addEventListener("MozReftestInvalidate", tweak, false);
|
||||||
|
} else {
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ div.after::after {content: " Y";}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
document.body.offsetHeight;
|
document.body.offsetHeight;
|
||||||
|
|
||||||
shadow("host1").innerHTML = '<content></content> c';
|
shadow("host1").innerHTML = '<content></content> c';
|
||||||
|
|
@ -59,6 +60,7 @@ div.after::after {content: " Y";}
|
||||||
shadow("host7").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
|
shadow("host7").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
|
||||||
shadow("host8").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
|
shadow("host8").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
|
||||||
shadow("host9").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
|
shadow("host9").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
document.body.offsetHeight;
|
document.body.offsetHeight;
|
||||||
|
|
@ -105,7 +107,12 @@ div.after::after {content: " Y";}
|
||||||
},0);
|
},0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
window.addEventListener("MozReftestInvalidate", tweak, false);
|
window.addEventListener("MozReftestInvalidate", tweak, false);
|
||||||
|
} else {
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
<script>
|
<script>
|
||||||
function insertShadowMathML() {
|
function insertShadowMathML() {
|
||||||
var x = document.getElementById("x");
|
var x = document.getElementById("x");
|
||||||
|
if (x.createShadowRoot) {
|
||||||
x.createShadowRoot();
|
x.createShadowRoot();
|
||||||
x.shadowRoot.innerHTML =
|
x.shadowRoot.innerHTML =
|
||||||
'<math><msup><mi>X</mi><mi>X</mi></msup></math>';
|
'<math><msup><mi>X</mi><mi>X</mi></msup></math>';
|
||||||
|
}
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
window.addEventListener("MozReftestInvalidate", insertShadowMathML, false);
|
window.addEventListener("MozReftestInvalidate", insertShadowMathML, false);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@
|
||||||
<head>
|
<head>
|
||||||
<script>
|
<script>
|
||||||
function tweak() {
|
function tweak() {
|
||||||
|
if (!document.body.createShadowRoot) {
|
||||||
|
document.documentElement.className = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var host = document.getElementById("host");
|
var host = document.getElementById("host");
|
||||||
var shadow = host.createShadowRoot();
|
var shadow = host.createShadowRoot();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
<script>
|
<script>
|
||||||
var host, root;
|
var host, root;
|
||||||
|
|
||||||
|
function run() {
|
||||||
host = document.getElementById("host");
|
host = document.getElementById("host");
|
||||||
root = host.attachShadow({mode: 'open'});
|
root = host.createShadowRoot();
|
||||||
root.innerHTML = 'a <slot></slot> c';
|
root.innerHTML = 'a <content></content> c';
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
var span = document.createElement("span");
|
var span = document.createElement("span");
|
||||||
|
|
@ -21,7 +23,12 @@
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("MozReftestInvalidate", tweak);
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
|
window.addEventListener("MozReftestInvalidate", tweak, false);
|
||||||
|
} else {
|
||||||
|
document.documentElement.className = "";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
<script>
|
<script>
|
||||||
var host, root;
|
var host, root;
|
||||||
|
|
||||||
|
function run() {
|
||||||
host = document.getElementById("host");
|
host = document.getElementById("host");
|
||||||
root = host.attachShadow({mode: 'open'});
|
root = host.createShadowRoot();
|
||||||
root.innerHTML = "<span>a</span>";
|
root.innerHTML = "<span>a</span>";
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
var span = document.createElement("span");
|
var span = document.createElement("span");
|
||||||
|
|
@ -22,7 +24,12 @@
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
window.addEventListener("MozReftestInvalidate", tweak);
|
window.addEventListener("MozReftestInvalidate", tweak);
|
||||||
|
} else {
|
||||||
|
document.documentElement.className = "";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
<script>
|
<script>
|
||||||
var host, root;
|
var host, root;
|
||||||
|
|
||||||
|
function run() {
|
||||||
host = document.getElementById("host");
|
host = document.getElementById("host");
|
||||||
root = host.attachShadow({mode: 'open'});
|
root = host.createShadowRoot();
|
||||||
root.innerHTML = '<style>input ~ div { background: red; transition: background 100ms; } input:checked ~ div { background: green; }</style><input id="one" type="checkbox"><div style="height: 50px; width: 50px;"></div>';
|
root.innerHTML = '<style>input ~ div { background: red; transition: background 100ms; } input:checked ~ div { background: green; }</style><input id="one" type="checkbox"><div style="height: 50px; width: 50px;"></div>';
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
var el = root.getElementById("one");
|
var el = root.getElementById("one");
|
||||||
|
|
@ -19,7 +21,12 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
window.addEventListener("MozReftestInvalidate", tweak);
|
window.addEventListener("MozReftestInvalidate", tweak);
|
||||||
|
} else {
|
||||||
|
document.documentElement.className = "";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
<div id="outer"><span id="distnode">text</span></div>
|
<div id="outer"><span id="distnode">text</span></div>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
|
function run() {
|
||||||
shadowRoot.innerHTML = '<div><slot></slot></div>';
|
var shadowRoot = document.getElementById('outer').createShadowRoot();
|
||||||
|
shadowRoot.innerHTML = '<div><content></content></div>';
|
||||||
|
}
|
||||||
|
|
||||||
function tweak() {
|
function tweak() {
|
||||||
var distNode = document.getElementById("distnode");
|
var distNode = document.getElementById("distnode");
|
||||||
|
|
@ -16,7 +18,12 @@
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.body.createShadowRoot) {
|
||||||
|
run();
|
||||||
window.addEventListener("MozReftestInvalidate", tweak);
|
window.addEventListener("MozReftestInvalidate", tweak);
|
||||||
|
} else {
|
||||||
|
document.documentElement.className = "";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue