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 {{unbound block and multi param usage. #12018

Merged
merged 1 commit into from
Aug 8, 2015
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
1 change: 1 addition & 0 deletions packages/ember-htmlbars/lib/keywords/unbound.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function unbound(morph, env, scope, originalParams, hash, templat
} else if (template === null) {
env.hooks.inline(morph, env, scope, valueStream.key, params, hash);
} else {
// deprecated via AST transform
env.hooks.block(morph, env, scope, valueStream.key, params, hash, template, inverse);
}

Expand Down
12 changes: 9 additions & 3 deletions packages/ember-htmlbars/tests/helpers/if_unless_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ QUnit.test("The `if` helper tests for `isTruthy` if available", function() {
QUnit.test("The `if` helper does not error on undefined", function() {
view = EmberView.create({
undefinedValue: undefined,
template: compile('{{#if view.undefinedValue}}Yep{{/if}}{{#unbound if view.undefinedValue}}Yep{{/unbound}}')
template: compile('{{#if view.undefinedValue}}Yep{{/if}}')
});

runAppend(view);
Expand All @@ -78,12 +78,12 @@ QUnit.test("The `if` helper does not error on undefined", function() {
QUnit.test("The `unless` helper does not error on undefined", function() {
view = EmberView.create({
undefinedValue: undefined,
template: compile('{{#unless view.undefinedValue}}YepBound{{/unless}}{{#unbound unless view.undefinedValue}}YepUnbound{{/unbound}}')
template: compile('{{#unless view.undefinedValue}}YepBound{{/unless}}')
});

runAppend(view);

equal(view.$().text(), 'YepBoundYepUnbound');
equal(view.$().text(), 'YepBound');
});

QUnit.test("The `if` helper does not print the contents for an object proxy without content", function() {
Expand Down Expand Up @@ -194,6 +194,8 @@ QUnit.test("The `if` helper updates when the value changes", function() {
});

QUnit.test("The `unbound if` helper does not update when the value changes", function() {
expectDeprecation(/Using the {{unbound}} helper with a block .* is deprecated and will be removed/);

view = EmberView.create({
conditional: true,
template: compile('{{#unbound if view.conditional}}Yep{{/unbound}}')
Expand All @@ -220,6 +222,8 @@ QUnit.test("The `unless` helper updates when the value changes", function() {
});

QUnit.test("The `unbound if` helper does not update when the value changes", function() {
expectDeprecation(/Using the {{unbound}} helper with a block .* is deprecated and will be removed/);

view = EmberView.create({
conditional: false,
template: compile('{{#unbound unless view.conditional}}Nope{{/unbound}}')
Expand All @@ -233,6 +237,8 @@ QUnit.test("The `unbound if` helper does not update when the value changes", fun
});

QUnit.test("The `unbound if` helper should work when its inverse is not present", function() {
expectDeprecation(/Using the {{unbound}} helper with a block .* is deprecated and will be removed/);

view = EmberView.create({
conditional: false,
template: compile('{{#unbound if view.conditional}}Yep{{/unbound}}')
Expand Down
2 changes: 2 additions & 0 deletions packages/ember-htmlbars/tests/helpers/unbound_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ QUnit.test('it should re-render if the parent view rerenders', function() {
});

QUnit.test('it should throw the helper missing error if multiple properties are provided', function() {
expectDeprecation(/Using the {{unbound}} helper with multiple params .* is deprecated and will be removed/);

expectAssertion(function() {
runAppend(EmberView.create({
template: compile('{{unbound foo bar}}'),
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 @@ -19,6 +19,7 @@ import TransformInputOnToOnEvent from "ember-template-compiler/plugins/transform
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';
import DeprecateBlockStuff from 'ember-template-compiler/plugins/deprecate-unbound-block-and-multi-param';

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

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

function DeprecateUnboundBlockAndMultiParam(options) {
// set later within HTMLBars to the syntax package
this.syntax = null;
this.options = options || {};
}

DeprecateUnboundBlockAndMultiParam.prototype.transform = function(ast) {
const pluginContext = this;
const walker = new pluginContext.syntax.Walker();
const moduleName = pluginContext.options.moduleName;

walker.visit(ast, function(node) {

if (pluginContext.isBlockUsage(node)) {
let moduleInfo = calculateLocationDisplay(moduleName, node.loc);

Ember.deprecate(
`Using the {{unbound}} helper with a block ${moduleInfo}is deprecated and will be removed in 2.0.0.`,
false,
{ id: 'ember-template-compiler.unbound-block', until: '2.0.0' }
);
} else if (pluginContext.hasMultipleParams(node)) {
let moduleInfo = calculateLocationDisplay(moduleName, node.loc);

Ember.deprecate(
`Using the {{unbound}} helper with multiple params ${moduleInfo}is deprecated and will be removed in 2.0.0. Please refactor to nested helper usage.`,
false,
{ id: 'ember-template-compiler.unbound-multiple-params', until: '2.0.0' }
);
}
});

return ast;
};

DeprecateUnboundBlockAndMultiParam.prototype.isBlockUsage = function(node) {
return node.type === 'BlockStatement' &&
node.path.original === 'unbound';
};

DeprecateUnboundBlockAndMultiParam.prototype.hasMultipleParams = function(node) {
return (node.type === 'BlockStatement' || node.type === 'MustacheStatement') &&
node.path.original === 'unbound' &&
node.params.length > 1;
};

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

QUnit.module('ember-template-compiler: deprecate-unbound-block-and-multi-params');

QUnit.test('Using `{{unbound}}` with a block issues a deprecation', function() {
expect(1);

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

QUnit.test('Using `{{unbound}}` with multiple params issues a deprecation', function() {
expect(1);

expectDeprecation(function() {
compile('{{unbound foo bar}}', {
moduleName: 'foo/bar/baz'
});
}, `Using the {{unbound}} helper with multiple params ('foo/bar/baz' @ L1:C0) is deprecated and will be removed in 2.0.0. Please refactor to nested helper usage.`);
});

QUnit.test('Using `{{unbound}}` with a single param is not deprecated', function() {
expect(1);

compile('{{unbound foo}}', {
moduleName: 'foo/bar/baz'
});

ok(true, 'no deprecations or assertions');
});