mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 883683 - Leak with DOM promises. r=bz
This commit is contained in:
parent
7f4d63c6b8
commit
12938be54b
@ -108,6 +108,17 @@ Future::PrefEnabled()
|
|||||||
return Preferences::GetBool("dom.future.enabled", false);
|
return Preferences::GetBool("dom.future.enabled", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
|
||||||
|
const Optional<JS::Handle<JS::Value> >& aValue)
|
||||||
|
{
|
||||||
|
// FIXME Bug 878849
|
||||||
|
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||||
|
JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
|
||||||
|
aAc.construct(aCx, rooted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<Future>
|
/* static */ already_AddRefed<Future>
|
||||||
Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
||||||
FutureInit& aInit, ErrorResult& aRv)
|
FutureInit& aInit, ErrorResult& aRv)
|
||||||
@ -129,6 +140,9 @@ Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
|||||||
if (aRv.IsJSException()) {
|
if (aRv.IsJSException()) {
|
||||||
Optional<JS::Handle<JS::Value> > value(aCx);
|
Optional<JS::Handle<JS::Value> > value(aCx);
|
||||||
aRv.StealJSException(aCx, &value.Value());
|
aRv.StealJSException(aCx, &value.Value());
|
||||||
|
|
||||||
|
Maybe<JSAutoCompartment> ac;
|
||||||
|
EnterCompartment(ac, aCx, value);
|
||||||
future->mResolver->Reject(aCx, value);
|
future->mResolver->Reject(aCx, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,17 @@ FutureCallback::~FutureCallback()
|
|||||||
MOZ_COUNT_DTOR(FutureCallback);
|
MOZ_COUNT_DTOR(FutureCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
|
||||||
|
const Optional<JS::Handle<JS::Value> >& aValue)
|
||||||
|
{
|
||||||
|
// FIXME Bug 878849
|
||||||
|
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||||
|
JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
|
||||||
|
aAc.construct(aCx, rooted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResolveFutureCallback
|
// ResolveFutureCallback
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolveFutureCallback,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolveFutureCallback,
|
||||||
@ -63,12 +74,8 @@ ResolveFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
|||||||
{
|
{
|
||||||
// Run resolver's algorithm with value and the synchronous flag set.
|
// Run resolver's algorithm with value and the synchronous flag set.
|
||||||
AutoJSContext cx;
|
AutoJSContext cx;
|
||||||
// FIXME Bug 878849
|
|
||||||
Maybe<JSAutoCompartment> ac;
|
Maybe<JSAutoCompartment> ac;
|
||||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
EnterCompartment(ac, cx, aValue);
|
||||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
|
||||||
ac.construct(cx, rooted);
|
|
||||||
}
|
|
||||||
|
|
||||||
mResolver->ResolveInternal(cx, aValue, FutureResolver::SyncTask);
|
mResolver->ResolveInternal(cx, aValue, FutureResolver::SyncTask);
|
||||||
}
|
}
|
||||||
@ -102,12 +109,8 @@ RejectFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
|||||||
{
|
{
|
||||||
// Run resolver's algorithm with value and the synchronous flag set.
|
// Run resolver's algorithm with value and the synchronous flag set.
|
||||||
AutoJSContext cx;
|
AutoJSContext cx;
|
||||||
// FIXME Bug 878849
|
|
||||||
Maybe<JSAutoCompartment> ac;
|
Maybe<JSAutoCompartment> ac;
|
||||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
EnterCompartment(ac, cx, aValue);
|
||||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
|
||||||
ac.construct(cx, rooted);
|
|
||||||
}
|
|
||||||
|
|
||||||
mResolver->RejectInternal(cx, aValue, FutureResolver::SyncTask);
|
mResolver->RejectInternal(cx, aValue, FutureResolver::SyncTask);
|
||||||
}
|
}
|
||||||
@ -142,12 +145,8 @@ void
|
|||||||
WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||||
{
|
{
|
||||||
AutoJSContext cx;
|
AutoJSContext cx;
|
||||||
// FIXME Bug 878849
|
|
||||||
Maybe<JSAutoCompartment> ac;
|
Maybe<JSAutoCompartment> ac;
|
||||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
EnterCompartment(ac, cx, aValue);
|
||||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
|
||||||
ac.construct(cx, rooted);
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
|
|
||||||
@ -162,12 +161,17 @@ WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
|||||||
if (rv.Failed() && rv.IsJSException()) {
|
if (rv.Failed() && rv.IsJSException()) {
|
||||||
Optional<JS::Handle<JS::Value> > value(cx);
|
Optional<JS::Handle<JS::Value> > value(cx);
|
||||||
rv.StealJSException(cx, &value.Value());
|
rv.StealJSException(cx, &value.Value());
|
||||||
|
|
||||||
|
Maybe<JSAutoCompartment> ac2;
|
||||||
|
EnterCompartment(ac2, cx, value);
|
||||||
mNextResolver->RejectInternal(cx, value, FutureResolver::SyncTask);
|
mNextResolver->RejectInternal(cx, value, FutureResolver::SyncTask);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, run resolver's resolve with value and the synchronous flag
|
// Otherwise, run resolver's resolve with value and the synchronous flag
|
||||||
// set.
|
// set.
|
||||||
|
Maybe<JSAutoCompartment> ac2;
|
||||||
|
EnterCompartment(ac2, cx, value);
|
||||||
mNextResolver->ResolveInternal(cx, value, FutureResolver::SyncTask);
|
mNextResolver->ResolveInternal(cx, value, FutureResolver::SyncTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
MOCHITEST_FILES = \
|
MOCHITEST_FILES = \
|
||||||
test_future.html \
|
test_future.html \
|
||||||
test_resolve.html \
|
test_resolve.html \
|
||||||
|
test_bug883683.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
41
dom/future/tests/test_bug883683.html
Normal file
41
dom/future/tests/test_bug883683.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Future - bug 883683</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript"><!--
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
[{}, {}, {}, {}, {}].reduce(Future.reject);
|
||||||
|
ok(true, "No leaks with reject?");
|
||||||
|
|
||||||
|
[{}, {}, {}, {}, {}].reduce(Future.resolve);
|
||||||
|
ok(true, "No leaks with resolve?");
|
||||||
|
|
||||||
|
[{}, {}, {}, {}, {}].reduce(function(a, b, c, d) { return new Future(function(r) { throw a; }); });
|
||||||
|
ok(true, "No leaks with exception?");
|
||||||
|
|
||||||
|
[{}, {}, {}, {}, {}].reduce(function(a, b, c, d) { return new Future(function(r) { }); });
|
||||||
|
ok(true, "No leaks with empty future?");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
|
||||||
|
// -->
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user