Bug 1493237 - Use a test-only non-nsISupports wrapper cached WebIDL class in a weak map test r=bzbarsky

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrew McCreight 2018-10-11 23:02:10 +00:00
parent a5939cf925
commit 53217795fe
8 changed files with 122 additions and 24 deletions

View File

@ -122,11 +122,11 @@ SOURCES += [
'StructuredClone.cpp',
]
# Tests for maplike and setlike require bindings to be built, which means they
# must be included in libxul. This breaks the "no test classes are exported"
# rule stated in the test/ directory, but it's the only way this will work.
# Test classes are only built in debug mode, and all tests requiring use of
# them are only run in debug mode.
# Some tests, including those for for maplike and setlike, require bindings
# to be built, which means they must be included in libxul. This breaks the
# "no test classes are exported" rule stated in the test/ directory, but it's
# the only way this will work. Test classes are only built in debug mode, and
# all tests requiring use of them are only run in debug mode.
if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
EXPORTS.mozilla.dom += [
"test/TestFunctions.h",
@ -136,7 +136,8 @@ if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
"test/TestInterfaceMaplike.h",
"test/TestInterfaceMaplikeObject.h",
"test/TestInterfaceSetlike.h",
"test/TestInterfaceSetlikeNode.h"
"test/TestInterfaceSetlikeNode.h",
"test/WrapperCachedNonISupportsTestInterface.h",
]
UNIFIED_SOURCES += [
"test/TestFunctions.cpp",
@ -147,6 +148,7 @@ if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
"test/TestInterfaceMaplikeObject.cpp",
"test/TestInterfaceSetlike.cpp",
"test/TestInterfaceSetlikeNode.cpp",
"test/WrapperCachedNonISupportsTestInterface.cpp",
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -7,6 +7,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/TestFunctions.h"
#include "mozilla/dom/TestFunctionsBinding.h"
#include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h"
#include "nsStringBuffer.h"
#include "mozITestInterfaceJS.h"
#include "nsComponentManagerUtils.h"
@ -140,6 +141,15 @@ TestFunctions::ObjectFromAboutBlank(JSContext* aCx, JSObject* aObj)
return doc->GetDocumentURI()->GetSpecOrDefault().EqualsLiteral("about:blank");
}
WrapperCachedNonISupportsTestInterface*
TestFunctions::WrapperCachedNonISupportsObject()
{
if (!mWrapperCachedNonISupportsTestInterface) {
mWrapperCachedNonISupportsTestInterface = new WrapperCachedNonISupportsTestInterface();
}
return mWrapperCachedNonISupportsTestInterface;
}
bool
TestFunctions::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aWrapper)

View File

@ -17,6 +17,7 @@ namespace dom {
class Promise;
class PromiseReturner;
class WrapperCachedNonISupportsTestInterface;
class TestFunctions : public NonRefcountedDOMObject {
public:
@ -51,10 +52,13 @@ public:
static bool ObjectFromAboutBlank(JSContext* aCx, JSObject* aObj);
WrapperCachedNonISupportsTestInterface* WrapperCachedNonISupportsObject();
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aWrapper);
private:
nsString mStringData;
RefPtr<WrapperCachedNonISupportsTestInterface> mWrapperCachedNonISupportsTestInterface;
};
} // namespace dom

View File

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h"
#include "mozilla/dom/TestFunctionsBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WrapperCachedNonISupportsTestInterface, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WrapperCachedNonISupportsTestInterface, Release)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WrapperCachedNonISupportsTestInterface)
JSObject*
WrapperCachedNonISupportsTestInterface::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return WrapperCachedNonISupportsTestInterface_Binding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WrapperCachedNonISupportsTestInterface_h
#define mozilla_dom_WrapperCachedNonISupportsTestInterface_h
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class WrapperCachedNonISupportsTestInterface final : public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WrapperCachedNonISupportsTestInterface)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WrapperCachedNonISupportsTestInterface)
public:
WrapperCachedNonISupportsTestInterface() {}
protected:
~WrapperCachedNonISupportsTestInterface() {}
public:
nsISupports* GetParentObject() const {
return nullptr;
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_WrapperCachedNonISupportsTestInterface_h

View File

@ -8,6 +8,10 @@
callback PromiseReturner = Promise<any>();
[Pref="dom.expose_test_interfaces"]
interface WrapperCachedNonISupportsTestInterface {
};
[Pref="dom.expose_test_interfaces",
Constructor]
interface TestFunctions {
@ -56,4 +60,11 @@ interface TestFunctions {
// Testing for how default toJSON behaves.
[Default] object toJSON();
// This returns a wrappercached non-ISupports object. While this will always
// return the same object, no optimization attributes like [Pure] should be
// used here because the object should not be held alive from JS by the
// bindings. This is needed to test wrapper preservation for weak map keys.
// See bug 1351501.
readonly attribute WrapperCachedNonISupportsTestInterface wrapperCachedNonISupportsObject;
};

View File

@ -103,6 +103,7 @@ support-files =
skip-if = (debug == false)
[test_getweakmapkeys.html]
[test_paris_weakmap_keys.html]
skip-if = (debug == false)
[test_nac.xhtml]
[test_nukeContentWindow.html]
[test_sameOriginPolicy.html]

View File

@ -39,28 +39,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777385
make_live_map();
// CanvasGradient is a non-nsISupports wrapper cached class using WebIDL
// bindings. If we used it as a key in a weak map, then it should not be
// removed from the weak map as long as it remains alive.
let doc = new DOMParser().parseFromString("", "text/html");
let canv = doc.createElement("canvas");
let ctx = canv.getContext("2d");
let tf = new TestFunctions;
let add_non_isupports2 = function () {
let grad = ctx.createLinearGradient(0, 0, 0, 0);
ctx.strokeStyle = grad;
let testKey = tf.wrapperCachedNonISupportsObject;
let gradFail = false;
let testFail = false;
try {
live_map.set(grad, 23456);
live_map.set(testKey, 23456);
} catch (e) {
gradFail = true;
testFail = true;
}
ok(!gradFail, "Using a wrapper cached non-nsISupports class as a weak map key should not produce an exception.");
ok(!testFail, "Using a wrapper cached non-nsISupports class as a weak map key should not produce an exception.");
is(live_map.get(grad), 23456, "Live map should have live DOMPoint with right value before GC.");
is(live_map.get(testKey), 23456, "Live map should have wrapper cached non-nsISupports class right value before GC.");
}
add_non_isupports2();
@ -74,20 +67,28 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777385
SpecialPowers.forceGC();
is(SpecialPowers.nondeterministicGetWeakMapKeys(live_map).length, 2,
"Live nsISupports new DOM bindings wrappercached native weak map key should not be removed.");
"Live WebIDL bindings keys should not be removed from a weak map.");
is(live_map.get(get_div_style()), 12345, "Live map should have live style with right value after GC.");
is(live_map.get(ctx.strokeStyle), 23456, "Live map should have live gradient with right value after GC.");
is(live_map.get(get_div_style()), 12345, "Live weak map should have live style with right value after GC.");
is(live_map.get(tf.wrapperCachedNonISupportsObject), 23456,
"Live weak map should have live wrapper cached non-nsISupports class with right value after GC.");
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]},
go);
});
</script>
</head>
<div></div>
<div id="mydivname"></div>
<body onload="go()";>
<body>
<p id="display"></p>
</body>
</html>