DEV: Improve injectServiceIntoService function

Previously we were preventing circular dependencies by looking up the service before adding it as an injection for future-initialized services. This works, but it means that the order of service injection is important, and we cannot have two services auto-injected into each other.

This commit takes a different approach. It removes the `lookup`, and instead adds a dummy injection which prevents the service being injected into itself during initialization. This allows us to have circular auto-imports, without breaking the injection resolver by injecting a service into itself.
This commit is contained in:
David Taylor 2022-07-30 18:05:06 +01:00
parent f3b2ee8e1b
commit 2463a8d568

View File

@ -8,12 +8,18 @@ import User from "discourse/models/user";
const ALL_TARGETS = ["controller", "component", "route", "model", "adapter"];
function injectServiceIntoService({ container, app, property, specifier }) {
function injectServiceIntoService({ app, property, specifier }) {
// app.inject doesn't allow implicit injection of services into services.
// However, we need to do it in order to convert our old service-like objects
// into true services, without breaking existing implicit injections.
// This hack will be removed when we remove implicit injections for the Ember 4.0 update.
container.lookup(specifier);
// Supplying a specific injection with the same property name prevents the infinite
// which would be caused by injecting a service into itself
app.register("discourse:null", null, { instantiate: false });
app.inject(specifier, property, "discourse:null");
// Bypass the validation in `app.inject` by adding directly to the array
app.__registry__._typeInjections["service"].push({
property,
specifier,
@ -64,20 +70,17 @@ export default {
app.inject("service", "session", "session:main");
injectServiceIntoService({
container,
app,
property: "messageBus",
specifier: "service:message-bus",
});
injectServiceIntoService({
container,
app,
property: "siteSettings",
specifier: "service:site-settings",
});
app.inject("service", "topicTrackingState", "topic-tracking-state:main");
injectServiceIntoService({
container,
app,
property: "keyValueStore",
specifier: "service:key-value-store",