Skip to content

Commit

Permalink
Implementation for RFC #756
Browse files Browse the repository at this point in the history
  • Loading branch information
NullVoxPopuli committed Nov 10, 2021
1 parent 0ac3cdf commit cee1965
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
37 changes: 37 additions & 0 deletions packages/@glimmer/manager/lib/internal/defaults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { buildCapabilities } from '../util/capabilities';

import type { CapturedArguments as Arguments, HelperCapabilities } from '@glimmer/interfaces';

type FnArgs<Args extends Arguments = Arguments> =
| [...Args['positional'], Args['named']]
| [...Args['positional'], {}];

interface FunctionHelperState<Args extends Arguments = Arguments> {
fn: <Return>(...args: FnArgs<Args>) => Return;
args: Args;
}

export class FunctionHelperManager<State extends FunctionHelperState> {
capabilities = buildCapabilities({
hasValue: true,
hasDestroyable: false,
hasScheduledEffect: false,
}) as HelperCapabilities;

createHelper(fn: State['fn'], args: State['args']) {
return { fn, args };
}

getValue({ fn, args }: State) {
let argsForFn: FnArgs<Arguments> = [
...args.positional,
Object.keys(args.named).length > 0 ? args.named : {},
];

return fn(...argsForFn);
}

getDebugName(fn: State['fn']) {
return fn.name || '(anonymous function)';
}
}
14 changes: 13 additions & 1 deletion packages/@glimmer/manager/lib/internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Owner,
} from '@glimmer/interfaces';
import { CustomHelperManager } from '../public/helper';
import { FunctionHelperManager } from './defaults';

type InternalManager =
| InternalComponentManager
Expand Down Expand Up @@ -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) {
Expand Down
9 changes: 8 additions & 1 deletion packages/@glimmer/manager/test/managers-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,18 @@ module('Managers', () => {
assert.ok(typeof instance === 'object', 'manager is an internal manager');
assert.ok(
typeof instance.getHelper({}) === 'function',
'manager can generatew helper function'
'manager can generate helper function'
);
assert.equal(instance['factory'], factory, 'manager has correct delegate factory');
});

test('it determines the default manager', (assert) => {
let helper = () => 0;
let instance = getInternalHelperManager(helper);

assert.ok(instance, helper as any);
});

test('it works with internal helpers', (assert) => {
let helper = () => {
return UNDEFINED_REFERENCE;
Expand Down

0 comments on commit cee1965

Please sign in to comment.