From bf750e7f0862bc42b25040773be7ed6cdc47ccce Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Tue, 16 Mar 2021 17:55:08 -0700 Subject: [PATCH] [BUGFIX] Restore nested paths on run and computed These values were previously nested on `run` and `computed`, and were accessible from the _imported_ versions of those values due to the fact that they transformed to be the same as globals. They were used by a few different consumers, but were not intended to be used this way. This PR restores the previous behavior, but also deprecates it. --- packages/@ember/-internals/metal/index.ts | 8 +- .../@ember/-internals/metal/lib/computed.ts | 2 - packages/@ember/object/index.js | 129 +++++++++++++++++- packages/@ember/runloop/index.js | 66 ++++++++- packages/ember/index.js | 96 +------------ packages/ember/tests/reexports_test.js | 116 ++++++++-------- .../lib/confirm-export.js | 6 +- 7 files changed, 260 insertions(+), 163 deletions(-) diff --git a/packages/@ember/-internals/metal/index.ts b/packages/@ember/-internals/metal/index.ts index 60ee9db0618..ab62c3cae84 100644 --- a/packages/@ember/-internals/metal/index.ts +++ b/packages/@ember/-internals/metal/index.ts @@ -1,10 +1,4 @@ -export { - default as computed, - autoComputed, - isComputed, - _globalsComputed, - ComputedProperty, -} from './lib/computed'; +export { default as computed, autoComputed, isComputed, ComputedProperty } from './lib/computed'; export { getCachedValueFor } from './lib/computed_cache'; export { default as alias } from './lib/alias'; export { deprecateProperty } from './lib/deprecate_property'; diff --git a/packages/@ember/-internals/metal/lib/computed.ts b/packages/@ember/-internals/metal/lib/computed.ts index 066c07ba7f5..630f1eade01 100644 --- a/packages/@ember/-internals/metal/lib/computed.ts +++ b/packages/@ember/-internals/metal/lib/computed.ts @@ -1079,6 +1079,4 @@ export function isComputed(obj: object, key: string): boolean { return Boolean(descriptorForProperty(obj, key)); } -export const _globalsComputed = computed.bind(null); - export default computed; diff --git a/packages/@ember/object/index.js b/packages/@ember/object/index.js index 4207c312993..9c6bb11faed 100644 --- a/packages/@ember/object/index.js +++ b/packages/@ember/object/index.js @@ -1,4 +1,5 @@ -import { assert } from '@ember/debug'; +import { DEBUG } from '@glimmer/env'; +import { assert, deprecate } from '@ember/debug'; import { assign } from '@ember/polyfills'; import { isElementDescriptor, setClassicDecorator } from '@ember/-internals/metal'; @@ -18,6 +19,132 @@ export { aliasMethod, } from '@ember/-internals/metal'; +import { computed } from '@ember/-internals/metal'; + +import { + alias, + and, + bool, + collect, + deprecatingAlias, + empty, + equal, + filterBy, + filter, + gte, + gt, + intersect, + lte, + lt, + mapBy, + map, + match, + max, + min, + none, + notEmpty, + not, + oneWay, + or, + readOnly, + setDiff, + sort, + sum, + union, + uniqBy, + uniq, +} from '@ember/object/computed'; + +// eslint-disable-next-line no-undef +if (DEBUG) { + 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/runloop';`, + false, + { + id: 'deprecated-run-loop-and-computed-dot-access', + until: '4.0.0', + for: 'ember-source', + since: { + enabled: '3.27.0', + }, + } + ); + + return func; + }, + }); + }; + + defineDeprecatedComputedFunc('alias', alias); + defineDeprecatedComputedFunc('and', and); + defineDeprecatedComputedFunc('bool', bool); + defineDeprecatedComputedFunc('collect', collect); + defineDeprecatedComputedFunc('deprecatingAlias', deprecatingAlias); + defineDeprecatedComputedFunc('empty', empty); + defineDeprecatedComputedFunc('equal', equal); + defineDeprecatedComputedFunc('filterBy', filterBy); + defineDeprecatedComputedFunc('filter', filter); + defineDeprecatedComputedFunc('gte', gte); + defineDeprecatedComputedFunc('gt', gt); + defineDeprecatedComputedFunc('intersect', intersect); + defineDeprecatedComputedFunc('lte', lte); + defineDeprecatedComputedFunc('lt', lt); + defineDeprecatedComputedFunc('mapBy', mapBy); + defineDeprecatedComputedFunc('map', map); + defineDeprecatedComputedFunc('match', match); + defineDeprecatedComputedFunc('max', max); + defineDeprecatedComputedFunc('min', min); + defineDeprecatedComputedFunc('none', none); + defineDeprecatedComputedFunc('notEmpty', notEmpty); + defineDeprecatedComputedFunc('not', not); + defineDeprecatedComputedFunc('oneWay', oneWay); + defineDeprecatedComputedFunc('reads', oneWay); + defineDeprecatedComputedFunc('or', or); + defineDeprecatedComputedFunc('readOnly', readOnly); + defineDeprecatedComputedFunc('setDiff', setDiff); + defineDeprecatedComputedFunc('sort', sort); + defineDeprecatedComputedFunc('sum', sum); + defineDeprecatedComputedFunc('union', union); + defineDeprecatedComputedFunc('uniqBy', uniqBy); + defineDeprecatedComputedFunc('uniq', uniq); +} else { + computed.alias = alias; + computed.and = and; + computed.bool = bool; + computed.collect = collect; + computed.deprecatingAlias = deprecatingAlias; + computed.empty = empty; + computed.equal = equal; + computed.filterBy = filterBy; + computed.filter = filter; + computed.gte = gte; + computed.gt = gt; + computed.intersect = intersect; + computed.lte = lte; + computed.lt = lt; + computed.mapBy = mapBy; + computed.map = map; + computed.match = match; + computed.max = max; + computed.min = min; + computed.none = none; + computed.notEmpty = notEmpty; + computed.not = not; + computed.oneWay = oneWay; + computed.reads = oneWay; + computed.or = or; + computed.readOnly = readOnly; + computed.setDiff = setDiff; + computed.sort = sort; + computed.sum = sum; + computed.union = union; + computed.uniqBy = uniqBy; + computed.uniq = uniq; +} + /** Decorator that turns the target function into an Action which can be accessed directly by reference. diff --git a/packages/@ember/runloop/index.js b/packages/@ember/runloop/index.js index caadd6c4a2d..f1be5573c61 100644 --- a/packages/@ember/runloop/index.js +++ b/packages/@ember/runloop/index.js @@ -1,4 +1,5 @@ -import { assert } from '@ember/debug'; +import { DEBUG } from '@glimmer/env'; +import { assert, deprecate } from '@ember/debug'; import { onErrorTarget } from '@ember/-internals/error-handling'; import { flushAsyncObservers } from '@ember/-internals/metal'; import Backburner from 'backburner'; @@ -103,9 +104,6 @@ export function run() { return backburner.run(...arguments); } -// used for the Ember.run global only -export const _globalsRun = run.bind(null); - /** If no run-loop is present, it creates a new one. If a run loop is present it will queue itself to run on the existing run-loops action @@ -742,3 +740,63 @@ export function debounce() { export function throttle() { return backburner.throttle(...arguments); } + +// eslint-disable-next-line no-undef +if (DEBUG) { + let defineDeprecatedRunloopFunc = (key, func, alt) => { + Object.defineProperty(run, key, { + get() { + deprecate( + `Using \`run.${key}\` has been deprecated. Instead, import the value directly from @ember/runloop:\n\n import { ${ + alt || 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', + }, + } + ); + + return func; + }, + }); + }; + + defineDeprecatedRunloopFunc('backburner', backburner); + defineDeprecatedRunloopFunc('begin', begin); + defineDeprecatedRunloopFunc('bind', bind); + defineDeprecatedRunloopFunc('cancel', cancel); + defineDeprecatedRunloopFunc('debounce', debounce); + defineDeprecatedRunloopFunc('end', end); + defineDeprecatedRunloopFunc('hasScheduledTimers', hasScheduledTimers); + defineDeprecatedRunloopFunc('join', join); + defineDeprecatedRunloopFunc('later', later); + defineDeprecatedRunloopFunc('next', next); + defineDeprecatedRunloopFunc('once', once); + defineDeprecatedRunloopFunc('schedule', schedule); + defineDeprecatedRunloopFunc('scheduleOnce', scheduleOnce); + defineDeprecatedRunloopFunc('throttle', throttle); + defineDeprecatedRunloopFunc('cancelTimers', cancelTimers); + defineDeprecatedRunloopFunc('currentRunLoop', getCurrentRunLoop, 'getCurrentRunLoop'); +} else { + run.backburner = backburner; + run.begin = begin; + run.bind = bind; + run.cancel = cancel; + run.debounce = debounce; + run.end = end; + run.hasScheduledTimers = hasScheduledTimers; + run.join = join; + run.later = later; + run.next = next; + run.once = once; + run.schedule = schedule; + run.scheduleOnce = scheduleOnce; + run.throttle = throttle; + run.cancelTimers = cancelTimers; + run.currentRunLoop = getCurrentRunLoop; +} diff --git a/packages/ember/index.js b/packages/ember/index.js index 980f6fb21bd..43543fdb462 100644 --- a/packages/ember/index.js +++ b/packages/ember/index.js @@ -33,42 +33,9 @@ import { } from '@ember/string'; import Service, { inject as injectService } from '@ember/service'; -import { action } from '@ember/object'; +import { action, computed } from '@ember/object'; import { dependentKeyCompat } from '@ember/object/compat'; -import { - and, - bool, - collect, - deprecatingAlias, - empty, - equal, - filterBy, - filter, - gte, - gt, - intersect, - lte, - lt, - mapBy, - map, - match, - max, - min, - none, - notEmpty, - not, - oneWay, - or, - readOnly, - setDiff, - sort, - sum, - union, - uniqBy, - uniq, -} from '@ember/object/computed'; - import { Object as EmberObject, RegistryProxyMixin, @@ -124,7 +91,7 @@ import * as views from '@ember/-internals/views'; import * as routing from '@ember/-internals/routing'; import * as extensionSupport from '@ember/-internals/extension-support'; import EmberError from '@ember/error'; -import * as runloop from '@ember/runloop'; +import { run } from '@ember/runloop'; import { getOnerror, setOnerror } from '@ember/-internals/error-handling'; import { getOwner, setOwner } from '@ember/-internals/owner'; import Application, { onLoad, runLoadHooks } from '@ember/application'; @@ -311,37 +278,14 @@ Ember.Instrumentation = { // ****@ember/runloop**** -// Using _globalsRun here so that mutating the function (adding -// `next`, `later`, etc to it) is only available in globals builds -Ember.run = runloop._globalsRun; -Ember.run.backburner = runloop.backburner; -Ember.run.begin = runloop.begin; -Ember.run.bind = runloop.bind; -Ember.run.cancel = runloop.cancel; -Ember.run.debounce = runloop.debounce; -Ember.run.end = runloop.end; -Ember.run.hasScheduledTimers = runloop.hasScheduledTimers; -Ember.run.join = runloop.join; -Ember.run.later = runloop.later; -Ember.run.next = runloop.next; -Ember.run.once = runloop.once; -Ember.run.schedule = runloop.schedule; -Ember.run.scheduleOnce = runloop.scheduleOnce; -Ember.run.throttle = runloop.throttle; -Ember.run.cancelTimers = runloop.cancelTimers; -Object.defineProperty(Ember.run, 'currentRunLoop', { - get: runloop.getCurrentRunLoop, - enumerable: false, -}); +Ember.run = run; // ****@ember/-internals/metal**** // in globals builds -const computed = metal._globalsComputed; Ember.computed = computed; Ember._descriptor = metal.nativeDescDecorator; Ember._tracked = metal.tracked; -computed.alias = metal.alias; Ember.cacheFor = metal.getCachedValueFor; Ember.ComputedProperty = metal.ComputedProperty; Ember._setClassicDecorator = metal.setClassicDecorator; @@ -507,40 +451,6 @@ Ember.Namespace = Namespace; Ember._action = action; Ember._dependentKeyCompat = dependentKeyCompat; -computed.empty = empty; -computed.notEmpty = notEmpty; -computed.none = none; -computed.not = not; -computed.bool = bool; -computed.match = match; -computed.equal = equal; -computed.gt = gt; -computed.gte = gte; -computed.lt = lt; -computed.lte = lte; -computed.oneWay = oneWay; -computed.reads = oneWay; -computed.readOnly = readOnly; -computed.deprecatingAlias = deprecatingAlias; -computed.and = and; -computed.or = or; - -computed.sum = sum; -computed.min = min; -computed.max = max; -computed.map = map; -computed.sort = sort; -computed.setDiff = setDiff; -computed.mapBy = mapBy; -computed.filter = filter; -computed.filterBy = filterBy; -computed.uniq = uniq; - -computed.uniqBy = uniqBy; -computed.union = union; -computed.intersect = intersect; -computed.collect = collect; - /** Defines the hash of localized strings for the current language. Used by the `String.loc` helper. To localize, add string values to this diff --git a/packages/ember/tests/reexports_test.js b/packages/ember/tests/reexports_test.js index e4a0dc4ebf4..3d928f78705 100644 --- a/packages/ember/tests/reexports_test.js +++ b/packages/ember/tests/reexports_test.js @@ -13,14 +13,22 @@ moduleFor( class extends AbstractTestCase { [`@test Ember exports correctly`](assert) { allExports.forEach((reexport) => { - let [path, moduleId, exportName] = reexport; + let [path, moduleId, exportName, isDeprecated] = reexport; // default path === exportName if none present if (!exportName) { exportName = path; } - confirmExport(Ember, assert, path, moduleId, exportName, `Ember.${path} exports correctly`); + confirmExport( + Ember, + assert, + path, + moduleId, + exportName, + isDeprecated, + `Ember.${path} exports correctly` + ); }); } @@ -279,7 +287,7 @@ let allExports = [ ['Object', '@ember/object', 'default'], ['_action', '@ember/object', 'action'], ['aliasMethod', '@ember/object', 'aliasMethod'], - [null, '@ember/object', 'computed'], + ['computed', '@ember/object', 'computed'], ['defineProperty', '@ember/object', 'defineProperty'], ['get', '@ember/object', 'get'], ['getProperties', '@ember/object', 'getProperties'], @@ -295,39 +303,39 @@ let allExports = [ // @ember/object/computed ['ComputedProperty', '@ember/object/computed', 'default'], - ['computed.alias', '@ember/object/computed', 'alias'], - ['computed.and', '@ember/object/computed', 'and'], - ['computed.bool', '@ember/object/computed', 'bool'], - ['computed.collect', '@ember/object/computed', 'collect'], - ['computed.deprecatingAlias', '@ember/object/computed', 'deprecatingAlias'], - ['computed.empty', '@ember/object/computed', 'empty'], - ['computed.equal', '@ember/object/computed', 'equal'], - ['expandProperties', '@ember/object/computed', 'expandProperties'], - ['computed.filter', '@ember/object/computed', 'filter'], - ['computed.filterBy', '@ember/object/computed', 'filterBy'], - ['computed.gt', '@ember/object/computed', 'gt'], - ['computed.gte', '@ember/object/computed', 'gte'], - ['computed.intersect', '@ember/object/computed', 'intersect'], - ['computed.lt', '@ember/object/computed', 'lt'], - ['computed.lte', '@ember/object/computed', 'lte'], - ['computed.map', '@ember/object/computed', 'map'], - ['computed.mapBy', '@ember/object/computed', 'mapBy'], - ['computed.match', '@ember/object/computed', 'match'], - ['computed.max', '@ember/object/computed', 'max'], - ['computed.min', '@ember/object/computed', 'min'], - ['computed.none', '@ember/object/computed', 'none'], - ['computed.not', '@ember/object/computed', 'not'], - ['computed.notEmpty', '@ember/object/computed', 'notEmpty'], - ['computed.oneWay', '@ember/object/computed', 'oneWay'], - ['computed.or', '@ember/object/computed', 'or'], - ['computed.readOnly', '@ember/object/computed', 'readOnly'], - ['computed.reads', '@ember/object/computed', 'reads'], - ['computed.setDiff', '@ember/object/computed', 'setDiff'], - ['computed.sort', '@ember/object/computed', 'sort'], - ['computed.sum', '@ember/object/computed', 'sum'], - ['computed.union', '@ember/object/computed', 'union'], - ['computed.uniq', '@ember/object/computed', 'uniq'], - ['computed.uniqBy', '@ember/object/computed', 'uniqBy'], + ['computed.alias', '@ember/object/computed', 'alias', true], + ['computed.and', '@ember/object/computed', 'and', true], + ['computed.bool', '@ember/object/computed', 'bool', true], + ['computed.collect', '@ember/object/computed', 'collect', true], + ['computed.deprecatingAlias', '@ember/object/computed', 'deprecatingAlias', true], + ['computed.empty', '@ember/object/computed', 'empty', true], + ['computed.equal', '@ember/object/computed', 'equal', true], + ['expandProperties', '@ember/object/computed', 'expandProperties', true], + ['computed.filter', '@ember/object/computed', 'filter', true], + ['computed.filterBy', '@ember/object/computed', 'filterBy', true], + ['computed.gt', '@ember/object/computed', 'gt', true], + ['computed.gte', '@ember/object/computed', 'gte', true], + ['computed.intersect', '@ember/object/computed', 'intersect', true], + ['computed.lt', '@ember/object/computed', 'lt', true], + ['computed.lte', '@ember/object/computed', 'lte', true], + ['computed.map', '@ember/object/computed', 'map', true], + ['computed.mapBy', '@ember/object/computed', 'mapBy', true], + ['computed.match', '@ember/object/computed', 'match', true], + ['computed.max', '@ember/object/computed', 'max', true], + ['computed.min', '@ember/object/computed', 'min', true], + ['computed.none', '@ember/object/computed', 'none', true], + ['computed.not', '@ember/object/computed', 'not', true], + ['computed.notEmpty', '@ember/object/computed', 'notEmpty', true], + ['computed.oneWay', '@ember/object/computed', 'oneWay', true], + ['computed.or', '@ember/object/computed', 'or', true], + ['computed.readOnly', '@ember/object/computed', 'readOnly', true], + ['computed.reads', '@ember/object/computed', 'reads', true], + ['computed.setDiff', '@ember/object/computed', 'setDiff', true], + ['computed.sort', '@ember/object/computed', 'sort', true], + ['computed.sum', '@ember/object/computed', 'sum', true], + ['computed.union', '@ember/object/computed', 'union', true], + ['computed.uniq', '@ember/object/computed', 'uniq', true], + ['computed.uniqBy', '@ember/object/computed', 'uniqBy', true], // @ember/object/core ['CoreObject', '@ember/object/core', 'default'], @@ -392,24 +400,23 @@ let allExports = [ ['Router', '@ember/routing/router', 'default'], // @ember/runloop - [null, '@ember/runloop', 'run'], - ['run', '@ember/runloop', '_globalsRun'], - ['run.backburner', '@ember/runloop', 'backburner'], - ['run.begin', '@ember/runloop', 'begin'], - ['run.bind', '@ember/runloop', 'bind'], - ['run.cancel', '@ember/runloop', 'cancel'], - ['run.debounce', '@ember/runloop', 'debounce'], - ['run.end', '@ember/runloop', 'end'], - ['run.hasScheduledTimers', '@ember/runloop', 'hasScheduledTimers'], - ['run.join', '@ember/runloop', 'join'], - ['run.later', '@ember/runloop', 'later'], - ['run.next', '@ember/runloop', 'next'], - ['run.once', '@ember/runloop', 'once'], - ['run.schedule', '@ember/runloop', 'schedule'], - ['run.scheduleOnce', '@ember/runloop', 'scheduleOnce'], - ['run.throttle', '@ember/runloop', 'throttle'], - ['run.currentRunLoop', '@ember/runloop', { get: 'getCurrentRunLoop' }], - ['run.cancelTimers', '@ember/runloop', 'cancelTimers'], + ['run', '@ember/runloop', 'run'], + ['run.backburner', '@ember/runloop', 'backburner', true], + ['run.begin', '@ember/runloop', 'begin', true], + ['run.bind', '@ember/runloop', 'bind', true], + ['run.cancel', '@ember/runloop', 'cancel', true], + ['run.debounce', '@ember/runloop', 'debounce', true], + ['run.end', '@ember/runloop', 'end', true], + ['run.hasScheduledTimers', '@ember/runloop', 'hasScheduledTimers', true], + ['run.join', '@ember/runloop', 'join', true], + ['run.later', '@ember/runloop', 'later', true], + ['run.next', '@ember/runloop', 'next', true], + ['run.once', '@ember/runloop', 'once', true], + ['run.schedule', '@ember/runloop', 'schedule', true], + ['run.scheduleOnce', '@ember/runloop', 'scheduleOnce', true], + ['run.throttle', '@ember/runloop', 'throttle', true], + ['run.currentRunLoop', '@ember/runloop', 'getCurrentRunLoop', true], + ['run.cancelTimers', '@ember/runloop', 'cancelTimers', true], // @ember/service ['Service', '@ember/service', 'default'], @@ -487,7 +494,6 @@ let allExports = [ ['Container', '@ember/-internals/container', 'Container'], // @ember/-internals/metal - ['computed', '@ember/-internals/metal', '_globalsComputed'], ['_descriptor', '@ember/-internals/metal', 'nativeDescDecorator'], ['_setClassicDecorator', '@ember/-internals/metal', 'setClassicDecorator'], ['_getPath', '@ember/-internals/metal'], diff --git a/packages/internal-test-helpers/lib/confirm-export.js b/packages/internal-test-helpers/lib/confirm-export.js index beb549f6ddf..20a87a0cf52 100644 --- a/packages/internal-test-helpers/lib/confirm-export.js +++ b/packages/internal-test-helpers/lib/confirm-export.js @@ -14,7 +14,7 @@ function getDescriptor(obj, path) { return Object.getOwnPropertyDescriptor(value, last); } -export default function confirmExport(Ember, assert, path, moduleId, exportName) { +export default function confirmExport(Ember, assert, path, moduleId, exportName, isDeprecated) { try { let desc; @@ -25,6 +25,10 @@ export default function confirmExport(Ember, assert, path, moduleId, exportName) desc = null; } + if (isDeprecated) { + expectDeprecation(); + } + if (desc === null) { let mod = require(moduleId); assert.notEqual(mod[exportName], undefined, `${moduleId}#${exportName} is not \`undefined\``);