UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

103 lines (85 loc) 11.3 kB
import { DEBUG } from '@glimmer/env'; import { createComputeRef, isInvokableRef, updateRef, valueForRef } from '@glimmer/reference'; import { reifyPositional } from '@glimmer/runtime'; import { buildUntouchableThis } from '@glimmer/util'; import { internalHelper } from './internal-helper'; var context = buildUntouchableThis('`fn` helper'); /** The `fn` helper allows you to ensure a function that you are passing off to another component, helper, or modifier has access to arguments that are available in the template. For example, if you have an `each` helper looping over a number of items, you may need to pass a function that expects to receive the item as an argument to a component invoked within the loop. Here's how you could use the `fn` helper to pass both the function and its arguments together: ```app/templates/components/items-listing.hbs {{#each @items as |item|}} <DisplayItem @item=item @select={{fn this.handleSelected item}} /> {{/each}} ``` ```app/components/items-list.js import Component from '@glimmer/component'; import { action } from '@ember/object'; export default class ItemsList extends Component { handleSelected = (item) => { // ...snip... } } ``` In this case the `display-item` component will receive a normal function that it can invoke. When it invokes the function, the `handleSelected` function will receive the `item` and any arguments passed, thanks to the `fn` helper. Let's take look at what that means in a couple circumstances: - When invoked as `this.args.select()` the `handleSelected` function will receive the `item` from the loop as its first and only argument. - When invoked as `this.args.select('foo')` the `handleSelected` function will receive the `item` from the loop as its first argument and the string `'foo'` as its second argument. In the example above, we used an arrow function to ensure that `handleSelected` is properly bound to the `items-list`, but let's explore what happens if we left out the arrow function: ```app/components/items-list.js import Component from '@glimmer/component'; export default class ItemsList extends Component { handleSelected(item) { // ...snip... } } ``` In this example, when `handleSelected` is invoked inside the `display-item` component, it will **not** have access to the component instance. In other words, it will have no `this` context, so please make sure your functions are bound (via an arrow function or other means) before passing into `fn`! See also [partial application](https://en.wikipedia.org/wiki/Partial_application). @method fn @public */ export default internalHelper(function (_ref) { var positional = _ref.positional; var callbackRef = positional[0]; if (DEBUG) assertCallbackIsFn(callbackRef); return createComputeRef(function () { return function () { var _reifyPositional = reifyPositional(positional), fn = _reifyPositional[0], args = _reifyPositional.slice(1); if (DEBUG) assertCallbackIsFn(callbackRef); for (var _len = arguments.length, invocationArgs = new Array(_len), _key = 0; _key < _len; _key++) { invocationArgs[_key] = arguments[_key]; } if (isInvokableRef(callbackRef)) { var value = args.length > 0 ? args[0] : invocationArgs[0]; return updateRef(callbackRef, value); } else { return fn.call.apply(fn, [context].concat(args, invocationArgs)); } }; }, null, 'fn'); }); function assertCallbackIsFn(callbackRef) { if (!(callbackRef && (isInvokableRef(callbackRef) || typeof valueForRef(callbackRef) === 'function'))) { throw new Error("You must pass a function as the `fn` helper's first argument, you passed " + (callbackRef ? valueForRef(callbackRef) : callbackRef) + ". While rendering:\n\n" + (callbackRef === null || callbackRef === void 0 ? void 0 : callbackRef.debugLabel)); } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL2hlbHBlcnMvZm4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FBQSxLQUFBLFFBQUEsY0FBQTtBQUVBLFNBQUEsZ0JBQUEsRUFBQSxjQUFBLEVBQUEsU0FBQSxFQUFBLFdBQUEsUUFBQSxvQkFBQTtBQU9BLFNBQUEsZUFBQSxRQUFBLGtCQUFBO0FBQ0EsU0FBQSxvQkFBQSxRQUFBLGVBQUE7QUFDQSxTQUFBLGNBQUEsUUFBQSxtQkFBQTtBQUVBLElBQU0sT0FBTyxHQUFHLG9CQUFvQixDQUFwQyxhQUFvQyxDQUFwQztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdFQSxlQUFlLGNBQWMsQ0FBQyxnQkFBc0M7QUFBQSxNQUFuQyxVQUFtQyxRQUFuQyxVQUFtQztBQUNsRSxNQUFJLFdBQVcsR0FBRyxVQUFVLENBQTVCLENBQTRCLENBQTVCO0FBRUEsTUFBQSxLQUFBLEVBQVcsa0JBQWtCLENBQWxCLFdBQWtCLENBQWxCO0FBRVgsU0FBTyxnQkFBZ0IsQ0FDckIsWUFBSztBQUNILFdBQU8sWUFBaUM7QUFBQSw2QkFDbEIsZUFBZSxDQUFuQyxVQUFtQyxDQURHO0FBQUEsVUFDbEMsRUFEa0M7QUFBQSxVQUNsQyxJQURrQzs7QUFHdEMsVUFBQSxLQUFBLEVBQVcsa0JBQWtCLENBQWxCLFdBQWtCLENBQWxCOztBQUgyQix3Q0FBakMsY0FBaUM7QUFBakMsUUFBQSxjQUFpQztBQUFBOztBQUt0QyxVQUFJLGNBQWMsQ0FBbEIsV0FBa0IsQ0FBbEIsRUFBaUM7QUFDL0IsWUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFKLE1BQUEsR0FBQSxDQUFBLEdBQWtCLElBQUksQ0FBdEIsQ0FBc0IsQ0FBdEIsR0FBNEIsY0FBYyxDQUF0RCxDQUFzRCxDQUF0RDtBQUNBLGVBQU8sU0FBUyxDQUFBLFdBQUEsRUFBaEIsS0FBZ0IsQ0FBaEI7QUFGRixPQUFBLE1BR087QUFDTCxlQUFRLEVBQWUsQ0FBZixJQUFBLE9BQUEsRUFBZSxHQUFmLE9BQWUsU0FBZixJQUFlLEVBQXZCLGNBQXVCLEVBQXZCO0FBQ0Q7QUFWSCxLQUFBO0FBRm1CLEdBQUEsRUFBQSxJQUFBLEVBQXZCLElBQXVCLENBQXZCO0FBTEYsQ0FBNkIsQ0FBN0I7O0FBeUJBLFNBQUEsa0JBQUEsQ0FBQSxXQUFBLEVBQWtEO0FBQ2hELE1BQ0UsRUFDRSxXQUFXLEtBQ1YsY0FBYyxDQUFkLFdBQWMsQ0FBZCxJQUErQixPQUFPLFdBQVcsQ0FBbEIsV0FBa0IsQ0FBbEIsS0FIcEMsVUFFZSxDQURiLENBREYsRUFLRTtBQUNBLFVBQU0sSUFBQSxLQUFBLGdGQUVGLFdBQVcsR0FBRyxXQUFXLENBQWQsV0FBYyxDQUFkLEdBQThCLFdBRnZDLGdDQUdxQixXQUFXLEtBQVgsSUFBQSxJQUFBLFdBQVcsS0FBQSxLQUFYLENBQUEsR0FBVyxLQUFYLENBQUEsR0FBQSxXQUFXLENBSHRDLFVBQU0sRUFBTjtBQUtEO0FBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBERUJVRyB9IGZyb20gJ0BnbGltbWVyL2Vudic7XG5pbXBvcnQgeyBDYXB0dXJlZEFyZ3VtZW50cyB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlQ29tcHV0ZVJlZixcbiAgaXNJbnZva2FibGVSZWYsXG4gIFJlZmVyZW5jZSxcbiAgdXBkYXRlUmVmLFxuICB2YWx1ZUZvclJlZixcbn0gZnJvbSAnQGdsaW1tZXIvcmVmZXJlbmNlJztcbmltcG9ydCB7IHJlaWZ5UG9zaXRpb25hbCB9IGZyb20gJ0BnbGltbWVyL3J1bnRpbWUnO1xuaW1wb3J0IHsgYnVpbGRVbnRvdWNoYWJsZVRoaXMgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IGludGVybmFsSGVscGVyIH0gZnJvbSAnLi9pbnRlcm5hbC1oZWxwZXInO1xuXG5jb25zdCBjb250ZXh0ID0gYnVpbGRVbnRvdWNoYWJsZVRoaXMoJ2BmbmAgaGVscGVyJyk7XG5cbi8qKlxuICBUaGUgYGZuYCBoZWxwZXIgYWxsb3dzIHlvdSB0byBlbnN1cmUgYSBmdW5jdGlvbiB0aGF0IHlvdSBhcmUgcGFzc2luZyBvZmZcbiAgdG8gYW5vdGhlciBjb21wb25lbnQsIGhlbHBlciwgb3IgbW9kaWZpZXIgaGFzIGFjY2VzcyB0byBhcmd1bWVudHMgdGhhdCBhcmVcbiAgYXZhaWxhYmxlIGluIHRoZSB0ZW1wbGF0ZS5cblxuICBGb3IgZXhhbXBsZSwgaWYgeW91IGhhdmUgYW4gYGVhY2hgIGhlbHBlciBsb29waW5nIG92ZXIgYSBudW1iZXIgb2YgaXRlbXMsIHlvdVxuICBtYXkgbmVlZCB0byBwYXNzIGEgZnVuY3Rpb24gdGhhdCBleHBlY3RzIHRvIHJlY2VpdmUgdGhlIGl0ZW0gYXMgYW4gYXJndW1lbnRcbiAgdG8gYSBjb21wb25lbnQgaW52b2tlZCB3aXRoaW4gdGhlIGxvb3AuIEhlcmUncyBob3cgeW91IGNvdWxkIHVzZSB0aGUgYGZuYFxuICBoZWxwZXIgdG8gcGFzcyBib3RoIHRoZSBmdW5jdGlvbiBhbmQgaXRzIGFyZ3VtZW50cyB0b2dldGhlcjpcblxuICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9pdGVtcy1saXN0aW5nLmhic1xuICB7eyNlYWNoIEBpdGVtcyBhcyB8aXRlbXx9fVxuICAgIDxEaXNwbGF5SXRlbSBAaXRlbT1pdGVtIEBzZWxlY3Q9e3tmbiB0aGlzLmhhbmRsZVNlbGVjdGVkIGl0ZW19fSAvPlxuICB7ey9lYWNofX1cbiAgYGBgXG5cbiAgYGBgYXBwL2NvbXBvbmVudHMvaXRlbXMtbGlzdC5qc1xuICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BnbGltbWVyL2NvbXBvbmVudCc7XG4gIGltcG9ydCB7IGFjdGlvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QnO1xuXG4gIGV4cG9ydCBkZWZhdWx0IGNsYXNzIEl0ZW1zTGlzdCBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgaGFuZGxlU2VsZWN0ZWQgPSAoaXRlbSkgPT4ge1xuICAgICAgLy8gLi4uc25pcC4uLlxuICAgIH1cbiAgfVxuICBgYGBcblxuICBJbiB0aGlzIGNhc2UgdGhlIGBkaXNwbGF5LWl0ZW1gIGNvbXBvbmVudCB3aWxsIHJlY2VpdmUgYSBub3JtYWwgZnVuY3Rpb25cbiAgdGhhdCBpdCBjYW4gaW52b2tlLiBXaGVuIGl0IGludm9rZXMgdGhlIGZ1bmN0aW9uLCB0aGUgYGhhbmRsZVNlbGVjdGVkYFxuICBmdW5jdGlvbiB3aWxsIHJlY2VpdmUgdGhlIGBpdGVtYCBhbmQgYW55IGFyZ3VtZW50cyBwYXNzZWQsIHRoYW5rcyB0byB0aGVcbiAgYGZuYCBoZWxwZXIuXG5cbiAgTGV0J3MgdGFrZSBsb29rIGF0IHdoYXQgdGhhdCBtZWFucyBpbiBhIGNvdXBsZSBjaXJjdW1zdGFuY2VzOlxuXG4gIC0gV2hlbiBpbnZva2VkIGFzIGB0aGlzLmFyZ3Muc2VsZWN0KClgIHRoZSBgaGFuZGxlU2VsZWN0ZWRgIGZ1bmN0aW9uIHdpbGxcbiAgICByZWNlaXZlIHRoZSBgaXRlbWAgZnJvbSB0aGUgbG9vcCBhcyBpdHMgZmlyc3QgYW5kIG9ubHkgYXJndW1lbnQuXG4gIC0gV2hlbiBpbnZva2VkIGFzIGB0aGlzLmFyZ3Muc2VsZWN0KCdmb28nKWAgdGhlIGBoYW5kbGVTZWxlY3RlZGAgZnVuY3Rpb25cbiAgICB3aWxsIHJlY2VpdmUgdGhlIGBpdGVtYCBmcm9tIHRoZSBsb29wIGFzIGl0cyBmaXJzdCBhcmd1bWVudCBhbmQgdGhlXG4gICAgc3RyaW5nIGAnZm9vJ2AgYXMgaXRzIHNlY29uZCBhcmd1bWVudC5cblxuICBJbiB0aGUgZXhhbXBsZSBhYm92ZSwgd2UgdXNlZCBhbiBhcnJvdyBmdW5jdGlvbiB0byBlbnN1cmUgdGhhdFxuICBgaGFuZGxlU2VsZWN0ZWRgIGlzIHByb3Blcmx5IGJvdW5kIHRvIHRoZSBgaXRlbXMtbGlzdGAsIGJ1dCBsZXQncyBleHBsb3JlIHdoYXRcbiAgaGFwcGVucyBpZiB3ZSBsZWZ0IG91dCB0aGUgYXJyb3cgZnVuY3Rpb246XG5cbiAgYGBgYXBwL2NvbXBvbmVudHMvaXRlbXMtbGlzdC5qc1xuICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BnbGltbWVyL2NvbXBvbmVudCc7XG5cbiAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgSXRlbXNMaXN0IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgICBoYW5kbGVTZWxlY3RlZChpdGVtKSB7XG4gICAgICAvLyAuLi5zbmlwLi4uXG4gICAgfVxuICB9XG4gIGBgYFxuXG4gIEluIHRoaXMgZXhhbXBsZSwgd2hlbiBgaGFuZGxlU2VsZWN0ZWRgIGlzIGludm9rZWQgaW5zaWRlIHRoZSBgZGlzcGxheS1pdGVtYFxuICBjb21wb25lbnQsIGl0IHdpbGwgKipub3QqKiBoYXZlIGFjY2VzcyB0byB0aGUgY29tcG9uZW50IGluc3RhbmNlLiBJbiBvdGhlclxuICB3b3JkcywgaXQgd2lsbCBoYXZlIG5vIGB0aGlzYCBjb250ZXh0LCBzbyBwbGVhc2UgbWFrZSBzdXJlIHlvdXIgZnVuY3Rpb25zXG4gIGFyZSBib3VuZCAodmlhIGFuIGFycm93IGZ1bmN0aW9uIG9yIG90aGVyIG1lYW5zKSBiZWZvcmUgcGFzc2luZyBpbnRvIGBmbmAhXG5cbiAgU2VlIGFsc28gW3BhcnRpYWwgYXBwbGljYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcnRpYWxfYXBwbGljYXRpb24pLlxuXG4gIEBtZXRob2QgZm5cbiAgQHB1YmxpY1xuKi9cbmV4cG9ydCBkZWZhdWx0IGludGVybmFsSGVscGVyKCh7IHBvc2l0aW9uYWwgfTogQ2FwdHVyZWRBcmd1bWVudHMpID0+IHtcbiAgbGV0IGNhbGxiYWNrUmVmID0gcG9zaXRpb25hbFswXTtcblxuICBpZiAoREVCVUcpIGFzc2VydENhbGxiYWNrSXNGbihjYWxsYmFja1JlZik7XG5cbiAgcmV0dXJuIGNyZWF0ZUNvbXB1dGVSZWYoXG4gICAgKCkgPT4ge1xuICAgICAgcmV0dXJuICguLi5pbnZvY2F0aW9uQXJnczogdW5rbm93bltdKSA9PiB7XG4gICAgICAgIGxldCBbZm4sIC4uLmFyZ3NdID0gcmVpZnlQb3NpdGlvbmFsKHBvc2l0aW9uYWwpO1xuXG4gICAgICAgIGlmIChERUJVRykgYXNzZXJ0Q2FsbGJhY2tJc0ZuKGNhbGxiYWNrUmVmKTtcblxuICAgICAgICBpZiAoaXNJbnZva2FibGVSZWYoY2FsbGJhY2tSZWYpKSB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gYXJncy5sZW5ndGggPiAwID8gYXJnc1swXSA6IGludm9jYXRpb25BcmdzWzBdO1xuICAgICAgICAgIHJldHVybiB1cGRhdGVSZWYoY2FsbGJhY2tSZWYsIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gKGZuIGFzIEZ1bmN0aW9uKS5jYWxsKGNvbnRleHQsIC4uLmFyZ3MsIC4uLmludm9jYXRpb25BcmdzKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9LFxuICAgIG51bGwsXG4gICAgJ2ZuJ1xuICApO1xufSk7XG5cbmZ1bmN0aW9uIGFzc2VydENhbGxiYWNrSXNGbihjYWxsYmFja1JlZjogUmVmZXJlbmNlKSB7XG4gIGlmIChcbiAgICAhKFxuICAgICAgY2FsbGJhY2tSZWYgJiZcbiAgICAgIChpc0ludm9rYWJsZVJlZihjYWxsYmFja1JlZikgfHwgdHlwZW9mIHZhbHVlRm9yUmVmKGNhbGxiYWNrUmVmKSA9PT0gJ2Z1bmN0aW9uJylcbiAgICApXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBZb3UgbXVzdCBwYXNzIGEgZnVuY3Rpb24gYXMgdGhlIFxcYGZuXFxgIGhlbHBlcidzIGZpcnN0IGFyZ3VtZW50LCB5b3UgcGFzc2VkICR7XG4gICAgICAgIGNhbGxiYWNrUmVmID8gdmFsdWVGb3JSZWYoY2FsbGJhY2tSZWYpIDogY2FsbGJhY2tSZWZcbiAgICAgIH0uIFdoaWxlIHJlbmRlcmluZzpcXG5cXG4ke2NhbGxiYWNrUmVmPy5kZWJ1Z0xhYmVsfWBcbiAgICApO1xuICB9XG59XG4iXSwic291cmNlUm9vdCI6IiJ9