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

[DEPRECATE] Deprecates aliasMethod #17540

Merged
merged 3 commits into from Feb 2, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 60 additions & 40 deletions packages/@ember/-internals/metal/lib/mixin.ts
Expand Up @@ -12,7 +12,8 @@ import {
setObservers,
wrap,
} from '@ember/-internals/utils';
import { assert } from '@ember/debug';
import { assert, deprecate } from '@ember/debug';
import { ALIAS_METHOD } from '@ember/deprecated-features';
import { assign } from '@ember/polyfills';
import { DEBUG } from '@glimmer/env';
import { ComputedProperty, ComputedPropertyGetter, ComputedPropertySetter } from './computed';
Expand Down Expand Up @@ -301,28 +302,37 @@ function mergeMixins(
}
}

function followMethodAlias(
let followMethodAlias: (
obj: object,
_desc: Alias,
alias: Alias,
descs: { [key: string]: any },
values: { [key: string]: any }
) {
let altKey = _desc.methodName;
let possibleDesc;
let desc = descs[altKey];
let value = values[altKey];

if (desc !== undefined || value !== undefined) {
// do nothing
} else if ((possibleDesc = descriptorFor(obj, altKey)) !== undefined) {
desc = possibleDesc;
value = undefined;
} else {
desc = undefined;
value = obj[altKey];
}
) => { desc: any; value: any };

if (ALIAS_METHOD) {
followMethodAlias = function(
obj: object,
alias: Alias,
descs: { [key: string]: any },
values: { [key: string]: any }
) {
let altKey = alias.methodName;
let possibleDesc;
let desc = descs[altKey];
let value = values[altKey];

if (desc !== undefined || value !== undefined) {
// do nothing
} else if ((possibleDesc = descriptorFor(obj, altKey)) !== undefined) {
desc = possibleDesc;
value = undefined;
} else {
desc = undefined;
value = obj[altKey];
}

return { desc, value };
return { desc, value };
};
}

function updateObserversAndListeners(
Expand Down Expand Up @@ -387,10 +397,12 @@ export function applyMixin(obj: { [key: string]: any }, mixins: Mixin[]) {
desc = descs[key];
value = values[key];

while (desc && desc instanceof Alias) {
let followed = followMethodAlias(obj, desc, descs, values);
desc = followed.desc;
value = followed.value;
if (ALIAS_METHOD) {
while (value && value instanceof AliasImpl) {
let followed = followMethodAlias(obj, value, descs, values);
desc = followed.desc;
value = followed.value;
}
}

if (desc === undefined && value === undefined) {
Expand Down Expand Up @@ -703,23 +715,17 @@ function _keys(mixin: Mixin, ret = new Set(), seen = new Set()) {
return ret;
}

class Alias extends Descriptor {
methodName: string;
declare class Alias {
public methodName: string;
constructor(methodName: string);
}

constructor(methodName: string) {
super();
this.methodName = methodName;
}
let AliasImpl: typeof Alias;

teardown(_obj: object, _keyName: string, _meta: Meta): void {
throw new Error('Method not implemented.');
}
get(_obj: object, _keyName: string) {
throw new Error('Method not implemented.');
}
set(_obj: object, _keyName: string, _value: any) {
throw new Error('Method not implemented.');
}
if (ALIAS_METHOD) {
AliasImpl = class AliasImpl {
constructor(public methodName: string) {}
} as typeof Alias;
}

/**
Expand Down Expand Up @@ -747,12 +753,26 @@ class Alias extends Descriptor {

@method aliasMethod
@static
@deprecated Use a shared utility method instead
@for @ember/object
@param {String} methodName name of the method to alias
@public
*/
export function aliasMethod(methodName: string): Alias {
return new Alias(methodName);
export let aliasMethod: (methodName: string) => any;

if (ALIAS_METHOD) {
aliasMethod = function aliasMethod(methodName: string): Alias {
deprecate(
`You attempted to alias '${methodName}, but aliasMethod has been deprecated. Consider extracting the method into a shared utility function.`,
false,
{
id: 'object.alias-method',
until: '4.0.0',
url: 'https://emberjs.com/deprecations/v3.x#toc_object-alias-method',
}
);
return new AliasImpl(methodName);
};
}

// ..........................................................
Expand Down
138 changes: 74 additions & 64 deletions packages/@ember/-internals/metal/tests/mixin/alias_method_test.js
Expand Up @@ -10,82 +10,92 @@ moduleFor(
'aliasMethod',
class extends AbstractTestCase {
['@test methods of another name are aliased when the mixin is applied'](assert) {
let MyMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
barMethod: aliasMethod('fooMethod'),
});

let obj = MyMixin.apply({});
validateAliasMethod(assert, obj);
expectDeprecation(() => {
let MyMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
barMethod: aliasMethod('fooMethod'),
});

let obj = MyMixin.apply({});
validateAliasMethod(assert, obj);
}, /aliasMethod has been deprecated. Consider extracting the method into a shared utility function/);
}

['@test should follow aliasMethods all the way down'](assert) {
let MyMixin = Mixin.create({
bar: aliasMethod('foo'), // put first to break ordered iteration
baz() {
return 'baz';
},
foo: aliasMethod('baz'),
});

let obj = MyMixin.apply({});
assert.equal(get(obj, 'bar')(), 'baz', 'should have followed aliasMethods');
expectDeprecation(() => {
let MyMixin = Mixin.create({
bar: aliasMethod('foo'), // put first to break ordered iteration
baz() {
return 'baz';
},
foo: aliasMethod('baz'),
});

let obj = MyMixin.apply({});
assert.equal(get(obj, 'bar')(), 'baz', 'should have followed aliasMethods');
}, /aliasMethod has been deprecated. Consider extracting the method into a shared utility function/);
}

['@test should alias methods from other dependent mixins'](assert) {
let BaseMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
});

let MyMixin = Mixin.create(BaseMixin, {
barMethod: aliasMethod('fooMethod'),
});

let obj = MyMixin.apply({});
validateAliasMethod(assert, obj);
expectDeprecation(() => {
let BaseMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
});

let MyMixin = Mixin.create(BaseMixin, {
barMethod: aliasMethod('fooMethod'),
});

let obj = MyMixin.apply({});
validateAliasMethod(assert, obj);
}, /aliasMethod has been deprecated. Consider extracting the method into a shared utility function/);
}

['@test should alias methods from other mixins applied at same time'](assert) {
let BaseMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
});

let MyMixin = Mixin.create({
barMethod: aliasMethod('fooMethod'),
});

let obj = mixin({}, BaseMixin, MyMixin);
validateAliasMethod(assert, obj);
expectDeprecation(() => {
let BaseMixin = Mixin.create({
fooMethod() {
return 'FOO';
},
});

let MyMixin = Mixin.create({
barMethod: aliasMethod('fooMethod'),
});

let obj = mixin({}, BaseMixin, MyMixin);
validateAliasMethod(assert, obj);
}, /aliasMethod has been deprecated. Consider extracting the method into a shared utility function/);
}

['@test should alias methods from mixins already applied on object'](assert) {
let BaseMixin = Mixin.create({
quxMethod() {
return 'qux';
},
});

let MyMixin = Mixin.create({
bar: aliasMethod('foo'),
barMethod: aliasMethod('fooMethod'),
});

let obj = {
fooMethod() {
return 'FOO';
},
};

BaseMixin.apply(obj);
MyMixin.apply(obj);

validateAliasMethod(assert, obj);
expectDeprecation(() => {
let BaseMixin = Mixin.create({
quxMethod() {
return 'qux';
},
});

let MyMixin = Mixin.create({
bar: aliasMethod('foo'),
barMethod: aliasMethod('fooMethod'),
});

let obj = {
fooMethod() {
return 'FOO';
},
};

BaseMixin.apply(obj);
MyMixin.apply(obj);

validateAliasMethod(assert, obj);
}, /aliasMethod has been deprecated. Consider extracting the method into a shared utility function/);
}
}
);
11 changes: 6 additions & 5 deletions packages/@ember/-internals/runtime/lib/mixins/array.js
Expand Up @@ -11,7 +11,6 @@ import {
replaceInNativeArray,
replace,
computed,
aliasMethod,
Mixin,
hasListeners,
beginPropertyChanges,
Expand Down Expand Up @@ -180,6 +179,10 @@ function nonEnumerableComputed() {
return property;
}

function mapBy(key) {
return this.map(next => get(next, key));
}

// ..........................................................
// ARRAY
//
Expand Down Expand Up @@ -572,7 +575,7 @@ const ArrayMixin = Mixin.create(Enumerable, {
@return {Array} The mapped array.
@public
*/
getEach: aliasMethod('mapBy'),
getEach: mapBy,

/**
Sets the value on the named property for each member. This is more
Expand Down Expand Up @@ -636,9 +639,7 @@ const ArrayMixin = Mixin.create(Enumerable, {
@return {Array} The mapped array.
@public
*/
mapBy(key) {
return this.map(next => get(next, key));
},
mapBy,

/**
Returns an array with all of the items in the enumeration that the passed
Expand Down
4 changes: 4 additions & 0 deletions packages/@ember/deprecated-features/index.ts
@@ -1,5 +1,8 @@
/* eslint-disable no-implicit-coercion */

// These versions should be the version that the deprecation was _introduced_,
// not the version that the feature will be removed.

export const SEND_ACTION = !!'3.4.0';
export const EMBER_EXTEND_PROTOTYPES = !!'3.2.0-beta.5';
export const RUN_SYNC = !!'3.0.0-beta.4';
Expand All @@ -10,3 +13,4 @@ export const ROUTER_EVENTS = !!'3.9.0';
export const TRANSITION_STATE = !!'3.9.0';
export const COMPONENT_MANAGER_STRING_LOOKUP = !!'4.0.0';
export const JQUERY_INTEGRATION = !!'3.9.0';
export const ALIAS_METHOD = !!'3.9.0';