Revert "DEV: Improve discourse-common/deprecate implementation (#18987)"
This reverts commit 8c48285145
. This introduced a bug which could cause sites to break when certain deprecations are hit. We'll re-introduce a fixed version of this change in a future commit.
This commit is contained in:
parent
ad4df89093
commit
47035693b7
|
@ -1,40 +1,14 @@
|
||||||
const handlers = [];
|
export default function deprecated(msg, opts = {}) {
|
||||||
const disabledDeprecations = new Set();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a deprecation warning with the provided message. The warning will be prefixed with the theme/plugin name
|
|
||||||
* if it can be automatically determined based on the current stack.
|
|
||||||
* @param {String} msg The deprecation message
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {String} [options.id] A unique identifier for this deprecation. This should be namespaced by dots (e.g. discourse.my_deprecation)
|
|
||||||
* @param {String} [options.since] The Discourse version this deprecation was introduced in
|
|
||||||
* @param {String} [options.dropFrom] The Discourse version this deprecation will be dropped in. Typically one major version after `since`
|
|
||||||
* @param {String} [options.url] A URL which provides more detail about the deprecation
|
|
||||||
* @param {boolean} [options.raiseError] Raise an error when this deprecation is triggered. Defaults to `false`
|
|
||||||
*/
|
|
||||||
export default function deprecated(msg, options) {
|
|
||||||
const { id, since, dropFrom, url, raiseError } = options;
|
|
||||||
|
|
||||||
if (id && disabledDeprecations.has(id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = ["Deprecation notice:", msg];
|
msg = ["Deprecation notice:", msg];
|
||||||
if (since) {
|
if (opts.since) {
|
||||||
msg.push(`[deprecated since Discourse ${since}]`);
|
msg.push(`(deprecated since Discourse ${opts.since})`);
|
||||||
}
|
}
|
||||||
if (dropFrom) {
|
if (opts.dropFrom) {
|
||||||
msg.push(`[removal in Discourse ${dropFrom}]`);
|
msg.push(`(removal in Discourse ${opts.dropFrom})`);
|
||||||
}
|
|
||||||
if (id) {
|
|
||||||
msg.push(`[deprecation id: ${id}]`);
|
|
||||||
}
|
|
||||||
if (url) {
|
|
||||||
msg.push(`[info: ${url}]`);
|
|
||||||
}
|
}
|
||||||
msg = msg.join(" ");
|
msg = msg.join(" ");
|
||||||
|
|
||||||
if (raiseError) {
|
if (opts.raiseError) {
|
||||||
throw msg;
|
throw msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,29 +20,4 @@ export default function deprecated(msg, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn(consolePrefix, msg); //eslint-disable-line no-console
|
console.warn(consolePrefix, msg); //eslint-disable-line no-console
|
||||||
|
|
||||||
handlers.forEach((h) => h(msg, options));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a function which will be called whenever a deprecation is triggered
|
|
||||||
* @param {function} callback The callback function. Arguments will match those of `deprecated()`.
|
|
||||||
*/
|
|
||||||
export function registerDeprecationHandler(callback) {
|
|
||||||
handlers.push(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Silence one or more deprecations while running `callback`
|
|
||||||
* @async
|
|
||||||
* @param {(string|string[])} deprecationIds A single id, or an array of ids, of deprecations to silence
|
|
||||||
* @param {function} callback The function to call while deprecations are silenced. Can be asynchronous.
|
|
||||||
*/
|
|
||||||
export async function withSilencedDeprecations(deprecationIds, callback) {
|
|
||||||
try {
|
|
||||||
Array(deprecationIds).forEach((id) => disabledDeprecations.add(id));
|
|
||||||
return await callback();
|
|
||||||
} finally {
|
|
||||||
Array(deprecationIds).forEach((id) => disabledDeprecations.delete(id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ export default TextField.extend({
|
||||||
@on("init")
|
@on("init")
|
||||||
deprecateComponent() {
|
deprecateComponent() {
|
||||||
deprecated(
|
deprecated(
|
||||||
"The `<UserSelector>` component is deprecated. Please use `<EmailGroupUserChooser>` instead.",
|
"`{{user-selector}}` is deprecated. Please use `{{email-group-user-chooser}}` instead.",
|
||||||
{ since: "2.7", dropFrom: "2.8", id: "discourse.user-selector-component" }
|
{ since: "2.7", dropFrom: "2.8" }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
const TapReporter = require("testem/lib/reporters/tap_reporter");
|
const TapReporter = require("testem/lib/reporters/tap_reporter");
|
||||||
const { shouldLoadPluginTestJs } = require("discourse/lib/plugin-js");
|
const { shouldLoadPluginTestJs } = require("discourse/lib/plugin-js");
|
||||||
const fs = require("fs");
|
|
||||||
|
|
||||||
class Reporter {
|
class Reporter {
|
||||||
failReports = [];
|
failReports = [];
|
||||||
deprecationCounts = new Map();
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._tapReporter = new TapReporter(...arguments);
|
this._tapReporter = new TapReporter(...arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
reportMetadata(tag, metadata) {
|
reportMetadata(tag, metadata) {
|
||||||
if (tag === "increment-deprecation") {
|
if (tag === "summary-line") {
|
||||||
const id = metadata.id;
|
|
||||||
const currentCount = this.deprecationCounts.get(id) || 0;
|
|
||||||
this.deprecationCounts.set(id, currentCount + 1);
|
|
||||||
} else if (tag === "summary-line") {
|
|
||||||
process.stdout.write(`\n${metadata.message}\n`);
|
process.stdout.write(`\n${metadata.message}\n`);
|
||||||
} else {
|
} else {
|
||||||
this._tapReporter.reportMetadata(...arguments);
|
this._tapReporter.reportMetadata(...arguments);
|
||||||
|
@ -29,46 +23,9 @@ class Reporter {
|
||||||
this._tapReporter.report(prefix, data);
|
this._tapReporter.report(prefix, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateDeprecationTable() {
|
|
||||||
const maxIdLength = Math.max(
|
|
||||||
...Array.from(this.deprecationCounts.keys()).map((k) => k.length)
|
|
||||||
);
|
|
||||||
|
|
||||||
let msg = `| ${"id".padEnd(maxIdLength)} | count |\n`;
|
|
||||||
msg += `| ${"".padEnd(maxIdLength, "-")} | ----- |\n`;
|
|
||||||
|
|
||||||
for (const [id, count] of this.deprecationCounts.entries()) {
|
|
||||||
const countString = count.toString();
|
|
||||||
msg += `| ${id.padEnd(maxIdLength)} | ${countString.padStart(5)} |\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
reportDeprecations() {
|
|
||||||
let deprecationMessage = "[Deprecation Counter] ";
|
|
||||||
if (this.deprecationCounts.size > 0) {
|
|
||||||
const table = this.generateDeprecationTable();
|
|
||||||
deprecationMessage += `Test run completed with deprecations:\n\n${table}`;
|
|
||||||
|
|
||||||
if (process.env.GITHUB_ACTIONS && process.env.GITHUB_STEP_SUMMARY) {
|
|
||||||
let jobSummary = `### ⚠️ JS Deprecations\n\nTest run completed with deprecations:\n\n`;
|
|
||||||
jobSummary += table;
|
|
||||||
jobSummary += `\n\n`;
|
|
||||||
|
|
||||||
fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, jobSummary);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deprecationMessage += "No deprecations logged";
|
|
||||||
}
|
|
||||||
process.stdout.write(`\n${deprecationMessage}\n\n`);
|
|
||||||
}
|
|
||||||
|
|
||||||
finish() {
|
finish() {
|
||||||
this._tapReporter.finish();
|
this._tapReporter.finish();
|
||||||
|
|
||||||
this.reportDeprecations();
|
|
||||||
|
|
||||||
if (this.failReports.length > 0) {
|
if (this.failReports.length > 0) {
|
||||||
process.stdout.write("\nFailures:\n\n");
|
process.stdout.write("\nFailures:\n\n");
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
import { registerDeprecationHandler } from "@ember/debug";
|
|
||||||
import { bind } from "discourse-common/utils/decorators";
|
|
||||||
import { registerDeprecationHandler as registerDiscourseDeprecationHandler } from "discourse-common/lib/deprecated";
|
|
||||||
|
|
||||||
export default class DeprecationCounter {
|
|
||||||
counts = new Map();
|
|
||||||
#configById = new Map();
|
|
||||||
|
|
||||||
constructor(config) {
|
|
||||||
for (const c of config) {
|
|
||||||
this.#configById.set(c.matchId, c.handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
registerDeprecationHandler(this.handleEmberDeprecation);
|
|
||||||
registerDiscourseDeprecationHandler(this.handleDiscourseDeprecation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@bind
|
|
||||||
handleEmberDeprecation(message, options, next) {
|
|
||||||
const { id } = options;
|
|
||||||
const matchingConfig = this.#configById.get(id);
|
|
||||||
|
|
||||||
if (matchingConfig !== "silence") {
|
|
||||||
this.incrementDeprecation(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
next(message, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@bind
|
|
||||||
handleDiscourseDeprecation(message, options) {
|
|
||||||
let { id } = options;
|
|
||||||
id ||= "discourse.(unknown)";
|
|
||||||
|
|
||||||
this.incrementDeprecation(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
incrementDeprecation(id) {
|
|
||||||
const existingCount = this.counts.get(id) || 0;
|
|
||||||
this.counts.set(id, existingCount + 1);
|
|
||||||
if (window.Testem) {
|
|
||||||
reportToTestem(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasDeprecations() {
|
|
||||||
return this.counts.size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
generateTable() {
|
|
||||||
const maxIdLength = Math.max(
|
|
||||||
...Array.from(this.counts.keys()).map((k) => k.length)
|
|
||||||
);
|
|
||||||
|
|
||||||
let msg = `| ${"id".padEnd(maxIdLength)} | count |\n`;
|
|
||||||
msg += `| ${"".padEnd(maxIdLength, "-")} | ----- |\n`;
|
|
||||||
|
|
||||||
for (const [id, count] of this.counts.entries()) {
|
|
||||||
const countString = count.toString();
|
|
||||||
msg += `| ${id.padEnd(maxIdLength)} | ${countString.padStart(5)} |\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function reportToTestem(id) {
|
|
||||||
window.Testem.useCustomAdapter(function (socket) {
|
|
||||||
socket.emit("test-metadata", "increment-deprecation", {
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setupDeprecationCounter(qunit) {
|
|
||||||
const config = window.deprecationWorkflow?.config?.workflow || {};
|
|
||||||
const deprecationCounter = new DeprecationCounter(config);
|
|
||||||
|
|
||||||
qunit.begin(() => deprecationCounter.start());
|
|
||||||
|
|
||||||
qunit.done(() => {
|
|
||||||
if (window.Testem) {
|
|
||||||
return;
|
|
||||||
} else if (deprecationCounter.hasDeprecations) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.warn(
|
|
||||||
`[Discourse Deprecation Counter] Test run completed with deprecations:\n\n${deprecationCounter.generateTable()}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log("[Discourse Deprecation Counter] No deprecations found");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
|
|
||||||
|
|
||||||
function paste(element, text) {
|
function paste(element, text) {
|
||||||
let e = new Event("paste");
|
let e = new Event("paste");
|
||||||
|
@ -17,14 +16,9 @@ module("Integration | Component | user-selector", function (hooks) {
|
||||||
test("pasting a list of usernames", async function (assert) {
|
test("pasting a list of usernames", async function (assert) {
|
||||||
this.set("usernames", "evil,trout");
|
this.set("usernames", "evil,trout");
|
||||||
|
|
||||||
await withSilencedDeprecations(
|
|
||||||
"discourse.user-selector-component",
|
|
||||||
async () => {
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<UserSelector @usernames={{this.usernames}} class="test-selector" />`
|
hbs`<UserSelector @usernames={{this.usernames}} class="test-selector" />`
|
||||||
);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let element = query(".test-selector");
|
let element = query(".test-selector");
|
||||||
|
|
||||||
|
@ -51,14 +45,9 @@ module("Integration | Component | user-selector", function (hooks) {
|
||||||
this.set("usernames", "mark");
|
this.set("usernames", "mark");
|
||||||
this.set("excludedUsernames", ["jeff", "sam", "robin"]);
|
this.set("excludedUsernames", ["jeff", "sam", "robin"]);
|
||||||
|
|
||||||
await withSilencedDeprecations(
|
|
||||||
"discourse.user-selector-component",
|
|
||||||
async () => {
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<UserSelector @usernames={{this.usernames}} @excludedUsernames={{this.excludedUsernames}} class="test-selector" />`
|
hbs`<UserSelector @usernames={{this.usernames}} @excludedUsernames={{this.excludedUsernames}} class="test-selector" />`
|
||||||
);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let element = query(".test-selector");
|
let element = query(".test-selector");
|
||||||
paste(element, "roman,penar,jeff,robin");
|
paste(element, "roman,penar,jeff,robin");
|
||||||
|
|
|
@ -40,7 +40,6 @@ import { clearState as clearPresenceState } from "discourse/tests/helpers/presen
|
||||||
import { addModuleExcludeMatcher } from "ember-cli-test-loader/test-support/index";
|
import { addModuleExcludeMatcher } from "ember-cli-test-loader/test-support/index";
|
||||||
import SiteSettingService from "discourse/services/site-settings";
|
import SiteSettingService from "discourse/services/site-settings";
|
||||||
import jQuery from "jquery";
|
import jQuery from "jquery";
|
||||||
import { setupDeprecationCounter } from "discourse/tests/helpers/deprecation-counter";
|
|
||||||
|
|
||||||
const Plugin = $.fn.modal;
|
const Plugin = $.fn.modal;
|
||||||
const Modal = Plugin.Constructor;
|
const Modal = Plugin.Constructor;
|
||||||
|
@ -200,8 +199,6 @@ function writeSummaryLine(message) {
|
||||||
export default function setupTests(config) {
|
export default function setupTests(config) {
|
||||||
disableCloaking();
|
disableCloaking();
|
||||||
|
|
||||||
setupDeprecationCounter(QUnit);
|
|
||||||
|
|
||||||
QUnit.config.hidepassed = true;
|
QUnit.config.hidepassed = true;
|
||||||
|
|
||||||
sinon.config = {
|
sinon.config = {
|
||||||
|
|
Loading…
Reference in New Issue