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 release] Deprecate @each as a leaf node. #11994

Merged
merged 12 commits into from
Aug 8, 2015
18 changes: 16 additions & 2 deletions packages/ember-htmlbars/lib/keywords/unbound.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
/**
@module ember
@submodule ember-htmlbars
The `{{unbound}}` helper can be used with bound helper invocations to
render them in their unbound form.

```handlebars
{{unbound (capitalize name)}}
```

In the aforementioned example, if the `name` property changes, the helper
will not re-render.

@module ember
@submodule ember-templates

@method unbound
@for Ember.Templates.helpers
@public
*/

export default function unbound(morph, env, scope, originalParams, hash, template, inverse) {
Expand Down
1 change: 1 addition & 0 deletions packages/ember-htmlbars/tests/helpers/collection_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ QUnit.test("empty views should be removed when content is added to the collectio
});

view = EmberView.create({
_viewRegistry: {},
listView: ListView,
listController: listController,
template: compile('{{#collection view.listView content=view.listController tagName="table"}} <td>{{view.content.title}}</td> {{/collection}}')
Expand Down
15 changes: 12 additions & 3 deletions packages/ember-htmlbars/tests/helpers/with_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ QUnit.test("it should wrap context with object controller [DEPRECATED]", functio
name: 'Bob Loblaw'
});

expectDeprecation(/Using the {{with}} helper with a `controller` specified/);

view = EmberView.create({
container: container,
template: compile('{{#with view.person controller="person"}}{{controllerName}}{{/with}}'),
Expand Down Expand Up @@ -379,6 +381,8 @@ QUnit.test("it should wrap keyword with object controller [DEPRECATED]", functio
});

QUnit.test("destroys the controller generated with {{with foo controller='blah'}} [DEPRECATED]", function() {
expectDeprecation(/Using the {{with}} helper with a `controller` specified/);

var destroyed = false;
var Controller = EmberController.extend({
willDestroy() {
Expand Down Expand Up @@ -433,10 +437,15 @@ QUnit.test("destroys the controller generated with {{with foo as bar controller=
name: 'Bob Loblaw'
});

var template;
expectDeprecation(function() {
template = compile('{{#with person controller="person" as |steve|}}{{controllerName}}{{/with}}');
}, `Using the {{with}} helper with a \`controller\` specified (L1:C0) is deprecated and will be removed in 2.0.0.`);

view = EmberView.create({
container: container,
template: compile('{{#with person controller="person" as |steve|}}{{controllerName}}{{/with}}'),
controller: parentController
controller: parentController,
template,
container
});

registry.register('controller:person', Controller);
Expand Down
8 changes: 8 additions & 0 deletions packages/ember-metal/lib/computed.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ember from 'ember-metal/core';
import { set } from "ember-metal/property_set";
import {
meta,
Expand Down Expand Up @@ -251,6 +252,13 @@ ComputedPropertyPrototype.property = function() {
var args;

var addArg = function(property) {
Ember.deprecate(
`Depending on arrays using a dependent key ending with \`@each\` is deprecated. ` +
`Please refactor from \`Ember.computed('${property}', function() {});\` to \`Ember.computed('${property.slice(0, -6)}.[]', function() {})\`.`,
property.slice(-5) !== '@each',
{ id: 'ember-metal.@each-dependent-key-leaf', until: '2.0.0' }
);

args.push(property);
};

Expand Down
1 change: 0 additions & 1 deletion packages/ember-metal/lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true;
An empty function useful for some operations. Always returns `this`.

@method K
@private
@return {Object}
@public
*/
Expand Down
3 changes: 2 additions & 1 deletion packages/ember-metal/lib/expand_properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ var SPLIT_REGEX = /\{|\}/;
Ember.expandProperties('{foo}.bar.{baz}') //=> 'foo.bar.baz'
```

@method
@method expandProperties
@for Ember
@private
@param {String} pattern The property pattern to expand.
@param {Function} callback The callback to invoke. It is invoked once per
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-metal/lib/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import keys from 'ember-metal/keys';
@param {Object} original The object to merge into
@param {Object} updates The object to copy properties from
@return {Object}
@private
@public
*/
export default function merge(original, updates) {
if (!updates || typeof updates !== 'object') {
Expand Down
11 changes: 10 additions & 1 deletion packages/ember-metal/lib/mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,16 @@ export function observer(...args) {
var func = args.slice(-1)[0];
var paths;

var addWatchedProperty = function(path) { paths.push(path); };
var addWatchedProperty = function(path) {
Ember.deprecate(
`Depending on arrays using a dependent key ending with \`@each\` is deprecated. ` +
`Please refactor from \`Ember.observer('${path}', function() {});\` to \`Ember.computed('${path.slice(0, -6)}.[]', function() {})\`.`,
path.slice(-5) !== '@each',
{ id: 'ember-metal.@each-dependent-key-leaf', until: '2.0.0' }
);

paths.push(path);
};
var _paths = args.slice(0, -1);

if (typeof func !== "function") {
Expand Down
10 changes: 10 additions & 0 deletions packages/ember-metal/tests/computed_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ QUnit.test('defining computed property should invoke property on set', function(
equal(get(obj, 'foo'), 'computed bar', 'should return new value');
});

QUnit.test('defining a computed property with a dependent key ending with @each is deprecated', function() {
expectDeprecation(function() {
computed('blazo.@each', function() { });
}, `Depending on arrays using a dependent key ending with \`@each\` is deprecated. Please refactor from \`Ember.computed('blazo.@each', function() {});\` to \`Ember.computed('blazo.[]', function() {})\`.`);

expectDeprecation(function() {
computed('qux', 'zoopa.@each', function() { });
}, `Depending on arrays using a dependent key ending with \`@each\` is deprecated. Please refactor from \`Ember.computed('zoopa.@each', function() {});\` to \`Ember.computed('zoopa.[]', function() {})\`.`);
});

var objA, objB;
QUnit.module('computed should inherit through prototype', {
setup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ QUnit.test("should target the current controller inside an {{each}} loop [DEPREC
QUnit.test("should target the with-controller inside an {{#with controller='person'}} [DEPRECATED]", function() {
var registeredTarget;

expectDeprecation(/Using the {{with}} helper with a `controller` specified/);

ActionHelper.registerAction = function({ node }) {
registeredTarget = node.state.target;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-runtime/lib/computed/reduce_computed.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ DependentArraysObserver.prototype = {
},

resetTransformations(dependentKey, observerContexts) {
this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts);
this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts, true);
},

trackAdd(dependentKey, index, newItems) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ export function filter(dependentKey, callback) {
_suppressDeprecation: true,

initialize(array, changeMeta, instanceMeta) {
instanceMeta.filteredArrayIndexes = new SubArray();
instanceMeta.filteredArrayIndexes = new SubArray(undefined, true);
},

addedItem(array, item, changeMeta, instanceMeta) {
Expand Down
10 changes: 5 additions & 5 deletions packages/ember-runtime/lib/mixins/enumerable.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export default Mixin.create({
@param {Function} callback The callback to execute
@param {Object} [target] The target object to use
@return {Object} receiver
@private
@public
*/
forEach(callback, target) {
if (typeof callback !== 'function') {
Expand Down Expand Up @@ -643,7 +643,7 @@ export default Mixin.create({
@param {Function} callback The callback to execute
@param {Object} [target] The target object to use
@return {Boolean}
@private
@public
*/
every(callback, target) {
return !this.find(function(x, idx, i) {
Expand Down Expand Up @@ -921,7 +921,7 @@ export default Mixin.create({

@method compact
@return {Array} the array without null and undefined elements.
@private
@public
*/
compact() {
return this.filter(function(value) {
Expand All @@ -942,7 +942,7 @@ export default Mixin.create({
@method without
@param {Object} value
@return {Ember.Enumerable}
@private
@public
*/
without(value) {
if (!this.contains(value)) {
Expand Down Expand Up @@ -1196,7 +1196,7 @@ export default Mixin.create({
@param {String} property name(s) to sort on
@return {Array} The sorted array.
@since 1.2.0
@private
@public
*/
sortBy() {
var sortKeys = arguments;
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-runtime/lib/mixins/sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default Mixin.create(MutableEnumerable, {
@property arrangedContent
@private
*/
arrangedContent: computed('content', 'sortProperties.@each', {
arrangedContent: computed('content', 'sortProperties.[]', {
get(key) {
var content = get(this, 'content');
var isSorted = get(this, 'isSorted');
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-runtime/lib/system/array_proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function K() { return this; }
@namespace Ember
@extends Ember.Object
@uses Ember.MutableArray
@private
@public
*/
var ArrayProxy = EmberObject.extend(MutableArray, {

Expand Down
11 changes: 9 additions & 2 deletions packages/ember-runtime/lib/system/subarray.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ember from 'ember-metal/core';
import EmberError from "ember-metal/error";
import { forEach } from "ember-metal/enumerable_utils";

Expand All @@ -20,8 +21,14 @@ export default SubArray;
@namespace Ember
@private
*/
function SubArray(length) {
if (arguments.length < 1) { length = 0; }
function SubArray(length, _suppressDeprecation) {
Ember.deprecate(
'Ember.SubArray will be removed in 2.0.0.',
_suppressDeprecation,
{ id: 'ember-metal.sub-array', until: '2.0.0' }
);

if (length === undefined) { length = 0; }

if (length > 0) {
this._operations = [new Operation(RETAIN, length)];
Expand Down
9 changes: 8 additions & 1 deletion packages/ember-runtime/lib/system/tracked_array.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ember from 'ember-metal/core';
import { get } from "ember-metal/property_get";
import { forEach } from "ember-metal/enumerable_utils";

Expand All @@ -18,7 +19,13 @@ export default TrackedArray;
the initial items for the starting state of retain:n.
@private
*/
function TrackedArray(items) {
function TrackedArray(items, _suppressDeprecation) {
Ember.deprecate(
'Ember.TrackedArray will be removed in 2.0.0.',
_suppressDeprecation,
{ id: 'ember-metal.tracked-array', until: '2.0.0' }
);

if (arguments.length < 1) { items = []; }

var length = get(items, 'length');
Expand Down
1 change: 1 addition & 0 deletions packages/ember-runtime/tests/system/subarray_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var subarray;

QUnit.module('SubArray', {
setup() {
expectDeprecation('Ember.SubArray will be removed in 2.0.0.');
subarray = new SubArray();
}
});
Expand Down
6 changes: 5 additions & 1 deletion packages/ember-runtime/tests/system/tracked_array_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ var RETAIN = TrackedArray.RETAIN;
var INSERT = TrackedArray.INSERT;
var DELETE = TrackedArray.DELETE;

QUnit.module('Ember.TrackedArray');
QUnit.module('Ember.TrackedArray', {
setup: function() {
expectDeprecation('Ember.TrackedArray will be removed in 2.0.0.');
}
});

QUnit.test("operations for a tracked array of length n are initially retain:n", function() {
trackedArray = new TrackedArray([1,2,3,4]);
Expand Down
2 changes: 2 additions & 0 deletions packages/ember-template-compiler/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import TransformAngleBracketComponents from "ember-template-compiler/plugins/tra
import TransformInputOnToOnEvent from "ember-template-compiler/plugins/transform-input-on-to-onEvent";
import DeprecateViewAndControllerPaths from "ember-template-compiler/plugins/deprecate-view-and-controller-paths";
import DeprecateViewHelper from "ember-template-compiler/plugins/deprecate-view-helper";
import DeprecateWithController from 'ember-template-compiler/plugins/deprecate-with-controller';

// used for adding Ember.Handlebars.compile for backwards compat
import "ember-template-compiler/compat";
Expand All @@ -36,6 +37,7 @@ registerPlugin('ast', TransformAngleBracketComponents);
registerPlugin('ast', TransformInputOnToOnEvent);
registerPlugin('ast', DeprecateViewAndControllerPaths);
registerPlugin('ast', DeprecateViewHelper);
registerPlugin('ast', DeprecateWithController);

export {
_Ember,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Ember from 'ember-metal/core';
import calculateLocationDisplay from 'ember-template-compiler/system/calculate-location-display';

/**
@module ember
@submodule ember-template-compiler
*/

/**
An HTMLBars AST transformation that deprecates usage of `controller` with the `{{with}}`
helper.

@private
@class DeprecateWithController
*/
function DeprecateWithController(options) {
// set later within HTMLBars to the syntax package
this.syntax = null;
this.options = options || {};
}

/**
@private
@method transform
@param {AST} ast The AST to be transformed.
*/
DeprecateWithController.prototype.transform = function DeprecateWithController_transform(ast) {
const pluginContext = this;
const walker = new pluginContext.syntax.Walker();
const moduleName = pluginContext.options.moduleName;

walker.visit(ast, function(node) {
if (pluginContext.validate(node)) {
let moduleInfo = calculateLocationDisplay(moduleName, node.loc);

Ember.deprecate(
`Using the {{with}} helper with a \`controller\` specified ${moduleInfo}is deprecated and will be removed in 2.0.0.`,
false,
{ id: 'ember-template-compiler.with-controller', until: '2.0.0' }
);
}
});

return ast;
};

DeprecateWithController.prototype.validate = function TransformWithAsToHash_validate(node) {
return (node.type === 'BlockStatement' || node.type === 'MustacheStatement') &&
node.path.original === 'with' &&
hashPairForKey(node.hash, 'controller');
};

function hashPairForKey(hash, key) {
for (let i = 0, l = hash.pairs.length; i < l; i++) {
let pair = hash.pairs[i];
if (pair.key === key) {
return pair;
}
}

return false;
}

export default DeprecateWithController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { compile } from 'ember-template-compiler';

QUnit.module('ember-template-compiler: deprecate-with-controller');

QUnit.test('Using `{{with}}` with `controller` hash argument provides a deprecation', function() {
expect(1);

expectDeprecation(function() {
compile('{{#with controller="foo"}}{{/with}}', {
moduleName: 'foo/bar/baz'
});
}, `Using the {{with}} helper with a \`controller\` specified ('foo/bar/baz' @ L1:C0) is deprecated and will be removed in 2.0.0.`);
});
Loading