Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save eventualbuddha/fa4ef27218379030b2c7 to your computer and use it in GitHub Desktop.
Save eventualbuddha/fa4ef27218379030b2c7 to your computer and use it in GitHub Desktop.
/* eslint-disable no-invalid-this, no-extend-native */
import Ember from 'ember';
/**
* Getter/Setter Computed Property Function Deprecation
*
* In Ember 1.12 a deprecation was added for creating a computed property with
* a function that acted as both a getter and a setter:
*
* Ember.computed(function(key, value) {
* if (arguments.length > 1) {
* this._value = value;
* }
* return this._value;
* });
*
* The new way of doing it is using separate functions with a config object:
*
* Ember.computed({
* get() { return this._value; },
* set(key, value) { this._value = value; }
* });
*
* Note that when there is only a getter a function is allowed:
*
* Ember.computed(function() { return this._value; });
*
* This module allows bringing this deprecation into earlier versions of Ember
* and allows callers to use the new API without a deprecation notice. If the
* API already supports config objects then the built-in deprecation will run
* instead and this module can be removed.
*/
/**
* This tries to use the new API and will be `true` if it works as expected.
*/
const canUseConfig = (() => {
try {
return Ember.Object.extend({
prop: Ember.computed({
get() {
return 1;
}
})
}).create().get('prop') === 1;
} catch (error) {
return false;
}
})();
Ember.deprecate(
'Please remove the backported deprecation for getter-setter properties as it is no longer needed.',
canUseConfig
);
/**
* Issues a deprecation notice for this situation.
*/
function deprecate() {
return Ember.deprecate('Using the same function as getter and setter is deprecated.', false, {
url: 'http://emberjs.com/deprecations/v1.x/#toc_deprecate-using-the-same-function-as-getter-and-setter-in-computed-properties'
});
}
// Store the old values so we can uninstall if needed.
const computed = Ember.computed;
const functionPrototypeProperty = Function.prototype.property;
/**
* Use the implementation with deprecation notices.
*/
export function install() {
if (!canUseConfig) {
Ember.computed = computedWithDeprecation;
copyHelpers(computed, computedWithDeprecation);
if (functionPrototypeProperty) {
// Only install this if the original was installed.
Function.prototype.property = functionPrototypePropertyWithDeprecation;
}
}
}
/**
* Copy helpers such as `alias` from one computed function to another. Because
* `source` is a function, we have to ignore a variety of function-related keys
* that show up as "own" properties, hence the gnarly regex.
*/
function copyHelpers(source, destination) {
Object.getOwnPropertyNames(source).forEach(name => {
if (!/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/.test(name)) {
destination[name] = source[name];
}
});
}
/**
* Restore the original implementation without deprecation notices.
*/
export function uninstall() {
if (!canUseConfig) {
Ember.computed = computed;
if (functionPrototypeProperty) {
// Only restore if it was there to begin with.
Function.prototype.property = functionPrototypeProperty;
}
}
}
/**
* Issues deprecations when calling `.property()` on a function with a
* getter-setter function instead of a config object.
*/
function functionPrototypePropertyWithDeprecation(...dependentKeys) {
return computedWithDeprecation.call(this, ...dependentKeys, this);
}
/**
* Transforms calls with a config object to use the function API, and issues
* deprecations when passing a getter-setter function.
*/
function computedWithDeprecation(...dependentKeys) {
let config = dependentKeys.pop();
if (typeof config !== 'function') {
config = (function(config) {
if (config.set) {
return (function(key, value) {
if (arguments.length > 1) {
config.set.call(this, key, value);
}
return config.get.call(this, key);
});
} else {
return config.get;
}
})(config);
} else if (config.length > 1) {
deprecate();
}
return computed(...dependentKeys, config);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment