declare module '@ember/template-compiler/lib/template' { import { type TemplateOnlyComponent } from '@ember/component/template-only'; type ComponentClass = abstract new (...args: any[]) => object; /** * All possible options passed to `template()` may specify a `moduleName`. */ export interface BaseTemplateOptions { moduleName?: string; /** * Whether the template should be treated as a strict-mode template. Defaults * to `true`. */ strictMode?: boolean; } /** * When using `template` in a class, you call it in a `static` block and pass * the class as the `component` option. * * ```ts * class MyComponent extends Component { * static { * template('{{this.greeting}}, {{@place}}!', * { component: this }, * // explicit or implicit option goes here * ); * } * } * ``` * * For the full explicit form, see {@linkcode ExplicitClassOptions}. For the * full implicit form, see {@linkcode ImplicitClassOptions}. */ export interface BaseClassTemplateOptions extends BaseTemplateOptions { component: C; } /** * When using `template` outside of a class (i.e. a "template-only component"), you can pass * a `scope` option that explicitly provides the lexical scope for the template. * * This is called the "explicit form". * * ```ts * const greeting = 'Hello'; * const HelloWorld = template('{{greeting}} World!', { scope: () => ({ greeting }) }); * ``` */ export interface ExplicitTemplateOnlyOptions extends BaseTemplateOptions { scope(): Record; } /** * When using `template` *inside* a class (see * {@linkcode BaseClassTemplateOptions}), you can pass a `scope` option that * explicitly provides the lexical scope for the template, just like a template-only * component (see {@linkcode ExplicitTemplateOnlyOptions}). * * ```ts * class MyComponent extends Component { * static { * template('{{this.greeting}}, {{@place}}!', * { component: this }, * // explicit or implicit option goes here * ); * } * } * ``` * * ## The Scope Function's `instance` Parameter * * However, the explicit `scope` function in a *class* also takes an `instance` option * that provides access to the component's instance. * * Once it's supported in Handlebars, this will make it possible to represent private * fields when using the explicit form. * * ```ts * class MyComponent extends Component { * static { * template('{{this.#greeting}}, {{@place}}!', * { component: this }, * scope: (instance) => ({ '#greeting': instance.#greeting }), * ); * } * } * ``` */ export interface ExplicitClassOptions extends BaseClassTemplateOptions { scope(instance?: InstanceType): Record; } /** * The *implicit* form of the `template` function takes an `eval` option that * allows the runtime compiler to evaluate local template variables without * needing to maintain an explicit list of the local variables used in the * template scope. * * The eval options *must* be passed in the following form: * * ```ts * { * eval() { return eval(arguments[0]) } * } * ``` * * ## Requirements of the `eval` Option * * **The syntactic form presented above is the only form you should use when * passing an `eval` option.** * * This is _required_ if you want your code to be compatible with the * compile-time implementation of `@ember/template-compiler`. While the runtime * compiler offers a tiny bit of additional wiggle room, you still need to follow * very strict rules. * * We don't recommend trying to memorize the rules. Instead, we recommend using * the snippet presented above and supported by the compile-time implementation. * * ### The Technical Requirements of the `eval` Option * * The `eval` function is passed a single parameter that is a JavaScript * identifier. This will be extended in the future to support private fields. * * Since keywords in JavaScript are contextual (e.g. `await` and `yield`), the * parameter might be a keyword. The `@ember/template-compiler/runtime` expects * the function to throw a `SyntaxError` if the identifier name is not valid in * the current scope. (The direct `eval` function takes care of this out of the * box.) * * Requirements: * * 1. The `eval` method must receive its parameter as `arguments[0]`, which * ensures that the variable name passed to `eval()` is not shadowed by the * function's parameter name. * 2. The `eval` option must be a function or concise method, and not an arrow. * This is because arrows do not have their own `arguments`, which breaks * (1). * 3. The `eval` method must call "*direct* `eval`", and not an alias of `eval`. * Direct `eval` evaluates the code in the scope it was called from, while * aliased versions of `eval` (including `new Function`) evaluate the code in * the global scope. * 4. The `eval` method must return the result of calling "direct `eval`". * * The easiest way to achieve these requirements is to use the exact syntax * presented above. This is *also* the only way to be compatible * * ## Rationale * * This is useful for two reasons: * * 1. This form is a useful _intermediate_ form for the compile-time toolchain. * It allows the content-tag preprocessor to convert the `