Skip to content

Commit

Permalink
[FEATURE EMBER_GLIMMER_FN_HELPER] Initial implementation of fn helper.
Browse files Browse the repository at this point in the history
  • Loading branch information
rwjblue committed Apr 17, 2019
1 parent 6f3ea5a commit 33ffc23
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
18 changes: 18 additions & 0 deletions packages/@ember/-internals/glimmer/lib/helpers/fn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Arguments, VM } from '@glimmer/runtime';
import { InternalHelperReference } from '../utils/references';
import { ICapturedArguments } from '@glimmer/runtime/dist/types/lib/vm/arguments';
import { assert } from '@ember/debug';

function fnHelper({ positional }: ICapturedArguments) {
assert(`You must pass a function as the \`fn\` helpers first argument, you passed ${positional.at(0).value()}`, typeof positional.at(0).value() === 'function');

return () => {
let [fn, ...args] = positional.value();

return fn!['apply'](null, args);
};
}

export default function(_vm: VM, args: Arguments) {
return new InternalHelperReference(fnHelper, args.capture());
}
17 changes: 13 additions & 4 deletions packages/@ember/-internals/glimmer/lib/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { LookupOptions, Owner, setOwner } from '@ember/-internals/owner';
import { lookupComponent, lookupPartial, OwnedTemplateMeta } from '@ember/-internals/views';
import {
EMBER_GLIMMER_ANGLE_BRACKET_BUILT_INS,
EMBER_GLIMMER_FN_HELPER,
EMBER_MODULE_UNIFICATION,
} from '@ember/canary-features';
import { assert } from '@ember/debug';
Expand Down Expand Up @@ -32,6 +33,7 @@ import { default as action } from './helpers/action';
import { default as array } from './helpers/array';
import { default as concat } from './helpers/concat';
import { default as eachIn } from './helpers/each-in';
import { default as fn } from './helpers/fn';
import { default as get } from './helpers/get';
import { default as hash } from './helpers/hash';
import { inlineIf, inlineUnless } from './helpers/if-unless';
Expand Down Expand Up @@ -61,7 +63,11 @@ function makeOptions(moduleName: string, namespace?: string): LookupOptions {
};
}

const BUILTINS_HELPERS = {
interface IBuiltInHelpers {
[name: string]: Helper | undefined;
}

const BUILTINS_HELPERS: IBuiltInHelpers = {
if: inlineIf,
action,
array,
Expand All @@ -82,8 +88,13 @@ const BUILTINS_HELPERS = {
'-mount': mountHelper,
'-outlet': outletHelper,
'-assert-implicit-component-helper-argument': componentAssertionHelper,
fn: undefined
};

if (EMBER_GLIMMER_FN_HELPER) {
BUILTINS_HELPERS.fn = fn;
}

const BUILTIN_MODIFIERS = {
action: { manager: new ActionModifierManager(), state: null },
};
Expand All @@ -96,9 +107,7 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
];
private objToHandle = new WeakMap<any, number>();

private builtInHelpers: {
[name: string]: Helper | undefined;
} = BUILTINS_HELPERS;
private builtInHelpers: IBuiltInHelpers = BUILTINS_HELPERS;

private builtInModifiers: {
[name: string]: ModifierDefinition;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { EMBER_GLIMMER_FN_HELPER } from '@ember/canary-features';
import { RenderingTestCase, moduleFor, runTask } from 'internal-test-helpers';

import { set } from '@ember/-internals/metal';

if (EMBER_GLIMMER_FN_HELPER) {
moduleFor(
'Helpers test: {{fn}}',
class extends RenderingTestCase {
beforeEach() {
this.registerHelper('invoke', function([fn]) {
return fn();
});
}

'@test invokes the provided function with arguments'() {
this.render(`{{invoke (fn this.myFunc this.arg1 this.arg2)}}`, {
myFunc(arg1, arg2) {
return `arg1: ${arg1}, arg2: ${arg2}`;
},

arg1: 'foo',
arg2: 'bar',
});

this.assertText('arg1: foo, arg2: bar');

this.assertStableRerender();

runTask(() => set(this.context, 'arg1', 'qux'));
this.assertText('arg1: qux, arg2: bar');

runTask(() => set(this.context, 'arg2', 'derp'));
this.assertText('arg1: qux, arg2: derp');

runTask(() => {
set(this.context, 'arg1', 'foo');
set(this.context, 'arg2', 'bar');
});

this.assertText('arg1: foo, arg2: bar');
}

'@test asserts if the first argument is not a function'() {
expectAssertion(() => {
this.render(`{{invoke (fn this.myFunc this.arg1 this.arg2)}}`, {
myFunc: null,
arg1: 'foo',
arg2: 'bar',
});
}, /You must pass a function as the `fn` helpers first argument, you passed null/);
}
}
);
}
2 changes: 2 additions & 0 deletions packages/@ember/canary-features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const DEFAULT_FEATURES = {
EMBER_GLIMMER_ANGLE_BRACKET_NESTED_LOOKUP: true,
EMBER_ROUTING_BUILD_ROUTEINFO_METADATA: true,
EMBER_NATIVE_DECORATOR_SUPPORT: true,
EMBER_GLIMMER_FN_HELPER: null,
};

/**
Expand Down Expand Up @@ -88,3 +89,4 @@ export const EMBER_ROUTING_BUILD_ROUTEINFO_METADATA = featureValue(
FEATURES.EMBER_ROUTING_BUILD_ROUTEINFO_METADATA
);
export const EMBER_NATIVE_DECORATOR_SUPPORT = featureValue(FEATURES.EMBER_NATIVE_DECORATOR_SUPPORT);
export const EMBER_GLIMMER_FN_HELPER = featureValue(FEATURES.EMBER_GLIMMER_FN_HELPER);

0 comments on commit 33ffc23

Please sign in to comment.