diff --git a/packages/@glimmer/manager/lib/internal/defaults.ts b/packages/@glimmer/manager/lib/internal/defaults.ts new file mode 100644 index 0000000000..0a698ba064 --- /dev/null +++ b/packages/@glimmer/manager/lib/internal/defaults.ts @@ -0,0 +1,36 @@ +import { CAPABILITIES, CapturedArguments as Arguments } from '@glimmer/interfaces'; + +type FnArgs = + | [...Args['positional'], Args['named']] + | [...Args['positional'], {}]; + +interface FunctionHelperState { + fn: (...args: FnArgs) => Return; + args: Args; +} + +export class FunctionHelperManager { + capabilities = { + [CAPABILITIES]: true, + hasValue: true, + hasDestroyable: false, + hasScheduledEffect: false, + } as const; + + createHelper(fn: State['fn'], args: State['args']) { + return { fn, args }; + } + + getValue({ fn, args }: State) { + let argsForFn: FnArgs = [ + ...args.positional, + Object.keys(args.named).length > 0 ? args.named : {}, + ]; + + return fn(...argsForFn); + } + + getDebugName(fn: State['fn']) { + return fn.name || '(anonymous function)'; + } +} diff --git a/packages/@glimmer/manager/lib/internal/index.ts b/packages/@glimmer/manager/lib/internal/index.ts index d4e485a627..d71615ce0b 100644 --- a/packages/@glimmer/manager/lib/internal/index.ts +++ b/packages/@glimmer/manager/lib/internal/index.ts @@ -7,6 +7,7 @@ import { Owner, } from '@glimmer/interfaces'; import { CustomHelperManager } from '../public/helper'; +import { FunctionHelperManager } from './defaults'; type InternalManager = | InternalComponentManager @@ -138,7 +139,18 @@ export function getInternalHelperManager( ); } - const manager = getManager(HELPER_MANAGERS, definition)!; + let manager = getManager(HELPER_MANAGERS, definition)!; + + // Functions are special-cased because functions are defined + // as the "default" helper, per: https://github.com/emberjs/rfcs/pull/756 + if (manager === undefined && typeof definition === 'function') { + setInternalHelperManager( + new CustomHelperManager(() => new FunctionHelperManager()), + definition + ); + + manager = getManager(HELPER_MANAGERS, definition)!; + } if (manager === undefined) { if (isOptional === true) {