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

[DEPRECATION] Deprecate old class binding syntax and {{attrs}} #19375

Merged
merged 1 commit into from
Feb 3, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ moduleFor(
expectDeprecation(
`The use of \`{{partial}}\` is deprecated, please refactor the "troll" partial to a component`
);
expectDeprecation(
'Using {{attrs}} to reference named arguments has been deprecated. {{attrs.wat}} should be updated to {{@wat}}. (L1:C2) '
);

this.setupEngineWithAttrs([]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ moduleFor(
}

['@test it can have class name bindings in the template']() {
expectDeprecation(
"Passing the `classNameBindings` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render(
Expand Down Expand Up @@ -343,6 +347,10 @@ moduleFor(
}

['@test const bindings can be set as attrs']() {
expectDeprecation(
"Passing the `classNameBindings` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });
this.render('{{foo-bar classNameBindings="foo:enabled:disabled"}}', {
foo: true,
Expand Down Expand Up @@ -675,6 +683,10 @@ moduleFor(
'ClassBinding integration',
class extends RenderingTestCase {
['@test it should apply classBinding without condition always']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding=":foo"}}');
Expand All @@ -695,6 +707,10 @@ moduleFor(
}

['@test it should merge classBinding with class']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="birdman:respeck" class="myName"}}', {
Expand All @@ -717,6 +733,10 @@ moduleFor(
}

['@test it should apply classBinding with only truthy condition']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="myName:respeck"}}', {
Expand All @@ -739,6 +759,10 @@ moduleFor(
}

['@test it should apply classBinding with only falsy condition']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="myName::shade"}}', {
Expand All @@ -761,6 +785,10 @@ moduleFor(
}

['@test it should apply nothing when classBinding is falsy but only supplies truthy class']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="myName:respeck"}}', {
Expand All @@ -783,6 +811,10 @@ moduleFor(
}

['@test it should apply nothing when classBinding is truthy but only supplies falsy class']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="myName::shade"}}', { myName: true });
Expand All @@ -803,6 +835,10 @@ moduleFor(
}

['@test it should apply classBinding with falsy condition']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="swag:fresh:scrub"}}', {
Expand All @@ -825,6 +861,10 @@ moduleFor(
}

['@test it should apply classBinding with truthy condition']() {
expectDeprecation(
"Passing the `classBinding` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('-top-level' @ L1:C0) "
);

this.registerComponent('foo-bar', { template: 'hello' });

this.render('{{foo-bar classBinding="swag:fresh:scrub"}}', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,10 @@ moduleFor(
}

['@test non-block with properties on attrs']() {
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.someProp}} should be updated to {{@someProp}}. ('my-app/templates/components/non-block.hbs' @ L1:C24) "
);

this.registerComponent('non-block', {
template: 'In layout - someProp: {{attrs.someProp}}',
});
Expand Down Expand Up @@ -1512,6 +1516,22 @@ moduleFor(
}

['@test this.attrs.foo === attrs.foo === @foo === foo']() {
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.value}} should be updated to {{@value}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C8) "
);

expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.value}} should be updated to {{@value}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C31) "
);

expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.items}} should be updated to {{@items}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C82) "
);

expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.items}} should be updated to {{@items}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C135) "
);

this.registerComponent('foo-bar', {
template: strip`
Args: {{this.attrs.value}} | {{attrs.value}} | {{@value}} | {{this.value}}
Expand Down Expand Up @@ -1606,6 +1626,10 @@ moduleFor(
}

['@test block with properties on attrs']() {
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.someProp}} should be updated to {{@someProp}}. ('my-app/templates/components/with-block.hbs' @ L1:C24) "
);

this.registerComponent('with-block', {
template: 'In layout - someProp: {{attrs.someProp}} - {{yield}}',
});
Expand Down Expand Up @@ -3521,6 +3545,13 @@ moduleFor(
}

['@test using attrs for positional params']() {
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.myVar}} should be updated to {{@myVar}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C10) "
);
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.myVar2}} should be updated to {{@myVar2}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C65) "
);

let MyComponent = Component.extend();

this.registerComponent('foo-bar', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,13 @@ moduleFor(

['@test nested component helpers']() {
this.registerComponent('foo-bar', {
template: 'yippie! {{attrs.location}} {{yield}}',
template: 'yippie! {{@location}} {{yield}}',
});
this.registerComponent('baz-qux', {
template: 'yummy {{attrs.location}} {{yield}}',
template: 'yummy {{@location}} {{yield}}',
});
this.registerComponent('corge-grault', {
template: 'delicious {{attrs.location}} {{yield}}',
template: 'delicious {{@location}} {{yield}}',
});

this.render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,43 +320,6 @@ moduleFor(
});
}

// See https://github.com/emberjs/ember.js/issues/17771
[`@skip The <LinkTo /> component supports 'classNameBindings' with custom values [GH #11699]`](
assert
) {
this.addTemplate(
'index',
`
<h3 class="home">Home</h3>
<LinkTo id='about-link' @route='about' @classNameBindings='foo:foo-is-true:foo-is-false'>About</LinkTo>
`
);

this.add(
'controller:index',
Controller.extend({
foo: false,
})
);

return this.visit('/').then(() => {
assert.equal(
this.$('#about-link.foo-is-false').length,
1,
'The about-link was rendered with the falsy class'
);

let controller = this.applicationInstance.lookup('controller:index');
runTask(() => controller.set('foo', true));

assert.equal(
this.$('#about-link.foo-is-true').length,
1,
'The about-link was rendered with the truthy class after toggling the property'
);
});
}

async ['@test Using <LinkTo> inside a non-routable engine errors'](assert) {
this.add(
'engine:not-routable',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ moduleFor(
[`@test The {{link-to}} component supports 'classNameBindings' with custom values [GH #11699]`](
assert
) {
expectDeprecation(
"Passing the `classNameBindings` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ('my-app/templates/index.hbs' @ L3:C8) "
);

this.addTemplate(
'index',
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ moduleFor(
}

['@test [#12718] a nice error is shown when a bound action function is undefined and it is passed as attrs.foo']() {
expectDeprecation(
"Using {{attrs}} to reference named arguments has been deprecated. {{attrs.external-action}} should be updated to {{@external-action}}. ('my-app/templates/components/inner-component.hbs' @ L1:C43) "
);

this.registerComponent('inner-component', {
template:
'<button id="inner-button" {{action (action attrs.external-action)}}>Click me</button>',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { deprecate } from '@ember/debug';
import { AST, ASTPlugin } from '@glimmer/syntax';
import calculateLocationDisplay from '../system/calculate-location-display';
import { EmberASTPluginEnvironment } from '../types';

/**
Expand Down Expand Up @@ -27,6 +29,7 @@ import { EmberASTPluginEnvironment } from '../types';

export default function transformAttrsIntoArgs(env: EmberASTPluginEnvironment): ASTPlugin {
let { builders: b } = env.syntax;
let { moduleName } = env.meta;

let stack: string[][] = [[]];

Expand All @@ -47,6 +50,26 @@ export default function transformAttrsIntoArgs(env: EmberASTPluginEnvironment):
PathExpression(node: AST.PathExpression): AST.Node | void {
if (isAttrs(node, stack[stack.length - 1])) {
let path = b.path(node.original.substr(6)) as AST.PathExpression;

deprecate(
`Using {{attrs}} to reference named arguments has been deprecated. {{attrs.${
path.original
}}} should be updated to {{@${path.original}}}. ${calculateLocationDisplay(
moduleName,
node.loc
)}`,
false,
{
id: 'attrs-arg-access',
url: 'https://deprecations.emberjs.com/v3.x/#toc_attrs-arg-access',
until: '4.0.0',
for: 'ember-source',
since: {
enabled: '3.26.0',
},
}
);

path.original = `@${path.original}`;
path.data = true;
return path;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import { deprecate } from '@ember/debug';
import { AST, ASTPlugin } from '@glimmer/syntax';
import calculateLocationDisplay from '../system/calculate-location-display';
import { Builders, EmberASTPluginEnvironment } from '../types';

export default function transformOldClassBindingSyntax(env: EmberASTPluginEnvironment): ASTPlugin {
let b = env.syntax.builders;
let { moduleName } = env.meta;

return {
name: 'transform-old-class-binding-syntax',

visitor: {
MustacheStatement(node: AST.MustacheStatement) {
process(b, node);
process(b, node, moduleName);
},

BlockStatement(node: AST.BlockStatement) {
process(b, node);
process(b, node, moduleName);
},
},
};
}

function process(b: Builders, node: AST.BlockStatement | AST.MustacheStatement) {
function process(
b: Builders,
node: AST.BlockStatement | AST.MustacheStatement,
moduleName: string
) {
let allOfTheMicrosyntaxes: AST.HashPair[] = [];
let allOfTheMicrosyntaxIndexes: number[] = [];
let classPair: AST.HashPair | undefined;
Expand All @@ -28,6 +35,24 @@ function process(b: Builders, node: AST.BlockStatement | AST.MustacheStatement)
let { key } = pair;

if (key === 'classBinding' || key === 'classNameBindings') {
deprecate(
`Passing the \`${key}\` property as an argument within templates has been deprecated. Instead, you can pass the class argument and use concatenation to produce the class value dynamically. ${calculateLocationDisplay(
moduleName,
node.loc
)}`,
false,
{
id: 'class-binding-and-class-name-bindings-in-templates',
url:
'https://deprecations.emberjs.com/v3.x/#toc_class-binding-and-class-name-bindings-in-templates',
until: '4.0.0',
for: 'ember-source',
since: {
enabled: '3.26.0',
},
}
);

allOfTheMicrosyntaxIndexes.push(index);
allOfTheMicrosyntaxes.push(pair);
} else if (key === 'class') {
Expand Down