diff --git a/packages/@ember/-internals/glimmer/lib/component.ts b/packages/@ember/-internals/glimmer/lib/component.ts index 5820c596b19..abe9d409e95 100644 --- a/packages/@ember/-internals/glimmer/lib/component.ts +++ b/packages/@ember/-internals/glimmer/lib/component.ts @@ -752,6 +752,10 @@ const Component = CoreView.extend( id: 'ember-views.event-dispatcher.mouseenter-leave-move', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_component-mouseenter-leave-move', + for: 'ember-source', + since: { + enabled: '3.13.0-beta.1', + }, } ); deprecate( @@ -761,6 +765,10 @@ const Component = CoreView.extend( id: 'ember-views.event-dispatcher.mouseenter-leave-move', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_component-mouseenter-leave-move', + for: 'ember-source', + since: { + enabled: '3.13.0-beta.1', + }, } ); deprecate( @@ -770,6 +778,10 @@ const Component = CoreView.extend( id: 'ember-views.event-dispatcher.mouseenter-leave-move', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_component-mouseenter-leave-move', + for: 'ember-source', + since: { + enabled: '3.13.0-beta.1', + }, } ); }, diff --git a/packages/@ember/-internals/glimmer/lib/environment.ts b/packages/@ember/-internals/glimmer/lib/environment.ts index d8ab17bb29a..c58bf049f4b 100644 --- a/packages/@ember/-internals/glimmer/lib/environment.ts +++ b/packages/@ember/-internals/glimmer/lib/environment.ts @@ -64,6 +64,10 @@ if (DEBUG) { deprecate(message, false, { id: 'autotracking.mutation-after-consumption', until: '4.0.0', + for: 'ember-source', + since: { + enabled: '3.21.0', + }, }); }, diff --git a/packages/@ember/-internals/glimmer/lib/helpers/action.ts b/packages/@ember/-internals/glimmer/lib/helpers/action.ts index dd52fda0351..5f7aa791e94 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/action.ts @@ -415,6 +415,10 @@ function makeClosureAction( { until: '3.25.0', id: 'actions.custom-invoke-invokable', + for: 'ember-source', + since: { + enabled: '3.23.0-beta.1', + }, } ); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index 571b4f94033..f59edfaf140 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -156,6 +156,10 @@ export class ActionState { { until: '3.25.0', id: 'actions.custom-invoke-invokable', + for: 'ember-source', + since: { + enabled: '3.23.0-beta.1', + }, } ); @@ -226,6 +230,10 @@ export default class ActionModifierManager implements ModifierManager>; } export type DeprecateFunc = (message: string, test?: boolean, options?: DeprecationOptions) => void; +export type MissingOptionDeprecateFunc = (id: string) => string; /** @module @ember/debug @@ -64,7 +69,11 @@ let registerHandler: (handler: HandlerCallback) => void = () => {}; let missingOptionsDeprecation: string; let missingOptionsIdDeprecation: string; let missingOptionsUntilDeprecation: string; +let missingOptionsForDeprecation: MissingOptionDeprecateFunc = () => ''; +let missingOptionsSinceDeprecation: MissingOptionDeprecateFunc = () => ''; let deprecate: DeprecateFunc = () => {}; +let FOR_MISSING_DEPRECATIONS = new Set(); +let SINCE_MISSING_DEPRECATIONS = new Set(); if (DEBUG) { registerHandler = function registerHandler(handler: HandlerCallback) { @@ -154,6 +163,13 @@ if (DEBUG) { '`options` should include `id` and `until` properties.'; missingOptionsIdDeprecation = 'When calling `deprecate` you must provide `id` in options.'; missingOptionsUntilDeprecation = 'When calling `deprecate` you must provide `until` in options.'; + + missingOptionsForDeprecation = (id: string) => { + return `When calling \`deprecate\` you must provide \`for\` in options. Missing options.for in "${id}" deprecation`; + }; + missingOptionsSinceDeprecation = (id: string) => { + return `When calling \`deprecate\` you must provide \`since\` in options. Missing options.since in "${id}" deprecation`; + }; /** @module @ember/debug @public @@ -176,8 +192,10 @@ if (DEBUG) { "view.helper.select". @param {string} options.until The version of Ember when this deprecation warning will be removed. + @param {String} options.for A namespace for the deprecation, usually the package name + @param {Object} options.since Describes when the deprecation became available and enabled. @param {String} [options.url] An optional url to the transition guide on the - emberjs.com website. + emberjs.com website. @static @public @since 1.0.0 @@ -187,6 +205,32 @@ if (DEBUG) { assert(missingOptionsIdDeprecation, Boolean(options!.id)); assert(missingOptionsUntilDeprecation, Boolean(options!.until)); + if (!options!.for && !FOR_MISSING_DEPRECATIONS.has(options!.id)) { + FOR_MISSING_DEPRECATIONS.add(options!.id); + + deprecate(missingOptionsForDeprecation(options!.id), Boolean(options!.for), { + id: 'ember-source.deprecation-without-for', + until: '4.0.0', + for: 'ember-source', + since: { + available: '3.24.0', + }, + }); + } + + if (!options!.since && !SINCE_MISSING_DEPRECATIONS.has(options!.id)) { + SINCE_MISSING_DEPRECATIONS.add(options!.id); + + deprecate(missingOptionsSinceDeprecation(options!.id), Boolean(options!.since), { + id: 'ember-source.deprecation-without-since', + until: '4.0.0', + for: 'ember-source', + since: { + available: '3.24.0', + }, + }); + } + invoke('deprecate', message, test, options); }; } @@ -198,4 +242,8 @@ export { missingOptionsDeprecation, missingOptionsIdDeprecation, missingOptionsUntilDeprecation, + missingOptionsForDeprecation, + missingOptionsSinceDeprecation, + FOR_MISSING_DEPRECATIONS, + SINCE_MISSING_DEPRECATIONS, }; diff --git a/packages/@ember/debug/tests/main_test.js b/packages/@ember/debug/tests/main_test.js index 0d5d401dd98..42213281502 100644 --- a/packages/@ember/debug/tests/main_test.js +++ b/packages/@ember/debug/tests/main_test.js @@ -6,6 +6,10 @@ import { missingOptionsDeprecation, missingOptionsIdDeprecation, missingOptionsUntilDeprecation, + missingOptionsForDeprecation, + missingOptionsSinceDeprecation, + FOR_MISSING_DEPRECATIONS, + SINCE_MISSING_DEPRECATIONS, } from '../lib/deprecate'; import { @@ -41,7 +45,8 @@ moduleFor( teardown() { HANDLERS.deprecate = originalDeprecateHandler; HANDLERS.warn = originalWarnHandler; - + FOR_MISSING_DEPRECATIONS.clear(); + SINCE_MISSING_DEPRECATIONS.clear(); ENV.RAISE_ON_DEPRECATION = originalEnvValue; } @@ -56,7 +61,12 @@ moduleFor( ENV.RAISE_ON_DEPRECATION = false; try { - deprecate('Should not throw', false, { id: 'test', until: 'forever' }); + deprecate('Should not throw', false, { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }); assert.ok(true, 'deprecate did not throw'); } catch (e) { assert.ok(false, `Expected deprecate not to throw but it did: ${e.message}`); @@ -72,7 +82,12 @@ moduleFor( ENV.RAISE_ON_DEPRECATION = false; try { - deprecate('Should not throw', false, { id: 'test', until: 'forever' }); + deprecate('Should not throw', false, { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }); assert.ok(true, 'deprecate did not throw'); } catch (e) { assert.ok(false, `Expected deprecate not to throw but it did: ${e.message}`); @@ -81,7 +96,12 @@ moduleFor( ENV.RAISE_ON_DEPRECATION = true; assert.throws(() => { - deprecate('Should throw', false, { id: 'test', until: 'forever' }); + deprecate('Should throw', false, { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }); }, /Should throw/); } @@ -101,6 +121,8 @@ moduleFor( deprecate('should be silenced with matching id', false, { id: 'my-deprecation', until: 'forever', + for: 'me', + since: { available: '1.0.0' }, }); assert.ok(true, 'Did not throw when level is set by id'); } catch (e) { @@ -111,6 +133,8 @@ moduleFor( deprecate('Should throw with no matching id', false, { id: 'test', until: 'forever', + for: 'me', + since: { available: '1.0.0' }, }); }, /Should throw with no matching id/); @@ -118,6 +142,8 @@ moduleFor( deprecate('Should throw with non-matching id', false, { id: 'other-id', until: 'forever', + for: 'me', + since: { available: '1.0.0' }, }); }, /Should throw with non-matching id/); } @@ -129,10 +155,26 @@ moduleFor( deprecate('Deprecation is thrown', false, { id: 'test', until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }) + ); + assert.throws(() => + deprecate('Deprecation is thrown', '', { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }) + ); + assert.throws(() => + deprecate('Deprecation is thrown', 0, { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, }) ); - assert.throws(() => deprecate('Deprecation is thrown', '', { id: 'test', until: 'forever' })); - assert.throws(() => deprecate('Deprecation is thrown', 0, { id: 'test', until: 'forever' })); } ['@test deprecate does not invoke a function as the second argument'](assert) { @@ -143,7 +185,7 @@ moduleFor( function () { assert.ok(false, 'this function should not be invoked'); }, - { id: 'test', until: 'forever' } + { id: 'test', until: 'forever', for: 'me', since: { available: '1.0.0' } } ); assert.ok(true, 'deprecations were not thrown'); @@ -155,9 +197,21 @@ moduleFor( deprecate('Deprecation is thrown', true, { id: 'test', until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }); + deprecate('Deprecation is thrown', '1', { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, + }); + deprecate('Deprecation is thrown', 1, { + id: 'test', + until: 'forever', + for: 'me', + since: { available: '1.0.0' }, }); - deprecate('Deprecation is thrown', '1', { id: 'test', until: 'forever' }); - deprecate('Deprecation is thrown', 1, { id: 'test', until: 'forever' }); assert.ok(true, 'deprecations were not thrown'); } @@ -257,7 +311,8 @@ moduleFor( assert.expect(1); assert.throws( - () => deprecate('foo', false, { until: 'forever' }), + () => + deprecate('foo', false, { until: 'forever', for: 'me', since: { available: '1.0.0' } }), new RegExp(missingOptionsIdDeprecation), 'proper assertion is triggered when options.id is missing' ); @@ -273,6 +328,77 @@ moduleFor( ); } + ['@test deprecate without options.for triggers an assertion'](assert) { + assert.expect(1); + + assert.throws( + () => deprecate('message1', false, { id: 'test', until: 'forever' }), + new RegExp(missingOptionsForDeprecation('test')), + 'proper assertion is triggered when options.for is missing' + ); + } + + ['@test deprecate without options.for only triggers once per id'](assert) { + ENV.RAISE_ON_DEPRECATION = false; + let messages = []; + registerHandler(function (message, options, next) { + if (options.id === 'ember-source.deprecation-without-for') { + messages.push(message); + } + next(...arguments); + }); + + deprecate('message1', false, { id: 'test', until: 'forever' }); + deprecate('message2', false, { id: 'test', until: 'forever' }); + deprecate('message3', false, { id: 'another', until: 'forever' }); + + assert.equal(messages.length, 2, 'correct number of deprecations'); + assert.equal(messages[0], missingOptionsForDeprecation('test'), 'first message is correct'); + + assert.equal( + messages[1], + missingOptionsForDeprecation('another'), + 'second message is correct' + ); + } + + ['@test deprecate without options.since triggers an assertion'](assert) { + assert.expect(1); + + assert.throws( + () => + deprecate('foo', false, { + id: 'test', + until: 'forever', + for: 'me', + }), + new RegExp(missingOptionsSinceDeprecation('test')), + 'proper assertion is triggered when options.since is missing' + ); + } + + ['@test deprecate without options.since only triggers once per id'](assert) { + ENV.RAISE_ON_DEPRECATION = false; + let messages = []; + registerHandler(function (message, options, next) { + if (options.id === 'ember-source.deprecation-without-since') { + messages.push(message); + } + next(...arguments); + }); + deprecate('foo', false, { id: 'test', until: 'forever', for: 'me' }); + deprecate('foobar', false, { id: 'test', until: 'forever', for: 'me' }); + deprecate('baz', false, { id: 'another', until: 'forever', for: 'me' }); + + assert.equal(messages.length, 2, 'deprecation message only sent once'); + assert.equal(messages[0], missingOptionsSinceDeprecation('test'), 'first message is correct'); + assert.equal( + messages[1], + missingOptionsSinceDeprecation('another'), + 'second message is correct' + ); + } + ['@test warn without options triggers an assert'](assert) { assert.expect(1); diff --git a/packages/@ember/polyfills/lib/merge.ts b/packages/@ember/polyfills/lib/merge.ts index 95dacb7cb7d..3e7bf2c08d7 100644 --- a/packages/@ember/polyfills/lib/merge.ts +++ b/packages/@ember/polyfills/lib/merge.ts @@ -32,6 +32,10 @@ function merge(original: object, updates: object) { id: 'ember-polyfills.deprecate-merge', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x/#toc_ember-polyfills-deprecate-merge', + for: 'ember-source', + since: { + enabled: '3.6.0-beta.1', + }, }); if (updates === null || typeof updates !== 'object') { diff --git a/packages/ember-template-compiler/lib/plugins/deprecate-send-action.ts b/packages/ember-template-compiler/lib/plugins/deprecate-send-action.ts index 5931fee8327..2b119ec4a55 100644 --- a/packages/ember-template-compiler/lib/plugins/deprecate-send-action.ts +++ b/packages/ember-template-compiler/lib/plugins/deprecate-send-action.ts @@ -49,6 +49,10 @@ export default function deprecateSendAction(env: EmberASTPluginEnvironment): AST id: 'ember-component.send-action', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_ember-component-send-action', + for: 'ember-source', + since: { + enabled: '3.4.0', + }, }); } else if ( value.type === 'MustacheStatement' && @@ -58,6 +62,10 @@ export default function deprecateSendAction(env: EmberASTPluginEnvironment): AST id: 'ember-component.send-action', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_ember-component-send-action', + for: 'ember-source', + since: { + enabled: '3.4.0', + }, }); } } @@ -76,6 +84,10 @@ export default function deprecateSendAction(env: EmberASTPluginEnvironment): AST id: 'ember-component.send-action', until: '4.0.0', url: 'https://emberjs.com/deprecations/v3.x#toc_ember-component-send-action', + for: 'ember-source', + since: { + enabled: '3.4.0', + }, }); } }); diff --git a/packages/ember-template-compiler/lib/plugins/transform-in-element.ts b/packages/ember-template-compiler/lib/plugins/transform-in-element.ts index abb6122223d..2b663493079 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-in-element.ts +++ b/packages/ember-template-compiler/lib/plugins/transform-in-element.ts @@ -86,6 +86,10 @@ export default function transformInElement(env: EmberASTPluginEnvironment): ASTP { id: 'glimmer.private-in-element', until: '3.25.0', + for: 'ember-source', + since: { + enabled: '3.20.0', + }, } ); }