Created
January 7, 2016 18:28
-
-
Save eventualbuddha/fa4ef27218379030b2c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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