Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX beta] Adds assertions to computed macros #17860

Merged
merged 1 commit into from
Apr 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/@ember/-internals/metal/lib/alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
addDependentKeys,
ComputedDescriptor,
Decorator,
isElementDescriptor,
makeComputedDecorator,
removeDependentKeys,
} from './decorator';
Expand All @@ -20,6 +21,11 @@ const CONSUMED = Object.freeze({});
export type AliasDecorator = Decorator & PropertyDecorator & AliasDecoratorImpl;

export default function alias(altKey: string): AliasDecorator {
assert(
'You attempted to use @alias as a decorator directly, but it requires a `altKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return makeComputedDecorator(new AliasedProperty(altKey), AliasDecoratorImpl) as AliasDecorator;
}

Expand Down
76 changes: 76 additions & 0 deletions packages/@ember/object/lib/computed/computed_macros.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
get,
set,
computed,
isElementDescriptor,
isEmpty,
isNone,
alias,
Expand Down Expand Up @@ -35,6 +36,11 @@ function expandPropertiesToArray(predicateName, properties) {

function generateComputedWithPredicate(name, predicate) {
return (...properties) => {
assert(
`You attempted to use @${name} as a decorator directly, but it requires at least one dependent key parameter`,
!isElementDescriptor(properties)
);

let dependentKeys = expandPropertiesToArray(name, properties);

let computedFunc = computed(...dependentKeys, function() {
Expand Down Expand Up @@ -112,6 +118,11 @@ function generateComputedWithPredicate(name, predicate) {
@public
*/
export function empty(dependentKey) {
assert(
'You attempted to use @empty as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(`${dependentKey}.length`, function() {
return isEmpty(get(this, dependentKey));
});
Expand Down Expand Up @@ -172,6 +183,11 @@ export function empty(dependentKey) {
@public
*/
export function notEmpty(dependentKey) {
assert(
'You attempted to use @notEmpty as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(`${dependentKey}.length`, function() {
return !isEmpty(get(this, dependentKey));
});
Expand Down Expand Up @@ -231,6 +247,11 @@ export function notEmpty(dependentKey) {
@public
*/
export function none(dependentKey) {
assert(
'You attempted to use @none as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return isNone(get(this, dependentKey));
});
Expand Down Expand Up @@ -287,6 +308,11 @@ export function none(dependentKey) {
@public
*/
export function not(dependentKey) {
assert(
'You attempted to use @not as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return !get(this, dependentKey);
});
Expand Down Expand Up @@ -355,6 +381,11 @@ export function not(dependentKey) {
@public
*/
export function bool(dependentKey) {
assert(
'You attempted to use @bool as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return Boolean(get(this, dependentKey));
});
Expand Down Expand Up @@ -417,6 +448,11 @@ export function bool(dependentKey) {
@public
*/
export function match(dependentKey, regexp) {
assert(
'You attempted to use @match as a decorator directly, but it requires `dependentKey` and `regexp` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
let value = get(this, dependentKey);
return regexp.test(value);
Expand Down Expand Up @@ -479,6 +515,11 @@ export function match(dependentKey, regexp) {
@public
*/
export function equal(dependentKey, value) {
assert(
'You attempted to use @equal as a decorator directly, but it requires `dependentKey` and `value` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return get(this, dependentKey) === value;
});
Expand Down Expand Up @@ -540,6 +581,11 @@ export function equal(dependentKey, value) {
@public
*/
export function gt(dependentKey, value) {
assert(
'You attempted to use @gt as a decorator directly, but it requires `dependentKey` and `value` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return get(this, dependentKey) > value;
});
Expand Down Expand Up @@ -601,6 +647,11 @@ export function gt(dependentKey, value) {
@public
*/
export function gte(dependentKey, value) {
assert(
'You attempted to use @gte as a decorator directly, but it requires `dependentKey` and `value` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return get(this, dependentKey) >= value;
});
Expand Down Expand Up @@ -662,6 +713,11 @@ export function gte(dependentKey, value) {
@public
*/
export function lt(dependentKey, value) {
assert(
'You attempted to use @lt as a decorator directly, but it requires `dependentKey` and `value` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return get(this, dependentKey) < value;
});
Expand Down Expand Up @@ -723,6 +779,11 @@ export function lt(dependentKey, value) {
@public
*/
export function lte(dependentKey, value) {
assert(
'You attempted to use @lte as a decorator directly, but it requires `dependentKey` and `value` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, function() {
return get(this, dependentKey) <= value;
});
Expand Down Expand Up @@ -991,6 +1052,11 @@ export const or = generateComputedWithPredicate('or', value => !value);
@public
*/
export function oneWay(dependentKey) {
assert(
'You attempted to use @oneWay as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return alias(dependentKey).oneWay();
}

Expand Down Expand Up @@ -1075,6 +1141,11 @@ export function oneWay(dependentKey) {
@public
*/
export function readOnly(dependentKey) {
assert(
'You attempted to use @readOnly as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return alias(dependentKey).readOnly();
}

Expand Down Expand Up @@ -1133,6 +1204,11 @@ export function readOnly(dependentKey) {
@public
*/
export function deprecatingAlias(dependentKey, options) {
assert(
'You attempted to use @deprecatingAlias as a decorator directly, but it requires `dependentKey` and `options` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return computed(dependentKey, {
get(key) {
deprecate(
Expand Down
72 changes: 69 additions & 3 deletions packages/@ember/object/lib/computed/reduce_computed_macros.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import { DEBUG } from '@glimmer/env';
import { assert } from '@ember/debug';
import {
get,
computed,
addObserver,
removeObserver,
computed,
get,
isElementDescriptor,
notifyPropertyChange,
removeObserver,
} from '@ember/-internals/metal';
import { compare, isArray, A as emberA, uniqBy as uniqByArray } from '@ember/-internals/runtime';

Expand Down Expand Up @@ -105,6 +106,11 @@ function multiArrayMacro(_dependentKeys, callback, name) {
@public
*/
export function sum(dependentKey) {
assert(
'You attempted to use @sum as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return reduceMacro(dependentKey, (sum, item) => sum + item, 0, 'sum');
}

Expand Down Expand Up @@ -200,6 +206,11 @@ export function sum(dependentKey) {
@public
*/
export function max(dependentKey) {
assert(
'You attempted to use @max as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return reduceMacro(dependentKey, (max, item) => Math.max(max, item), -Infinity, 'max');
}

Expand Down Expand Up @@ -294,6 +305,11 @@ export function max(dependentKey) {
@public
*/
export function min(dependentKey) {
assert(
'You attempted to use @min as a decorator directly, but it requires a `dependentKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return reduceMacro(dependentKey, (min, item) => Math.min(min, item), Infinity, 'min');
}

Expand Down Expand Up @@ -392,6 +408,11 @@ export function min(dependentKey) {
@public
*/
export function map(dependentKey, additionalDependentKeys, callback) {
assert(
'You attempted to use @map as a decorator directly, but it requires atleast `dependentKey` and `callback` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

if (callback === undefined && typeof additionalDependentKeys === 'function') {
callback = additionalDependentKeys;
additionalDependentKeys = [];
Expand Down Expand Up @@ -496,6 +517,11 @@ export function map(dependentKey, additionalDependentKeys, callback) {
@public
*/
export function mapBy(dependentKey, propertyKey) {
assert(
'You attempted to use @mapBy as a decorator directly, but it requires `dependentKey` and `propertyKey` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

assert(
'`computed.mapBy` expects a property string for its second argument, ' +
'perhaps you meant to use "map"',
Expand Down Expand Up @@ -638,6 +664,11 @@ export function mapBy(dependentKey, propertyKey) {
@public
*/
export function filter(dependentKey, additionalDependentKeys, callback) {
assert(
'You attempted to use @filter as a decorator directly, but it requires atleast `dependentKey` and `callback` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

if (callback === undefined && typeof additionalDependentKeys === 'function') {
callback = additionalDependentKeys;
additionalDependentKeys = [];
Expand Down Expand Up @@ -715,6 +746,11 @@ export function filter(dependentKey, additionalDependentKeys, callback) {
@public
*/
export function filterBy(dependentKey, propertyKey, value) {
assert(
'You attempted to use @filterBy as a decorator directly, but it requires atleast `dependentKey` and `propertyKey` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

assert(
`Dependent key passed to \`computed.filterBy\` shouldn't contain brace expanding pattern.`,
!/[\[\]\{\}]/g.test(dependentKey)
Expand Down Expand Up @@ -789,6 +825,11 @@ export function filterBy(dependentKey, propertyKey, value) {
@public
*/
export function uniq(...args) {
assert(
'You attempted to use @uniq/@union as a decorator directly, but it requires atleast one dependent key parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return multiArrayMacro(
args,
function(dependentKeys) {
Expand Down Expand Up @@ -873,6 +914,11 @@ export function uniq(...args) {
@public
*/
export function uniqBy(dependentKey, propertyKey) {
assert(
'You attempted to use @uniqBy as a decorator directly, but it requires `dependentKey` and `propertyKey` parameters',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

assert(
`Dependent key passed to \`computed.uniqBy\` shouldn't contain brace expanding pattern.`,
!/[\[\]\{\}]/g.test(dependentKey)
Expand Down Expand Up @@ -1013,6 +1059,11 @@ export let union = uniq;
@public
*/
export function intersect(...args) {
assert(
'You attempted to use @intersect as a decorator directly, but it requires atleast one dependent key parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return multiArrayMacro(
args,
function(dependentKeys) {
Expand Down Expand Up @@ -1115,6 +1166,11 @@ export function intersect(...args) {
@public
*/
export function setDiff(setAProperty, setBProperty) {
assert(
'You attempted to use @setDiff as a decorator directly, but it requires atleast one dependent key parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

assert('`computed.setDiff` requires exactly two dependent arrays.', arguments.length === 2);
assert(
`Dependent keys passed to \`computed.setDiff\` shouldn't contain brace expanding pattern.`,
Expand Down Expand Up @@ -1187,6 +1243,11 @@ export function setDiff(setAProperty, setBProperty) {
@public
*/
export function collect(...dependentKeys) {
assert(
'You attempted to use @collect as a decorator directly, but it requires atleast one dependent key parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

return multiArrayMacro(
dependentKeys,
function() {
Expand Down Expand Up @@ -1373,6 +1434,11 @@ export function collect(...dependentKeys) {
@public
*/
export function sort(itemsKey, additionalDependentKeys, sortDefinition) {
assert(
'You attempted to use @sort as a decorator directly, but it requires atleast an `itemsKey` parameter',
!isElementDescriptor(Array.prototype.slice.call(arguments))
);

if (DEBUG) {
let argumentsValid = false;

Expand Down
Loading