Files
Andrew McCreight e5895fd4d2 Bug 2062720 - Don't allow CreateInstance for singleton XPCOM components. r=nika,necko-reviewers,valentin
This patch tracks which XPCOM components are singletons at runtime, and
throws an error if you attempt to call createInstance for a singleton.
The motivation here is that many singleton XPCOM components only expect
to be created once, via do_GetService(), and calling do_CreateInstance()
multiple times could result in races or memory corruption, which we'd like
to avoid.

The system principal is implemented as a singleton, but it isn't a service,
and calls to createInstance with it far outnumber the calls to getService.
Furthermore, you have to be able to createInstance it to work with
nsBinaryStream. For these reasons, the patch changes the 'singleton' property
for it to False. The nsBinaryStream behavior is tested in
test_binarystream_systemprincipal.js.

The test browser_bug1535877.js was testing that you can safely createInstance
the eTLD service, but now it simply throws. That aspect is maintained by XPCOM
and not the eTLD service itself, so I've moved the test into test_create_single.js
and updated it for the new behavior.

Differential Revision: https://phabricator.services.mozilla.com/D320728
2026-08-24 22:22:50 +00:00

28 lines
1.1 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const ETLD_CONTRACT_ID = "@mozilla.org/network/effective-tld-service;1";
function run_test() {
// The effective TLD service is a singleton, so createInstance is not allowed
// on it: it must be accessed via the service getters.
Assert.throws(
() => Cc[ETLD_CONTRACT_ID].createInstance(Ci.nsIEffectiveTLDService),
e => e.result == Cr.NS_ERROR_XPC_CI_RETURNED_FAILURE,
"createInstance should throw for a singleton component"
);
// Check that the service getters all return the same object.
// eslint-disable-next-line mozilla/use-services
let etld = Cc[ETLD_CONTRACT_ID].getService(Ci.nsIEffectiveTLDService);
Assert.equal(etld, Services.eTLD, "getService returns the singleton");
// For backwards compatibility reasons, we allow calling createInstance for
// the system principal, so it should not throw.
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
Ci.nsIPrincipal
);
Assert.notEqual(principal, undefined);
}