DEV: Deprecate implicit injections for all services

Ember's implementation of implicit injections is removed in Ember 4.x. In Discourse, we've implemented a shim for the behavior via 743be2d596 to buy us more time. This commit takes an incremental step towards removing the shim by introducing a deprecation notice for all implicit injections on "Service" classes, which should be the easiest to fix up.

Eventually we will want to do something similar for Controller/Route/etc, so this commit implements the deprecation notice in a generic way.

Before merging this commit, we'll need to fix up the remaining implicit injections in core services. (in the core test suite, relying on deprecations causes test failures)
This commit is contained in:
David Taylor 2023-09-25 15:16:00 +01:00
parent 70be873b9c
commit 7b4e7bbe1d
No known key found for this signature in database
GPG Key ID: 46904C18B1D3F434
2 changed files with 36 additions and 19 deletions

View File

@ -7,6 +7,7 @@ import Route from "@ember/routing/route";
import RestModel from "discourse/models/rest";
import RestAdapter from "discourse/adapters/rest";
import Service from "@ember/service";
import deprecated from "discourse-common/lib/deprecated";
const disableImplicitInjectionsKey = Symbol("DISABLE_IMPLICIT_INJECTIONS");
@ -16,7 +17,7 @@ const disableImplicitInjectionsKey = Symbol("DISABLE_IMPLICIT_INJECTIONS");
* https://github.com/emberjs/ember.js/blob/22b318a381/packages/%40ember/-internals/metal/lib/injected_property.ts#L37
*
*/
function implicitInjectionShim(lookupName, key) {
function implicitInjectionShim(lookupName, key, deprecationLabel) {
let overrideKey = `__OVERRIDE_${key}`;
return computed(key, {
@ -28,6 +29,13 @@ function implicitInjectionShim(lookupName, key) {
return undefined;
}
if (deprecationLabel) {
deprecated(
`Implicit injection for ${key} on '${deprecationLabel}' type is deprecated. Add explicit '@service' injections to the class definition.`,
{ id: `discourse.implicit-injections.${deprecationLabel}` }
);
}
let owner = getOwner(this) || this.container;
if (!owner) {
return undefined;
@ -41,10 +49,10 @@ function implicitInjectionShim(lookupName, key) {
});
}
function setInjections(target, injections) {
function setInjections(target, injections, { deprecationLabel } = {}) {
const extension = {};
for (const [key, lookupName] of Object.entries(injections)) {
extension[key] = implicitInjectionShim(lookupName, key);
extension[key] = implicitInjectionShim(lookupName, key, deprecationLabel);
}
EmberObject.reopen.call(target, extension);
}
@ -105,14 +113,18 @@ export function registerDiscourseImplicitInjections() {
...commonInjections,
});
setInjections(Service, {
session: "service:session",
messageBus: "service:message-bus",
siteSettings: "service:site-settings",
topicTrackingState: "service:topic-tracking-state",
keyValueStore: "service:key-value-store",
currentUser: "service:current-user",
});
setInjections(
Service,
{
session: "service:session",
messageBus: "service:message-bus",
siteSettings: "service:site-settings",
topicTrackingState: "service:topic-tracking-state",
keyValueStore: "service:key-value-store",
currentUser: "service:current-user",
},
{ deprecationLabel: "service" }
);
alreadyRegistered = true;
}

View File

@ -3,16 +3,19 @@ import { test } from "qunit";
import RestModel from "discourse/models/rest";
import Service, { inject as service } from "@ember/service";
import { getOwner, setOwner } from "@ember/application";
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
acceptance("Implicit injections shims", function () {
test("it provides legacy injections on common models", function (assert) {
const serviceInstance = Service.create();
setOwner(serviceInstance, getOwner(this));
assert.strictEqual(
serviceInstance.session,
getOwner(this).lookup("service:session")
);
withSilencedDeprecations("discourse.implicit-injections.service", () => {
assert.strictEqual(
serviceInstance.session,
getOwner(this).lookup("service:session")
);
});
});
test("it allows overlaying explicit injections", function (assert) {
@ -22,10 +25,12 @@ acceptance("Implicit injections shims", function () {
const serviceInstance = MyService.create();
setOwner(serviceInstance, getOwner(this));
assert.strictEqual(
serviceInstance.session,
getOwner(this).lookup("service:session")
);
withSilencedDeprecations("discourse.implicit-injections.service", () => {
assert.strictEqual(
serviceInstance.session,
getOwner(this).lookup("service:session")
);
});
});
test("it allows overriding values by assignment", function (assert) {