diff --git a/packages/compat/src/resolver-transform.ts b/packages/compat/src/resolver-transform.ts index 50e44e911..d66cc98d4 100644 --- a/packages/compat/src/resolver-transform.ts +++ b/packages/compat/src/resolver-transform.ts @@ -5,6 +5,8 @@ import { ResolutionFail, Resolution, ResolvedDep, + HelperResolution, + ModifierResolution, } from './resolver'; import type { ASTv1, ASTPluginBuilder, ASTPluginEnvironment, WalkerPath } from '@glimmer/syntax'; import type { WithJSUtils } from 'babel-plugin-ember-template-compilation'; @@ -241,11 +243,17 @@ export default function makeResolverTransform({ resolver, patchHelpersBug }: Opt return; } if (node.path.original === 'helper' && node.params.length > 0) { - handleDynamicHelper(node.params[0], resolver, filename); + let resolution = handleDynamicHelper(node.params[0], resolver, filename); + emit(path, resolution, (node, newId) => { + node.params[0] = newId; + }); return; } if (node.path.original === 'modifier' && node.params.length > 0) { - handleDynamicModifier(node.params[0], resolver, filename); + let resolution = handleDynamicModifier(node.params[0], resolver, filename); + emit(path, resolution, (node, newId) => { + node.params[0] = newId; + }); return; } let resolution = resolver.resolveSubExpression(node.path.original, filename, node.path.loc); @@ -288,7 +296,10 @@ export default function makeResolverTransform({ resolver, patchHelpersBug }: Opt return; } if (node.path.original === 'helper' && node.params.length > 0) { - handleDynamicHelper(node.params[0], resolver, filename); + let resolution = handleDynamicHelper(node.params[0], resolver, filename); + emit(path, resolution, (node, newIdentifier) => { + node.params[0] = newIdentifier; + }); return; } let hasArgs = node.params.length > 0 || node.hash.pairs.length > 0; @@ -520,20 +531,30 @@ function handleComponentHelper( return resolver.resolveComponentHelper(locator, moduleName, param.loc, impliedBecause); } -function handleDynamicHelper(param: ASTv1.Expression, resolver: Resolver, moduleName: string): void { +function handleDynamicHelper( + param: ASTv1.Expression, + resolver: Resolver, + moduleName: string +): HelperResolution | ResolutionFail | null { // We only need to handle StringLiterals since Ember already throws an error if unsupported values // are passed to the helper keyword. // If a helper reference is passed in we don't need to do anything since it's either the result of a previous // helper keyword invocation, or a helper reference that was imported somewhere. if (param.type === 'StringLiteral') { - resolver.resolveDynamicHelper({ type: 'literal', path: param.value }, moduleName, param.loc); + return resolver.resolveDynamicHelper({ type: 'literal', path: param.value }, moduleName, param.loc); } + return null; } -function handleDynamicModifier(param: ASTv1.Expression, resolver: Resolver, moduleName: string): void { +function handleDynamicModifier( + param: ASTv1.Expression, + resolver: Resolver, + moduleName: string +): ModifierResolution | ResolutionFail | null { if (param.type === 'StringLiteral') { - resolver.resolveDynamicModifier({ type: 'literal', path: param.value }, moduleName, param.loc); + return resolver.resolveDynamicModifier({ type: 'literal', path: param.value }, moduleName, param.loc); } + return null; } function extendPath( diff --git a/packages/compat/tests/resolver.test.ts b/packages/compat/tests/resolver.test.ts index 38b014c49..39c4f7ec9 100644 --- a/packages/compat/tests/resolver.test.ts +++ b/packages/compat/tests/resolver.test.ts @@ -696,7 +696,7 @@ describe('compat-resolver', function () { `); }); - test.skip('string literal passed to "helper" keyword in content position', function () { + test('string literal passed to "helper" keyword in content position', function () { let transform = configure({ staticHelpers: true, }); @@ -705,11 +705,14 @@ describe('compat-resolver', function () { import helloWorld from "../helpers/hello-world.js"; import { precompileTemplate } from "@ember/template-compilation"; export default precompileTemplate("{{helper helloWorld}}", { - moduleName: "my-app/templates/application.hbs" + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + helloWorld, + }), }); `); }); - test.skip('string literal passed to "modifier" keyword in content position', function () { + test('string literal passed to "modifier" keyword in content position', function () { let transform = configure({ staticModifiers: true, }); @@ -723,11 +726,70 @@ describe('compat-resolver', function () { import addListener from "../modifiers/add-listener.js"; import { precompileTemplate } from "@ember/template-compilation"; export default precompileTemplate("", { - moduleName: "my-app/templates/application.hbs" + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + addListener + }) + }); + `); + }); + test('modifier in bare mustache, no args', function () { + let transform = configure({ + staticModifiers: false, + }); + givenFile('modifiers/scroll-top.js'); + expect(transform('templates/application.hbs', `
Test
`)).toEqualCode(` + import { precompileTemplate } from "@ember/template-compilation"; + export default precompileTemplate("
Test
", { + moduleName: "my-app/templates/application.hbs", + }); + `); + }); + test('modifier in bare mustache, with args', function () { + let transform = configure({ + staticModifiers: false, + }); + givenFile('modifiers/scroll-top.js'); + expect(transform('templates/application.hbs', `
Test
`)).toEqualCode(` + import { precompileTemplate } from "@ember/template-compilation"; + export default precompileTemplate("
Test
", { + moduleName: "my-app/templates/application.hbs", + }); + `); + }); + test('modifier in bare mustache, no args', function () { + let transform = configure({ + staticModifiers: true, + }); + givenFile('modifiers/scroll-top.js'); + expect(transform('templates/application.hbs', `
Test
`)).toEqualCode(` + import scrollTop from "../modifiers/scroll-top.js"; + import { precompileTemplate } from "@ember/template-compilation"; + export default precompileTemplate("
Test
", { + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + scrollTop + }) }); `); }); - test.skip('modifier currying using the "modifier" keyword', function () { + test('modifier in bare mustache, with args', function () { + let transform = configure({ + staticModifiers: true, + }); + givenFile('modifiers/scroll-top.js'); + expect(transform('templates/application.hbs', `
Test
`)).toEqualCode(` + import scrollTop from "../modifiers/scroll-top.js"; + import { precompileTemplate } from "@ember/template-compilation"; + export default precompileTemplate("
Test
", { + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + scrollTop + }) + }); + `); + }); + test('modifier currying using the "modifier" keyword', function () { let transform = configure({ staticModifiers: true }); givenFile('modifiers/add-listener.js'); expect( @@ -743,7 +805,10 @@ describe('compat-resolver', function () { import addListener from "../modifiers/add-listener.js"; import { precompileTemplate } from "@ember/template-compilation"; export default precompileTemplate("{{#let (modifier addListener) as |addListener|}}\\n {{#let (modifier addListener \\"click\\") as |addClickListener|}}\\n \\n {{/let}}\\n {{/let}}", { - moduleName: "my-app/templates/application.hbs" + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + addListener + }) }); `); }); @@ -970,7 +1035,7 @@ describe('compat-resolver', function () { `); }); - test.skip('string literal passed to "helper" keyword in helper position', function () { + test('string literal passed to "helper" keyword in helper position', function () { let transform = configure({ staticHelpers: true }); givenFile('helpers/hello-world.js'); expect( @@ -983,14 +1048,17 @@ describe('compat-resolver', function () { ` ) ).toEqualCode(` - import HelloWorld from "../helpers/hello-world.js"; + import helloWorld from "../helpers/hello-world.js"; import { precompileTemplate } from "@ember/template-compilation"; - export default precompileTemplate("\\n {{#let (helper HelloWorld) as |helloWorld|}}\\n {{helloWorld}}\\n {{/let}}\\n ", { - moduleName: "my-app/templates/application.hbs" + export default precompileTemplate("\\n {{#let (helper helloWorld) as |helloWorld|}}\\n {{helloWorld}}\\n {{/let}}\\n ", { + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + helloWorld, + }), }); `); }); - test.skip('helper currying using the "helper" keyword', function () { + test('helper currying using the "helper" keyword', function () { let transform = configure({ staticHelpers: true }); givenFile('helpers/hello-world.js'); expect( @@ -1005,14 +1073,17 @@ describe('compat-resolver', function () { ` ) ).toEqualCode(` - import HelloWorld from "../helpers/hello-world.js"; + import helloWorld from "../helpers/hello-world.js"; import { precompileTemplate } from "@ember/template-compilation"; - export default precompileTemplate("\\n {{#let (helper HelloWorld name=\\"World\\") as |hello|}}\\n {{#let (helper hello name=\\"Tomster\\") as |helloTomster|}}\\n {{helloTomster name=\\"Zoey\\"}}\\n {{/let}}\\n {{/let}}\\n ", { - moduleName: "my-app/templates/application.hbs" + export default precompileTemplate("\\n {{#let (helper helloWorld name=\\"World\\") as |hello|}}\\n {{#let (helper hello name=\\"Tomster\\") as |helloTomster|}}\\n {{helloTomster name=\\"Zoey\\"}}\\n {{/let}}\\n {{/let}}\\n ", { + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + helloWorld, + }), }); `); }); - test.skip('string literal passed to "modifier" keyword in helper position', function () { + test('string literal passed to "modifier" keyword in helper position', function () { let transform = configure({ staticModifiers: true }); givenFile('modifiers/add-listener.js'); expect( @@ -1024,11 +1095,14 @@ describe('compat-resolver', function () { {{/let}} ` ) - ).toEqual(` - import AddListener from ../modifiers/add-listener.js; + ).toEqualCode(` + import addListener from "../modifiers/add-listener.js"; import { precompileTemplate } from "@ember/template-compilation"; - export default precompileTemplate("\\n {{#let (modifier AddListener \\"click\\") as |addClickListener|}}\\n \\n {{/let}}\\n ", { - moduleName: "my-app/templates/application.hbs" + export default precompileTemplate("\\n {{#let (modifier addListener \\"click\\") as |addClickListener|}}\\n \\n {{/let}}\\n ", { + moduleName: "my-app/templates/application.hbs", + scope: () => ({ + addListener + }), }); `); }); @@ -1039,13 +1113,13 @@ describe('compat-resolver', function () { transform('templates/application.hbs', `{{my-thing header=(component "hello-world") }}`); }).toThrow(new RegExp(`Missing component: hello-world in templates/application.hbs`)); }); - test.skip('string literal passed to "helper" keyword fails to resolve', function () { + test('string literal passed to "helper" keyword fails to resolve', function () { let transform = configure({ staticHelpers: true }); expect(() => { transform('templates/application.hbs', `{{helper "hello-world"}}`); }).toThrow(new RegExp(`Missing helper: hello-world in templates/application.hbs`)); }); - test.skip('string literal passed to "modifier" keyword fails to resolve', function () { + test('string literal passed to "modifier" keyword fails to resolve', function () { let transform = configure({ staticModifiers: true }); expect(() => { transform(