@@ -16,7 +16,9 @@ import { ALLOWED_GLOBALS } from '../src/scope-locals';
16
16
17
17
describe ( 'htmlbars-inline-precompile' , function ( ) {
18
18
// eslint-disable-next-line @typescript-eslint/no-var-requires
19
- let compiler : EmberTemplateCompiler = { ...require ( 'ember-source/dist/ember-template-compiler' ) } ;
19
+ let compiler : EmberTemplateCompiler = {
20
+ ...require ( 'ember-source/dist/ember-template-compiler.js' ) ,
21
+ } ;
20
22
let plugins : ( [ typeof HTMLBarsInlinePrecompile , Options ] | [ unknown ] ) [ ] ;
21
23
22
24
async function transform ( code : string ) {
@@ -392,7 +394,7 @@ describe('htmlbars-inline-precompile', function () {
392
394
*/
393
395
{
394
396
id: "<id>",
395
- block: "[[[8,[32,0],null,null,null]],[],false, []]",
397
+ block: "[[[8,[32,0],null,null,null]],[],[]]",
396
398
moduleName: "<moduleName>",
397
399
scope: () => [Setup],
398
400
isStrictMode: true,
@@ -797,7 +799,7 @@ describe('htmlbars-inline-precompile', function () {
797
799
*/
798
800
{
799
801
id: "<id>",
800
- block: '[[[8,[39,0],null,[["@text"],[[32,0]]],null]],[],false, ["message"]]',
802
+ block: '[[[8,[39,0],null,[["@text"],[[32,0]]],null]],[],["message"]]',
801
803
moduleName: "<moduleName>",
802
804
scope: () => [two],
803
805
isStrictMode: false,
@@ -1694,7 +1696,7 @@ describe('htmlbars-inline-precompile', function () {
1694
1696
*/
1695
1697
{
1696
1698
id: "<id>",
1697
- block: "[[[8,[32,0],null,null,null]],[],false, []]",
1699
+ block: "[[[8,[32,0],null,null,null]],[],[]]",
1698
1700
moduleName: "<moduleName>",
1699
1701
scope: () => [HelloWorld],
1700
1702
isStrictMode: true,
@@ -1740,7 +1742,7 @@ describe('htmlbars-inline-precompile', function () {
1740
1742
*/
1741
1743
{
1742
1744
id: "<id>",
1743
- block: "[[[8,[32,0],null,null,null]],[],false, []]",
1745
+ block: "[[[8,[32,0],null,null,null]],[],[]]",
1744
1746
moduleName: "<moduleName>",
1745
1747
scope: () => [HelloWorld],
1746
1748
isStrictMode: true,
@@ -1824,7 +1826,7 @@ describe('htmlbars-inline-precompile', function () {
1824
1826
*/
1825
1827
{
1826
1828
id: "<id>",
1827
- block: "[[[8,[32,0],null,null,null],[8,[32,1],null,null,null]],[],false, []]",
1829
+ block: "[[[8,[32,0],null,null,null],[8,[32,1],null,null,null]],[],[]]",
1828
1830
moduleName: "<moduleName>",
1829
1831
scope: () => [bar, MyButton],
1830
1832
isStrictMode: false,
@@ -1872,6 +1874,34 @@ describe('htmlbars-inline-precompile', function () {
1872
1874
` ) ;
1873
1875
expect ( spy . firstCall . lastArg ) . toHaveProperty ( 'locals' , [ 'bar' ] ) ;
1874
1876
} ) ;
1877
+
1878
+ it ( 'can pass lexically scoped "this"' , async function ( ) {
1879
+ let spy = sinon . spy ( compiler , 'precompile' ) ;
1880
+ let transformed = await transform ( `
1881
+ import { precompileTemplate } from '@ember/template-compilation';
1882
+ export function example() {
1883
+ return precompileTemplate('{{this.message}}', { scope: () => ({ "this": this }) });
1884
+ }
1885
+ ` ) ;
1886
+ expect ( spy . firstCall . lastArg ) . toHaveProperty ( 'locals' , [ 'this' ] ) ;
1887
+ expect ( normalizeWireFormat ( transformed ) ) . toEqualCode ( `
1888
+ import { createTemplateFactory } from "@ember/template-factory";
1889
+ export function example() {
1890
+ return createTemplateFactory(
1891
+ /*
1892
+ {{this.message}}
1893
+ */
1894
+ {
1895
+ id: "<id>",
1896
+ block: '[[[1,[32,0,["message"]]]],[],[]]',
1897
+ moduleName: "<moduleName>",
1898
+ scope: () => [this],
1899
+ isStrictMode: false,
1900
+ }
1901
+ );
1902
+ }
1903
+ ` ) ;
1904
+ } ) ;
1875
1905
} ) ;
1876
1906
1877
1907
describe ( 'implicit-scope-form' , function ( ) {
@@ -1991,6 +2021,136 @@ describe('htmlbars-inline-precompile', function () {
1991
2021
` ) ;
1992
2022
} ) ;
1993
2023
2024
+ it ( 'captures lexical "this" in mustache when template is used as an expression' , async function ( ) {
2025
+ plugins = [
2026
+ [
2027
+ HTMLBarsInlinePrecompile ,
2028
+ {
2029
+ compiler,
2030
+ targetFormat : 'hbs' ,
2031
+ } ,
2032
+ ] ,
2033
+ ] ;
2034
+
2035
+ let transformed = await transform (
2036
+ `import { template } from '@ember/template-compiler';
2037
+ function upper(s) { return s.toUpperCase() }
2038
+ export function exampleTest() {
2039
+ this.message = "hello";
2040
+ render(template('{{upper this.message}}', { eval: function() { return eval(arguments[0]) } }))
2041
+ }
2042
+ `
2043
+ ) ;
2044
+
2045
+ expect ( transformed ) . toEqualCode ( `
2046
+ import { precompileTemplate } from "@ember/template-compilation";
2047
+ import { setComponentTemplate } from "@ember/component";
2048
+ import templateOnly from "@ember/component/template-only";
2049
+ function upper(s) {
2050
+ return s.toUpperCase();
2051
+ }
2052
+ export function exampleTest() {
2053
+ this.message = "hello";
2054
+ render(
2055
+ setComponentTemplate(
2056
+ precompileTemplate("{{upper this.message}}", {
2057
+ strictMode: true,
2058
+ scope: () => ({
2059
+ upper,
2060
+ this: this,
2061
+ }),
2062
+ }),
2063
+ templateOnly()
2064
+ )
2065
+ );
2066
+ }
2067
+ ` ) ;
2068
+ } ) ;
2069
+
2070
+ it ( 'captures lexical "this" in Element when template is used as an expression' , async function ( ) {
2071
+ plugins = [
2072
+ [
2073
+ HTMLBarsInlinePrecompile ,
2074
+ {
2075
+ compiler,
2076
+ targetFormat : 'hbs' ,
2077
+ } ,
2078
+ ] ,
2079
+ ] ;
2080
+
2081
+ let transformed = await transform (
2082
+ `import { template } from '@ember/template-compiler';
2083
+ import SomeComponent from './elsewhere.js';
2084
+ export function exampleTest() {
2085
+ this.message = SomeComponent;
2086
+ render(template('<this.message />', { eval: function() { return eval(arguments[0]) } }))
2087
+ }
2088
+ `
2089
+ ) ;
2090
+
2091
+ expect ( transformed ) . toEqualCode ( `
2092
+ import SomeComponent from './elsewhere.js';
2093
+ import { precompileTemplate } from "@ember/template-compilation";
2094
+ import { setComponentTemplate } from "@ember/component";
2095
+ import templateOnly from "@ember/component/template-only";
2096
+ export function exampleTest() {
2097
+ this.message = SomeComponent;
2098
+ render(
2099
+ setComponentTemplate(
2100
+ precompileTemplate("<this.message />", {
2101
+ strictMode: true,
2102
+ scope: () => ({
2103
+ this: this,
2104
+ }),
2105
+ }),
2106
+ templateOnly()
2107
+ )
2108
+ );
2109
+ }
2110
+ ` ) ;
2111
+ } ) ;
2112
+
2113
+ it ( 'does not captures lexical "this" when template is used in class body' , async function ( ) {
2114
+ plugins = [
2115
+ [
2116
+ HTMLBarsInlinePrecompile ,
2117
+ {
2118
+ compiler,
2119
+ targetFormat : 'hbs' ,
2120
+ } ,
2121
+ ] ,
2122
+ ] ;
2123
+
2124
+ let transformed = await transform (
2125
+ `import { template } from '@ember/template-compiler';
2126
+ import Component from '@glimmer/component';
2127
+ export class Example extends Component {
2128
+ upper(s) { return s.toUpperCase() }
2129
+ message = "hi";
2130
+ static {
2131
+ template('{{this.upper this.message}}', { component: this, eval: function() { return eval(arguments[0]) } })
2132
+ }
2133
+ }
2134
+ `
2135
+ ) ;
2136
+
2137
+ expect ( transformed ) . toEqualCode ( `
2138
+ import Component from '@glimmer/component';
2139
+ import { precompileTemplate } from "@ember/template-compilation";
2140
+ import { setComponentTemplate } from "@ember/component";
2141
+ export class Example extends Component {
2142
+ upper(s) { return s.toUpperCase() }
2143
+ message = "hi";
2144
+ static {
2145
+ setComponentTemplate(
2146
+ precompileTemplate("{{this.upper this.message}}", {
2147
+ strictMode: true,
2148
+ }), this)
2149
+ }
2150
+ }
2151
+ ` ) ;
2152
+ } ) ;
2153
+
1994
2154
it ( 'leaves ember keywords alone when no local is defined' , async function ( ) {
1995
2155
plugins = [
1996
2156
[
@@ -2046,7 +2206,7 @@ describe('htmlbars-inline-precompile', function () {
2046
2206
*/
2047
2207
{
2048
2208
id: "<id>",
2049
- block: "[[[8,[32,0],null,null,null]],[],false, []]",
2209
+ block: "[[[8,[32,0],null,null,null]],[],[]]",
2050
2210
moduleName: "<moduleName>",
2051
2211
scope: () => [HelloWorld],
2052
2212
isStrictMode: true,
@@ -2159,7 +2319,7 @@ describe('htmlbars-inline-precompile', function () {
2159
2319
*/
2160
2320
{
2161
2321
id: "<id>",
2162
- block: "[[[8,[32,0],null,null,null]],[],false, []]",
2322
+ block: "[[[8,[32,0],null,null,null]],[],[]]",
2163
2323
moduleName: "<moduleName>",
2164
2324
scope: () => [HelloWorld],
2165
2325
isStrictMode: true,
@@ -2202,6 +2362,39 @@ describe('htmlbars-inline-precompile', function () {
2202
2362
` ) ;
2203
2363
} ) ;
2204
2364
2365
+ it ( 'expression form can capture lexical "this"' , async function ( ) {
2366
+ plugins = [
2367
+ [
2368
+ HTMLBarsInlinePrecompile ,
2369
+ {
2370
+ compiler,
2371
+ targetFormat : 'hbs' ,
2372
+ } ,
2373
+ ] ,
2374
+ ] ;
2375
+
2376
+ let p = new Preprocessor ( ) ;
2377
+
2378
+ let transformed = await transform (
2379
+ p . process (
2380
+ `
2381
+ export function example() {
2382
+ return <template>{{this.message}}</template>;
2383
+ }
2384
+ `
2385
+ )
2386
+ ) ;
2387
+
2388
+ expect ( transformed ) . toEqualCode ( `
2389
+ import { precompileTemplate } from "@ember/template-compilation";
2390
+ import { setComponentTemplate } from "@ember/component";
2391
+ import templateOnly from "@ember/component/template-only";
2392
+ export function example() {
2393
+ return setComponentTemplate(precompileTemplate('{{this.message}}', { strictMode: true, scope: () => ({ this: this }) }), templateOnly());
2394
+ }
2395
+ ` ) ;
2396
+ } ) ;
2397
+
2205
2398
it ( 'works for class member form' , async function ( ) {
2206
2399
plugins = [
2207
2400
[
0 commit comments