Skip to content
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 @@ -1256,13 +1256,17 @@ moduleFor(
this.assertText('somecomponent');
}

['@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) "
);
['@test non-block with properties access via attrs is asserted against']() {
expectAssertion(() => {
this.registerComponent('non-block', {
template: 'In layout - someProp: {{attrs.someProp}}',
});
}, "Using {{attrs}} to reference named arguments is not supported. {{attrs.someProp}} should be updated to {{@someProp}}. ('my-app/templates/components/non-block.hbs' @ L1:C24) ");
}

['@test non-block with properties on this.attrs']() {
this.registerComponent('non-block', {
template: 'In layout - someProp: {{attrs.someProp}}',
template: 'In layout - someProp: {{this.attrs.someProp}}',
});

this.render('{{non-block someProp=this.prop}}', {
Expand Down Expand Up @@ -1469,32 +1473,13 @@ 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) "
);

['@test this.attrs.foo === @foo === foo']() {
this.registerComponent('foo-bar', {
template: strip`
Args: {{this.attrs.value}} | {{attrs.value}} | {{@value}} | {{this.value}}
Args: {{this.attrs.value}} | {{@value}} | {{this.value}}
{{#each this.attrs.items as |item|}}
{{item}}
{{/each}}
{{#each attrs.items as |item|}}
{{item}}
{{/each}}
{{#each @items as |item|}}
{{item}}
{{/each}}
Expand All @@ -1518,11 +1503,11 @@ moduleFor(
this.context.set('model.items', [1]);
});

this.assertText(strip`Args: lul | lul | lul | lul1111`);
this.assertText(strip`Args: lul | lul | lul111`);

runTask(() => this.context.set('model', { value: 'wat', items: [1, 2, 3] }));

this.assertText('Args: wat | wat | wat | wat123123123123');
this.assertText('Args: wat | wat | wat123123123');
}

['@test non-block with properties on self']() {
Expand Down Expand Up @@ -1579,13 +1564,17 @@ moduleFor(
this.assertText('In layout - someProp: something here - In template');
}

['@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) "
);
['@test block with properties on attrs is asserted against']() {
expectAssertion(() => {
this.registerComponent('with-block', {
template: 'In layout - someProp: {{attrs.someProp}} - {{yield}}',
});
}, "Using {{attrs}} to reference named arguments is not supported. {{attrs.someProp}} should be updated to {{@someProp}}. ('my-app/templates/components/with-block.hbs' @ L1:C24) ");
}

['@test block with properties on this.attrs']() {
this.registerComponent('with-block', {
template: 'In layout - someProp: {{attrs.someProp}} - {{yield}}',
template: 'In layout - someProp: {{this.attrs.someProp}} - {{yield}}',
});

this.render(
Expand Down Expand Up @@ -3298,21 +3287,29 @@ moduleFor(
this.assertText('hello');
}

['@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) "
);
['@test using attrs for positional params is asserted against']() {
let MyComponent = Component.extend();

expectAssertion(() => {
this.registerComponent('foo-bar', {
ComponentClass: MyComponent.reopenClass({
positionalParams: ['myVar'],
}),
template:
'MyVar1: {{attrs.myVar}} {{this.myVar}} MyVar2: {{this.myVar2}} {{attrs.myVar2}}',
});
}, "Using {{attrs}} to reference named arguments is not supported. {{attrs.myVar}} should be updated to {{@myVar}}. ('my-app/templates/components/foo-bar.hbs' @ L1:C10) ");
}

['@test using this.attrs for positional params']() {
let MyComponent = Component.extend();

this.registerComponent('foo-bar', {
ComponentClass: MyComponent.reopenClass({
positionalParams: ['myVar'],
}),
template: 'MyVar1: {{attrs.myVar}} {{this.myVar}} MyVar2: {{this.myVar2}} {{attrs.myVar2}}',
template:
'MyVar1: {{this.attrs.myVar}} {{this.myVar}} MyVar2: {{this.myVar2}} {{this.attrs.myVar2}}',
});

this.render('{{foo-bar 1 myVar2=2}}');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,10 @@ moduleFor(
}, /An action could not be made for `.*` in .*\. Please confirm that you are using either a quoted action name \(i\.e\. `\(action '.*'\)`\) or a function available in .*\./);
}

['@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) "
);

['@test [#12718] a nice error is shown when a bound action function is undefined and it is passed as @foo']() {
this.registerComponent('inner-component', {
template:
'<button id="inner-button" {{action (action attrs.external-action)}}>Click me</button>',
'<button id="inner-button" {{action (action @external-action)}}>Click me</button>',
});

this.registerComponent('outer-component', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deprecate } from '@ember/debug';
import { assert } from '@ember/debug';
import { AST, ASTPlugin } from '@glimmer/syntax';
import calculateLocationDisplay from '../system/calculate-location-display';
import { EmberASTPluginEnvironment } from '../types';
Expand All @@ -8,26 +8,19 @@ import { EmberASTPluginEnvironment } from '../types';
*/

/**
A Glimmer2 AST transformation that replaces all instances of
A Glimmer2 AST transformation that asserts against

```handlebars
{{attrs.foo.bar}}
{{attrs.foo.bar}}
```

to

```handlebars
{{@foo.bar}}
```

as well as `{{#if attrs.foo}}`, `{{deeply (nested attrs.foobar.baz)}}`,
`{{this.attrs.foo}}` etc
...as well as `{{#if attrs.foo}}`, `{{deeply (nested attrs.foobar.baz)}}`.

@private
@class TransformAttrsToProps
@class AssertAgainstAttrs
*/

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

Expand All @@ -39,7 +32,7 @@ export default function transformAttrsIntoArgs(env: EmberASTPluginEnvironment):
}

return {
name: 'transform-attrs-into-args',
name: 'assert-against-attrs',

visitor: {
Program: {
Expand All @@ -64,28 +57,15 @@ export default function transformAttrsIntoArgs(env: EmberASTPluginEnvironment):
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.${
assert(
`Using {{attrs}} to reference named arguments is not supported. {{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',
},
}
node.this !== false
);

path.original = `@${path.original}`;
path.data = true;
return path;
}
},
},
Expand Down
4 changes: 2 additions & 2 deletions packages/ember-template-compiler/lib/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import AssertAgainstAttrs from './assert-against-attrs';
import AssertAgainstDynamicHelpersModifiers from './assert-against-dynamic-helpers-modifiers';
import AssertAgainstNamedBlocks from './assert-against-named-blocks';
import AssertAgainstNamedOutlets from './assert-against-named-outlets';
import AssertInputHelperWithoutBlock from './assert-input-helper-without-block';
import AssertReservedNamedArguments from './assert-reserved-named-arguments';
import AssertSplattributeExpressions from './assert-splattribute-expression';
import TransformActionSyntax from './transform-action-syntax';
import TransformAttrsIntoArgs from './transform-attrs-into-args';
import TransformEachInIntoEach from './transform-each-in-into-each';
import TransformEachTrackArray from './transform-each-track-array';
import TransformInElement from './transform-in-element';
Expand All @@ -24,7 +24,7 @@ export const RESOLUTION_MODE_TRANSFORMS = Object.freeze(
TransformQuotedBindingsIntoJustBindings,
AssertReservedNamedArguments,
TransformActionSyntax,
TransformAttrsIntoArgs,
AssertAgainstAttrs,
TransformEachInIntoEach,
TransformLinkTo,
AssertInputHelperWithoutBlock,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import TransformTestCase from '../utils/transform-test-case';
import { moduleFor, RenderingTestCase } from 'internal-test-helpers';

moduleFor(
'ember-template-compiler: assert against attrs',
class extends TransformTestCase {
['@test it asserts against attrs']() {
expectAssertion(() => {
this.assertTransformed(`{{attrs.foo}}`, `{{attrs.foo}}`);
}, /Using {{attrs}} to reference named arguments is not supported. {{attrs.foo}} should be updated to {{@foo}}./);

expectAssertion(() => {
this.assertTransformed(`{{attrs.foo.bar}}`, `{{attrs.foo.bar}}`);
}, /Using {{attrs}} to reference named arguments is not supported. {{attrs.foo.bar}} should be updated to {{@foo.bar}}./);

expectAssertion(() => {
this.assertTransformed(`{{if attrs.foo "foo"}}`, `{{if attrs.foo "foo"}}`);
}, /Using {{attrs}} to reference named arguments is not supported. {{attrs.foo}} should be updated to {{@foo}}./);

expectAssertion(() => {
this.assertTransformed(`{{#if attrs.foo}}{{/if}}`, `{{#if attrs.foo}}{{/if}}`);
}, /Using {{attrs}} to reference named arguments is not supported. {{attrs.foo}} should be updated to {{@foo}}./);

expectAssertion(() => {
this.assertTransformed(
`{{deeply (nested attrs.foo.bar)}}`,
`{{deeply (nested attrs.foo.bar)}}`
);
}, /Using {{attrs}} to reference named arguments is not supported. {{attrs.foo.bar}} should be updated to {{@foo.bar}}./);
}

['@test it does not assert against this.attrs']() {
this.assertTransformed(`{{this.attrs.foo}}`, `{{this.attrs.foo}}`);
this.assertTransformed(`{{if this.attrs.foo "foo"}}`, `{{if this.attrs.foo "foo"}}`);
this.assertTransformed(`{{#if this.attrs.foo}}{{/if}}`, `{{#if this.attrs.foo}}{{/if}}`);
this.assertTransformed(
`{{deeply (nested this.attrs.foo.bar)}}`,
`{{deeply (nested this.attrs.foo.bar)}}`
);
}
}
);

moduleFor(
'ember-template-compiler: not asserting against block params named "attrs"',
class extends RenderingTestCase {
["@test it doesn't assert block params"]() {
this.registerComponent('foo', {
template: '{{#let "foo" as |attrs|}}{{attrs}}{{/let}}',
});
this.render('<Foo />');
this.assertComponentElement(this.firstChild, { content: 'foo' });
}

["@test it doesn't assert component block params"]() {
this.registerComponent('foo', {
template: '{{yield "foo"}}',
});
this.render('<Foo as |attrs|>{{attrs}}</Foo>');
this.assertComponentElement(this.firstChild, { content: 'foo' });
}

["@test it doesn't assert block params with nested keys"]() {
this.registerComponent('foo', {
template: '{{yield (hash bar="baz")}}',
});
this.render('<Foo as |attrs|>{{attrs.bar}}</Foo>');
this.assertComponentElement(this.firstChild, { content: 'baz' });
}
}
);

This file was deleted.