From 7a8ab95eeeee95680974b2bdb04031b96e4ee7a4 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Wed, 26 May 2021 14:37:13 -0700 Subject: [PATCH] [BUGFIX release] Improve computed.* and run.* deprecation message Show details about outdated ember-cli-babel and only show the first instance by default. Example message: ``` Using `computed.reads` has been deprecated. Instead, import the value directly from @ember/object/computed: import { reads } from '@ember/object/computed'; These usages may be caused by an outdated ember-cli-babel dependency. The following steps may help: * Upgrade the following addons to the latest version: * active-model-adapter * ember-animated * ember-async-await-helper * ember-attacher * ember-cli-showdown * ember-md5 ### Important ### In order to avoid repeatedly showing the same deprecation messages, no further deprecation messages will be shown for theses deprecated usages until ember-cli-babel is upgraded to v7.26.6 or above. To see all instances of this deprecation message, set the `EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS` environment variable to "all", e.g. `EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS=all ember test`. ### Details ### Prior to v7.26.6, ember-cli-babel sometimes transpiled imports into the equivalent Ember Global API, potentially triggering this deprecation message indirectly, even when you did not observe these deprecated usages in your code. The following outdated versions are found in your project: * ember-cli-babel@6.11.0, currently used by: * ember-md5@6.11.0 * Depends on ember-cli-babel@6.11.0 * ember-cli-babel@6.18.0, currently used by: * active-model-adapter@6.18.0 * Depends on ember-cli-babel@^6.8.2 * ember-angle-bracket-invocation-polyfill@6.18.0 * Depends on ember-cli-babel@^6.17.0 * Added by ember-animated@0.11.0 * ember-async-await-helper@6.18.0 * Depends on ember-cli-babel@^6.16.0 * ember-cli-deploy-bugsnag@6.18.0 (Dormant) * Depends on ember-cli-babel@^6.16.0 * ember-cli-showdown@6.18.0 * Depends on ember-cli-babel@^6.8.1 * ember-inflector@6.18.0 * Depends on ember-cli-babel@^6.0.0 * Added by active-model-adapter@2.2.0 * ember-maybe-import-regenerator@6.18.0 (Dormant) * Depends on ember-cli-babel@^6.0.0-beta.4 * Added by ember-animated@0.11.0 * ember-named-arguments-polyfill@6.18.0 (Dormant) * Depends on ember-cli-babel@^6.6.0 * Added by ember-animated@0.11.0 * ember-raf-scheduler@6.18.0 * Depends on ember-cli-babel@^6.6.0 * Added by ember-attacher@1.2.3 > ember-popper@0.11.3 * ember-runtime-enumerable-includes-polyfill@6.18.0 (Dormant) * Depends on ember-cli-babel@^6.9.0 * Added by ember-freestyle@0.12.11 Note: Addons marked as "Dormant" does not appear to have any JavaScript files. Therefore, even if they are using an old version ember-cli-babel, they are unlikely to be the cuplrit of this deprecation and can likely be ignored. ``` --- lib/index.js | 153 +++++++++++++++++++++---------- packages/@ember/object/index.js | 32 ++++--- packages/@ember/runloop/index.js | 54 ++++++----- 3 files changed, 154 insertions(+), 85 deletions(-) diff --git a/lib/index.js b/lib/index.js index 580469b2275..6bb6a231626 100644 --- a/lib/index.js +++ b/lib/index.js @@ -415,101 +415,86 @@ module.exports = { } } - let message = - 'Usage of the Ember Global is deprecated. ' + - 'You should import the Ember module or the specific API instead.\n\n' + - 'See https://deprecations.emberjs.com/v3.x/#toc_ember-global for details.\n\n' + - 'Usages of the Ember Global may be caused by an outdated ember-cli-babel dependency. ' + - 'The following steps may help:\n\n'; + let suggestions = 'The following steps may help:\n\n'; - let hasActionableSteps = false; + let hasActionableSuggestions = false; if (projectInfo) { - message += '* Upgrade your `devDependencies` on `ember-cli-babel` to `^7.26.6`.\n'; - hasActionableSteps = true; + suggestions += '* Upgrade your `devDependencies` on `ember-cli-babel` to `^7.26.6`.\n'; + hasActionableSuggestions = true; } else if (compatibleTopLevelAddons.length > 0) { // Only show the compatible addons if the project itself is up-to-date, because updating the // project's own dependency on ember-cli-babel to latest may also get these addons to use it // as well. Otherwise, there is an unnecessary copy in the tree and it needs to be deduped. if (isYarnProject === true) { - message += + suggestions += '* Run `npx yarn-deduplicate --packages ember-cli-babel` followed by `yarn install`.\n'; } else if (isYarnProject === false) { - message += '* Run `npm dedupe`.\n'; + suggestions += '* Run `npm dedupe`.\n'; } else { - message += + suggestions += '* If using yarn, run `npx yarn-deduplicate --packages ember-cli-babel` followed by `yarn install`.\n' + '* If using npm, run `npm dedupe`.\n'; } - hasActionableSteps = true; + hasActionableSuggestions = true; } if (incompatibleTopLevelAddons.length > 0) { - message += '* Upgrade the following addons to the latest version:\n'; + suggestions += '* Upgrade the following addons to the latest version:\n'; for (let addon of incompatibleTopLevelAddons) { - message += ` * ${addon}\n`; + suggestions += ` * ${addon}\n`; } - hasActionableSteps = true; + hasActionableSuggestions = true; } - if (!hasActionableSteps) { + if (!hasActionableSuggestions) { // Only show the dormant addons if there are nothing else to do because they are unlikely to // be the problem. - message += '* Upgrade the following addons to the latest version, if available:\n'; + suggestions += '* Upgrade the following addons to the latest version, if available:\n'; for (let addon of dormantTopLevelAddons) { - message += ` * ${addon}\n`; + suggestions += ` * ${addon}\n`; } } - if (hasActionableSteps && process.env.EMBER_GLOBAL_DEPRECATIONS !== 'all') { - message += - '\n### Important ###\n\n' + - 'In order to avoid repeatedly showing the same deprecation messages, ' + - 'no further deprecation messages will be shown for usages of the Ember Global ' + - 'until ember-cli-babel is upgraded to v7.26.6 or above.\n\n' + - 'To see all instances of this deprecation message at runtime, ' + - 'set the `EMBER_GLOBAL_DEPRECATIONS` environment variable to "all", ' + - 'e.g. `EMBER_GLOBAL_DEPRECATIONS=all ember test`.\n'; - } - - message += + let details = '\n### Details ###\n\n' + 'Prior to v7.26.6, ember-cli-babel sometimes transpiled imports into the equivalent Ember Global API, ' + - 'potentially triggering this deprecation message even when you did not directly reference the Ember Global.\n\n' + + 'potentially triggering this deprecation message indirectly, ' + + 'even when you did not observe these deprecated usages in your code.\n\n' + 'The following outdated versions are found in your project:\n'; let hasDormantAddons = false; let hasCompatibleAddons = false; for (let version of Object.keys(groupedByVersion).sort(semver.compare)) { - message += `\n* ember-cli-babel@${version}, currently used by:\n`; + details += `\n* ember-cli-babel@${version}, currently used by:\n`; for (let parent of Object.keys(groupedByVersion[version]).sort()) { let info = groupedByVersion[version][parent][0]; - message += ` * ${parent}`; + details += ` * ${parent}`; if (info.dormant) { - message += ' (Dormant)\n'; + details += ' (Dormant)\n'; hasDormantAddons = true; } else if (info.compatible) { - message += ' (Compatible)\n'; + details += ' (Compatible)\n'; hasCompatibleAddons = true; } else { - message += '\n'; + details += '\n'; } - message += ` * Depends on ember-cli-babel@${groupedByVersion[version][parent][0].requirement}\n`; + details += ` * Depends on ember-cli-babel@${groupedByVersion[version][parent][0].requirement}\n`; for (let info of groupedByVersion[version][parent]) { let adddedBy = info.path.slice(0, -1); if (adddedBy.length) { - message += ` * Added by ${adddedBy.join(' > ')}\n`; + details += ` * Added by ${adddedBy.join(' > ')}\n`; } if (info.compatible) { @@ -520,40 +505,110 @@ module.exports = { } if (hasDormantAddons) { - message += + details += '\nNote: Addons marked as "Dormant" does not appear to have any JavaScript files. ' + 'Therefore, even if they are using an old version ember-cli-babel, they are ' + 'unlikely to be the cuplrit of this deprecation and can likely be ignored.\n'; } if (hasCompatibleAddons) { - message += `\nNote: Addons marked as "Compatible" are already compatible with ember-cli-babel@7.26.6. `; + details += `\nNote: Addons marked as "Compatible" are already compatible with ember-cli-babel@7.26.6. `; if (projectInfo) { - message += 'Try upgrading your `devDependencies` on `ember-cli-babel` to `^7.26.6`.\n'; + details += 'Try upgrading your `devDependencies` on `ember-cli-babel` to `^7.26.6`.\n'; } else { if (isYarnProject === true) { - message += + details += 'Try running `npx yarn-deduplicate --packages ember-cli-babel` followed by `yarn install`.\n'; } else if (isYarnProject === false) { - message += 'Try running `npm dedupe`.\n'; + details += 'Try running `npm dedupe`.\n'; } else { - message += + details += 'If using yarn, try running `npx yarn-deduplicate --packages ember-cli-babel` followed by `yarn install`.' + 'If using npm, try running `npm dedupe`.\n'; } } } - if (hasActionableSteps) { - this.ui.writeWarnLine('[DEPRECATION] ' + message); + let globalMessage = + 'Usage of the Ember Global is deprecated. ' + + 'You should import the Ember module or the specific API instead.\n\n' + + 'See https://deprecations.emberjs.com/v3.x/#toc_ember-global for details.\n\n' + + 'Usages of the Ember Global may be caused by an outdated ember-cli-babel dependency. ' + + suggestions; + + if (hasActionableSuggestions && process.env.EMBER_GLOBAL_DEPRECATIONS !== 'all') { + globalMessage += + '\n### Important ###\n\n' + + 'In order to avoid repeatedly showing the same deprecation messages, ' + + 'no further deprecation messages will be shown for usages of the Ember Global ' + + 'until ember-cli-babel is upgraded to v7.26.6 or above.\n\n' + + 'To see all instances of this deprecation message, ' + + 'set the `EMBER_GLOBAL_DEPRECATIONS` environment variable to "all", ' + + 'e.g. `EMBER_GLOBAL_DEPRECATIONS=all ember test`.\n'; + } + + globalMessage += details; + + if (hasActionableSuggestions) { + this.ui.writeWarnLine('[DEPRECATION] ' + globalMessage); } + let onDotAccess = `(dotKey, importKey, module) => { + let message = + \`Using \\\`\${dotKey}\\\` has been deprecated. Instead, import the value directly from \${module}:\\n\\n\` + + \` import { \${importKey} } from '\${module}';\\n\\n\` + + 'These usages may be caused by an outdated ember-cli-babel dependency. ' + + ${JSON.stringify(suggestions)}; + + if (${ + hasActionableSuggestions && + process.env.EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS !== 'all' + }) { + message += + '\\n### Important ###\\n\\n' + + 'In order to avoid repeatedly showing the same deprecation messages, ' + + 'no further deprecation messages will be shown for theses deprecated usages ' + + 'until ember-cli-babel is upgraded to v7.26.6 or above.\\n\\n' + + 'To see all instances of this deprecation message, ' + + 'set the \`EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS\` environment variable to "all", ' + + 'e.g. \`EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS=all ember test\`.\\n'; + } + + message += ${JSON.stringify(details)}; + + return message; + }`; + this._bootstrapEmber = ` require('@ember/-internals/bootstrap').default( - ${JSON.stringify(message)}, - ${hasActionableSteps && process.env.EMBER_GLOBAL_DEPRECATIONS !== 'all'} + ${JSON.stringify(globalMessage)}, + ${hasActionableSuggestions && process.env.EMBER_GLOBAL_DEPRECATIONS !== 'all'} ); + + { + let disabled = false; + + let once = ${ + hasActionableSuggestions && + process.env.EMBER_RUNLOOP_AND_COMPUTED_DOT_ACCESS_DEPRECATIONS !== 'all' + }; + + let _onDotAccess = ${onDotAccess}; + + let onDotAccess = (...args) => { + if (disabled) { + return null; + } else { + disabled = once; + return _onDotAccess(...args); + } + }; + + require('@ember/object')._onDotAccess(onDotAccess); + + require('@ember/runloop')._onDotAccess(onDotAccess); + } `; }, }; diff --git a/packages/@ember/object/index.js b/packages/@ember/object/index.js index f2fe18b27f9..af4dd9d5735 100644 --- a/packages/@ember/object/index.js +++ b/packages/@ember/object/index.js @@ -55,23 +55,31 @@ import { uniq, } from '@ember/object/computed'; +export let _onDotAccess; + // eslint-disable-next-line no-undef if (DEBUG) { + let _callback = (dotKey, importKey, module) => { + return `Using \`${dotKey}\` has been deprecated. Instead, import the value directly from ${module}:\n\n import { ${importKey} } from '${module}';`; + }; + + _onDotAccess = (callback) => { + _callback = callback; + }; + let defineDeprecatedComputedFunc = (key, func) => { Object.defineProperty(computed, key, { get() { - deprecate( - `Using \`computed.${key}\` has been deprecated. Instead, import the value directly from @ember/object/computed:\n\n import { ${key} } from '@ember/object/computed';`, - false, - { - id: 'deprecated-run-loop-and-computed-dot-access', - until: '4.0.0', - for: 'ember-source', - since: { - enabled: '3.27.0', - }, - } - ); + let message = _callback(`computed.${key}`, key, '@ember/object/computed'); + + deprecate(message, message === null, { + id: 'deprecated-run-loop-and-computed-dot-access', + until: '4.0.0', + for: 'ember-source', + since: { + enabled: '3.27.0', + }, + }); return func; }, diff --git a/packages/@ember/runloop/index.js b/packages/@ember/runloop/index.js index d3ae2d1e780..6ce847c96db 100644 --- a/packages/@ember/runloop/index.js +++ b/packages/@ember/runloop/index.js @@ -743,23 +743,31 @@ export function throttle() { export let _deprecatedGlobalGetCurrentRunLoop; +export let _onDotAccess; + // eslint-disable-next-line no-undef if (DEBUG) { + let _callback = (dotKey, importKey, module) => { + return `Using \`${dotKey}\` has been deprecated. Instead, import the value directly from ${module}:\n\n import { ${importKey} } from '${module}';`; + }; + + _onDotAccess = (callback) => { + _callback = callback; + }; + let defineDeprecatedRunloopFunc = (key, func) => { Object.defineProperty(run, key, { get() { - deprecate( - `Using \`run.${key}\` has been deprecated. Instead, import the value directly from @ember/runloop:\n\n import { ${key} } from '@ember/runloop';`, - false, - { - id: 'deprecated-run-loop-and-computed-dot-access', - until: '4.0.0', - for: 'ember-source', - since: { - enabled: '3.27.0', - }, - } - ); + let message = _callback(`run.${key}`, key, '@ember/runloop'); + + deprecate(message, message === null, { + id: 'deprecated-run-loop-and-computed-dot-access', + until: '4.0.0', + for: 'ember-source', + since: { + enabled: '3.27.0', + }, + }); return func; }, @@ -767,18 +775,16 @@ if (DEBUG) { }; _deprecatedGlobalGetCurrentRunLoop = () => { - deprecate( - `Using \`run.currentRunLoop\` has been deprecated. Instead, import the getCurrentRunLoop() directly from @ember/runloop:\n\n import { getCurrentRunLoop } from '@ember/runloop';`, - false, - { - id: 'deprecated-run-loop-and-computed-dot-access', - until: '4.0.0', - for: 'ember-source', - since: { - enabled: '3.27.0', - }, - } - ); + let message = _callback('run.currentRunLoop', 'getCurrentRunLoop', '@ember/runloop'); + + deprecate(message, message === null, { + id: 'deprecated-run-loop-and-computed-dot-access', + until: '4.0.0', + for: 'ember-source', + since: { + enabled: '3.27.0', + }, + }); return _getCurrentRunLoop(); };