diff --git a/app/assets/javascripts/discourse-common/addon/utils/handle-descriptor.js b/app/assets/javascripts/discourse-common/addon/utils/handle-descriptor.js index d871e454eb..f53354a413 100644 --- a/app/assets/javascripts/discourse-common/addon/utils/handle-descriptor.js +++ b/app/assets/javascripts/discourse-common/addon/utils/handle-descriptor.js @@ -1,37 +1,48 @@ -import { computed, get } from "@ember/object"; +import EmberObject, { computed, get } from "@ember/object"; import extractValue from "./extract-value"; export default function handleDescriptor(target, key, desc, params = []) { - return { - enumerable: desc.enumerable, - configurable: desc.configurable, - writeable: desc.writeable, - initializer() { - let computedDescriptor; + const val = extractValue(desc); - if (desc.writable) { - let val = extractValue(desc); - if (typeof val === "object") { - let value = {}; - if (val.get) { - value.get = callUserSuppliedGet(params, val.get); + if (typeof val === "function" && target instanceof EmberObject) { + // We're in a native class, so convert the method to a getter first + desc.writable = false; + desc.initializer = undefined; + desc.value = undefined; + desc.get = callUserSuppliedGet(params, val); + + return computed(target, key, desc); + } else { + return { + enumerable: desc.enumerable, + configurable: desc.configurable, + writable: desc.writable, + initializer() { + let computedDescriptor; + + if (desc.writable) { + if (typeof val === "object") { + let value = {}; + if (val.get) { + value.get = callUserSuppliedGet(params, val.get); + } + if (val.set) { + value.set = callUserSuppliedSet(params, val.set); + } + computedDescriptor = value; + } else { + computedDescriptor = callUserSuppliedGet(params, val); } - if (val.set) { - value.set = callUserSuppliedSet(params, val.set); - } - computedDescriptor = value; } else { - computedDescriptor = callUserSuppliedGet(params, val); + throw new Error( + "ember-computed-decorators does not support using getters and setters" + ); } - } else { - throw new Error( - "ember-computed-decorators does not support using getters and setters" - ); - } - return computed.apply(null, params.concat(computedDescriptor)); - }, - }; + return computed.apply(null, params.concat(computedDescriptor)); + }, + }; + } } function niceAttr(attr) { diff --git a/app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js b/app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js index c0b7c960ab..d9df7ce3e1 100644 --- a/app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js +++ b/app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js @@ -1,5 +1,7 @@ import Component from "@ember/component"; -import { afterRender } from "discourse-common/utils/decorators"; +import discourseComputed, { + afterRender, +} from "discourse-common/utils/decorators"; import componentTest, { setupRenderingTest, } from "discourse/tests/helpers/component-test"; @@ -29,7 +31,16 @@ const fooComponent = Component.extend({ }, }); -discourseModule("utils:decorators", function (hooks) { +class NativeComponent extends Component { + name = ""; + + @discourseComputed("name") + text(name) { + return `hello, ${name}`; + } +} + +discourseModule("Unit | Utils | decorators", function (hooks) { setupRenderingTest(hooks); componentTest("afterRender", { @@ -50,4 +61,26 @@ discourseModule("utils:decorators", function (hooks) { assert.strictEqual(this.baz, 1); }, }); + + componentTest("discourseComputed works in native classes", { + template: hbs``, + + beforeEach() { + Ember.TEMPLATES[ + "components/native-component" + ] = hbs`{{this.text}}`; + this.registry.register("component:native-component", NativeComponent); + }, + + afterEach() { + delete Ember.TEMPLATES["components/native-component"]; + }, + + test(assert) { + assert.strictEqual( + document.querySelector(".native-component").textContent, + "hello, Jarek" + ); + }, + }); });