Skip to content

Add builtin keyword helpers (fn, hash, array, and, or, not, eq, neq, lt, lte, gt, gte)#21229

Closed
NullVoxPopuli-ai-agent wants to merge 3 commits intoemberjs:nvp/on-as-keyword-tremplate-the-transform-wayfrom
NullVoxPopuli-ai-agent:nvp/builtin-keyword-helpers
Closed

Add builtin keyword helpers (fn, hash, array, and, or, not, eq, neq, lt, lte, gt, gte)#21229
NullVoxPopuli-ai-agent wants to merge 3 commits intoemberjs:nvp/on-as-keyword-tremplate-the-transform-wayfrom
NullVoxPopuli-ai-agent:nvp/builtin-keyword-helpers

Conversation

@NullVoxPopuli-ai-agent
Copy link
Copy Markdown
Contributor

Summary

Building on the foundation from #21068 (on as keyword), this PR adds all remaining helpers as strict-mode keywords per their respective RFCs:

  • fn (RFC #998), hash (RFC #999), array (RFC #1000) — already existed as helpers, now registered as keywords
  • and, or, not (RFC #562) — new helper implementations + keyword registration
  • lt, lte, gt, gte (RFC #561) — new helper implementations + keyword registration
  • eq, neq (RFC #560) — new helper implementations + keyword registration

What this means

In strict-mode templates (.gjs/.gts/<template>), these helpers are now available without importing them:

<template>
  {{! No imports needed for any of these }}
  <button {{on "click" (fn this.doStuff "arg")}}>Click</button>
  {{#each (array "a" "b" "c") as |item|}}{{item}}{{/each}}
  {{#let (hash name="Ember") as |obj|}}{{obj.name}}{{/let}}
  {{if (eq this.status "active") "Active" "Inactive"}}
  {{if (and this.isReady (not this.isLoading)) "Go" "Wait"}}
  {{if (gt this.count 10) "Many" "Few"}}
</template>

All keywords can still be shadowed by local scope definitions, maintaining backwards compatibility.

Implementation

  • New helpers (and, or, not, eq, neq, lt, lte, gt, gte) implemented as Glimmer internal helpers in @glimmer/runtime
  • All helpers exported from @ember/helper
  • auto-import-builtins AST plugin extended to handle MustacheStatement and SubExpression nodes (in addition to ElementModifierStatement for on)
  • Strict mode only — no changes to loose mode (hbs) templates

Not included

  • element (RFC #389) — this involves contextual components and needs separate implementation

Test plan

  • Integration tests for each keyword helper (explicit scope, keyword-only scope, runtime compiler)
  • Tests for shadowing behavior
  • Smoke tests for keyword usage in a real Ember app
  • All existing tests pass (8794 tests, 0 failures)
  • TypeScript types pass
  • Lints pass (ESLint, Prettier, docs coverage)

🤖 Generated with Claude Code

NullVoxPopuli and others added 2 commits March 23, 2026 11:12
sketching some updates

@ef4 -- it doesn't work

Use globalThis

lint:fix
…lt, lte, gt, gte

Building on the foundation from emberjs#21068 (on as keyword), this adds all
remaining helpers as strict-mode keywords per their respective RFCs:
- fn (RFC 998), hash (RFC 999), array (RFC 1000)
- and, or, not (RFC 562)
- lt, lte, gt, gte (RFC 561)
- eq, neq (RFC 560)

Each helper is implemented as a Glimmer internal helper in @glimmer/runtime,
exported from @ember/helper, and registered in the auto-import-builtins AST
plugin for strict-mode templates only.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- fn: Use fn in SubExpression position with on modifier (fn creates
  partial application, not a direct invocation)
- array: Use array in SubExpression position with fn+on instead of
  each (avoids strict mode resolution edge case with each keyword)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@NullVoxPopuli NullVoxPopuli marked this pull request as draft March 23, 2026 19:37
@NullVoxPopuli NullVoxPopuli self-assigned this Mar 23, 2026
@NullVoxPopuli NullVoxPopuli force-pushed the nvp/on-as-keyword-tremplate-the-transform-way branch from 202a724 to a5c1907 Compare March 26, 2026 16:18
@NullVoxPopuli NullVoxPopuli force-pushed the nvp/on-as-keyword-tremplate-the-transform-way branch from 360c67b to 5403b05 Compare April 6, 2026 16:12
@NullVoxPopuli NullVoxPopuli deleted the branch emberjs:nvp/on-as-keyword-tremplate-the-transform-way April 6, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants