DEV: Add native class shims for on/observes decorators

This commit is contained in:
David Taylor 2023-02-21 14:37:15 +00:00
parent 89c6296638
commit 8d2fa1c184
3 changed files with 113 additions and 6 deletions

View File

@ -1,5 +1,5 @@
import Controller, { inject as controller } from "@ember/controller";
import { observes } from "discourse-common/utils/decorators";
import { observes } from "@ember-decorators/object";
import I18n from "I18n";
import { bufferedProperty } from "discourse/mixins/buffered-content";
import { popupAjaxError } from "discourse/lib/ajax-error";

View File

@ -1,4 +1,9 @@
import { on as emberOn } from "@ember/object/evented";
import {
observes as emberObservesDecorator,
on as emberOnDecorator,
} from "@ember-decorators/object";
import { observer } from "@ember/object";
import {
alias as EmberAlias,
@ -37,6 +42,8 @@ import handleDescriptor from "discourse-common/utils/handle-descriptor";
import isDescriptor from "discourse-common/utils/is-descriptor";
import macroAlias from "discourse-common/utils/macro-alias";
import discourseDebounce from "discourse-common/lib/debounce";
import CoreObject from "@ember/object/core";
import deprecated from "discourse-common/lib/deprecated";
export default function discourseComputedDecorator(...params) {
// determine if user called as @discourseComputed('blah', 'blah') or @discourseComputed
@ -112,11 +119,39 @@ export function debounce(delay, immediate = false) {
};
}
export const on = decoratorAlias(emberOn, "Can not `on` without event names");
export const observes = decoratorAlias(
observer,
"Can not `observe` without property names"
);
export function on(...onParams) {
return function (target) {
if (target instanceof CoreObject) {
deprecated(
`Using 'on' from 'discourse-common/utils/decorators' as a class property decorator is deprecated. You should import it from '@ember-decorators/object' instead.`,
{ id: "discourse.utils-decorators-on", from: "3.1.0.beta2" }
);
return emberOnDecorator(...onParams)(...arguments);
} else {
return decoratorAlias(
emberOn,
"Can not `on` without event names"
)(...onParams)(...arguments);
}
};
}
export function observes(...observeParams) {
return function (target) {
if (target instanceof CoreObject) {
deprecated(
`Using 'observes' from 'discourse-common/utils/decorators' as a class property decorator is deprecated. You should import it from '@ember-decorators/object' instead.`,
{ id: "discourse.utils-decorators-observes", from: "3.1.0.beta2" }
);
return emberObservesDecorator(...observeParams)(...arguments);
} else {
return decoratorAlias(
observer,
"Can not `observe` without property names"
)(...observeParams)(...arguments);
}
};
}
export const alias = macroAlias(EmberAlias);
export const and = macroAlias(EmberAnd);

View File

@ -6,10 +6,12 @@ import discourseComputed, {
afterRender,
debounce,
observes,
on,
} from "discourse-common/utils/decorators";
import { exists } from "discourse/tests/helpers/qunit-helpers";
import { hbs } from "ember-cli-htmlbars";
import EmberObject from "@ember/object";
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
const fooComponent = Component.extend({
classNames: ["foo-component"],
@ -175,4 +177,74 @@ module("Unit | Utils | decorators", function (hooks) {
assert.strictEqual(stub.otherCounter, 1);
});
test("@observes works via .extend and native class syntax", async function (assert) {
let NativeClassWithObserver;
withSilencedDeprecations("discourse.utils-decorators-observes", () => {
NativeClassWithObserver = class extends EmberObject {
counter = 0;
@observes("value")
incrementCounter() {
this.set("counter", this.counter + 1);
}
};
});
const ExtendWithObserver = EmberObject.extend({
counter: 0,
@observes("value")
incrementCounter() {
this.set("counter", this.counter + 1);
},
});
const nativeClassTest = NativeClassWithObserver.create();
nativeClassTest.set("value", "one");
await settled();
nativeClassTest.set("value", "two");
await settled();
assert.strictEqual(
nativeClassTest.counter,
2,
"observer triggered for native class"
);
const extendTest = ExtendWithObserver.create();
extendTest.set("value", "one");
await settled();
extendTest.set("value", "two");
await settled();
assert.strictEqual(extendTest.counter, 2, "observer triggered for .extend");
});
test("@on works via .extend and native class syntax", async function (assert) {
let NativeClassWithOn;
withSilencedDeprecations("discourse.utils-decorators-on", () => {
NativeClassWithOn = class extends EmberObject {
counter = 0;
@on("init")
incrementCounter() {
this.set("counter", this.counter + 1);
}
};
});
const ExtendWithOn = EmberObject.extend({
counter: 0,
@on("init")
incrementCounter() {
this.set("counter", this.counter + 1);
},
});
const nativeClassTest = NativeClassWithOn.create();
assert.strictEqual(
nativeClassTest.counter,
1,
"on triggered for native class"
);
const extendTest = ExtendWithOn.create();
assert.strictEqual(extendTest.counter, 1, "on triggered for .extend");
});
});