From b9f88348900717c0200d55dac7e2e57f03f0e85c Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 15:09:02 -0500
Subject: [PATCH 01/23] Motivation and Summary
---
...0-public-api-for-contextual-exploration.md | 98 +++++++++++++++++++
1 file changed, 98 insertions(+)
create mode 100644 text/0000-public-api-for-contextual-exploration.md
diff --git a/text/0000-public-api-for-contextual-exploration.md b/text/0000-public-api-for-contextual-exploration.md
new file mode 100644
index 0000000000..e4f358f360
--- /dev/null
+++ b/text/0000-public-api-for-contextual-exploration.md
@@ -0,0 +1,98 @@
+---
+stage: accepted
+start-date: # In format YYYY-MM-DDT00:00:00.000Z
+release-date: # In format YYYY-MM-DDT00:00:00.000Z
+release-versions:
+teams: # delete teams that aren't relevant
+ - cli
+ - data
+ - framework
+ - learning
+ - steering
+ - typescript
+prs:
+ accepted: # Fill this in with the URL for the Proposal RFC PR
+project-link:
+suite:
+---
+
+
+
+
+
+# Public API for render-tree-based contextual exploration
+
+## Summary
+
+This RFC proposes a public API that enables safe experimentation with render-tree-based contextual data access patterns. The API provides scope-based synchronous access for all invokables (components, helpers, modifiers) across apps, engines, and addons.
+
+## Motivation
+
+The Ember community has long desired a Context API to share state across the render tree without prop drilling, but developers currently must resort to [abusing private Glimmer APIs](https://github.com/customerio/ember-provide-consume-context/blob/def6d34f639d56ebec1c7c8c888f86ec524b8688/ember-provide-consume-context/src/-private/override-glimmer-runtime-classes.ts#L1), creating upgrade risks and maintenance burdens. This RFC provides a public API that enables safe experimentation with Context patterns for use cases like theme systems, authentication state, and feature flags. The expected outcome is to establish a stable foundation for community exploration of contextual data access patterns while gathering real-world feedback to inform future official Context API design.
+
+Additionally, this also enables exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
+
+## Detailed design
+
+> This is the bulk of the RFC.
+
+> Explain the design in enough detail for somebody
+familiar with the framework to understand, and for somebody familiar with the
+implementation to implement. This should get into specifics and corner-cases,
+and include examples of how the feature is used. Any new terminology should be
+defined here.
+
+> Please keep in mind any implications within the Ember ecosystem, such as:
+> - Lint rules (ember-template-lint, eslint-plugin-ember) that should be added, modified or removed
+> - Features that are replaced or made obsolete by this feature and should eventually be deprecated
+> - Ember Inspector and debuggability
+> - Server-side Rendering
+> - Ember Engines
+> - The Addon Ecosystem
+> - IDE Support
+> - Blueprints that should be added or modified
+
+## How we teach this
+
+> What names and terminology work best for these concepts and why? How is this
+idea best presented? As a continuation of existing Ember patterns, or as a
+wholly new one?
+
+> Would the acceptance of this proposal mean the Ember guides must be
+re-organized or altered? Does it change how Ember is taught to new users
+at any level?
+
+> How should this feature be introduced and taught to existing Ember
+users?
+
+> Keep in mind the variety of learning materials: API docs, guides, blog posts, tutorials, etc.
+
+## Drawbacks
+
+> Why should we *not* do this? Please consider the impact on teaching Ember,
+on the integration of this feature with other existing and planned features,
+on the impact of the API churn on existing apps, etc.
+
+> There are tradeoffs to choosing any path, please attempt to identify them here.
+
+## Alternatives
+
+- [ember-provide-consume-context](https://github.com/customerio/ember-provide-consume-context)
+- [passing a third argument to component constructors that is the VM Stack](https://github.com/rtablada/ember-context-experiment/blob/main/app/components/UserName.gjs)
+
+## Unresolved questions
+
+> Optional, but suggested for first drafts. What parts of the design are still
+TBD?
From 6feee9ead215ce3b522c5a05494656d52c08ce81 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:35:03 -0500
Subject: [PATCH 02/23] Some how we teach this via example
---
...0-public-api-for-contextual-exploration.md | 353 ++++++++++++++++--
1 file changed, 321 insertions(+), 32 deletions(-)
diff --git a/text/0000-public-api-for-contextual-exploration.md b/text/0000-public-api-for-contextual-exploration.md
index e4f358f360..4c73994618 100644
--- a/text/0000-public-api-for-contextual-exploration.md
+++ b/text/0000-public-api-for-contextual-exploration.md
@@ -46,46 +46,336 @@ Additionally, this also enables exploration of providing _owner_ access to plain
## Detailed design
-> This is the bulk of the RFC.
-
-> Explain the design in enough detail for somebody
-familiar with the framework to understand, and for somebody familiar with the
-implementation to implement. This should get into specifics and corner-cases,
-and include examples of how the feature is used. Any new terminology should be
-defined here.
-
-> Please keep in mind any implications within the Ember ecosystem, such as:
-> - Lint rules (ember-template-lint, eslint-plugin-ember) that should be added, modified or removed
-> - Features that are replaced or made obsolete by this feature and should eventually be deprecated
-> - Ember Inspector and debuggability
-> - Server-side Rendering
-> - Ember Engines
-> - The Addon Ecosystem
-> - IDE Support
-> - Blueprints that should be added or modified
+> [!NOTE]
+> This RFC does not intend to tie is to any implementation details in our renderer, as experimentation in this area should be possible without changing existing behavior for pre-exitsing apps, and such renderer changes would not change the behavior of what this RFC proposes.
+
+### The Public API
+
+A few examples of usage, once implemented,
+
+Accessing the owner in a plain function
+
+```gjs
+import { getScope } from '@ember/renderer';
+import { getOwner } from '@ember/owner';
+
+function currentRoute() {
+ const scope = getScope();
+ const owner = getOwner(scope);
+
+ return owner.lookup('service:router').currentRouteName;
+}
+
+
+ {{ (currentRoute) }}
+
+```
+
+
+
+Accessing the owner in a modifier
+
+```gjs
+import { getScope } from '@ember/renderer';
+import { modifier } from 'ember-modifier';
+
+const dimensions = modifier((element) => {
+ const scope = getScope();
+ const owner = getOwner(scope);
+ const resize = owner.lookup('service:resize');
+ const callback => (entry) => {
+ element.textContent = JSON.stringify(entry);
+ };
+
+ resize.observe(element, callback);
+
+ return () => {
+ resize.unobserve(element, callback)
+ }
+})
+
+
+
+```
+
+
+
+Accessing via component getter
+
+```gjs
+import Component from '@glimmer/component';
+import { getScope } from '@ember/renderer';
+import { getOwner } from '@ember/owner';
+
+export default class Demo extends Component {
+ // equiv of @service router;
+ get router() {
+ return getOwner(getScope()).lookup('service:router');
+ }
+
+
+ {{this.router.currentRouteName}}
+
+}
+```
+
+
+
+Writing to scope: A component adding to the scope for the component's descendants
+
+```gjs
+import { addToScope, getScope } from '@ember/renderer';
+import Component from '@glimmer/component';
+
+class MyCustomState {
+ /* ... */
+ foo = 2;
+}
+
+class Demo extends Component {
+ constructor(owner, args) {
+ super(owner, args);
+
+ let state = new MyCustomState(owner);
+ addToScope(state);
+ }
+
+
+ {{yield}}
+
+}
+
+function accessIt() {
+ let scope = getScope();
+ let state = scope.entries.find(x => x instanceof MyCustomState);
+
+ return state.foo;
+}
+
+// And then accessing:
+
+
+ {{ (accessIt) }} {{! prints 2 }}
+
+
+```
+
+
+
+### Interface
+
+```ts
+import type Owner from '@ember/owner';
+
+function getScope(): Scope | undefined;
+
+interface Scope {
+ /**
+ * The owner can change based on rendering context,
+ * renderComponent usage, engine usage, etc.
+ *
+ * there are two ways this could be implemented:
+ * - the framework could add the owner into 'entries' whenever it would change
+ * - since the renderer _always_ knows the current owner, we reference that
+ */
+ get [OwnerSymbol](): Owner;
+
+ /**
+ * Each rendering layer will push into this array,
+ * we can detect usage of `addToScope`, and pop when we exit rendering the thing that called `addToScope`.
+ *
+ * This array should contain references *only* (but we can't enforce that).
+ * For each invokable, we'll associate the scope with the invokable during its creation.
+ *
+ * This means that modifications to the scope *cannot* occur during updates.
+ */
+ entries: unknown[];
+}
+```
+
+
+
+### High-level "how it works"
+
+Simular to the exiting debug-render-tree, we'd keep track of a set of "scope" objects throughout the render hierarchy.
+
+And similar to how auto-tracking works, we'd enable access to the scope via:
+```js
+// psuedocode
+
+// Evaluating an "Invokable" ( a curly expression, component, etc )
+globalThis.scope = currentScope(); // implementation depends on renderer strategy
+invoke()
+delete globalThis.scope;
+
+// in @ember/renderer
+export function getScope() {
+ return globalThis.scope;
+}
+```
+
+> [!NOTE]
+> `globalThis.scope` is not literally being suggested here -- this variable should be private, and un findable by means other than the exported `getScope` function.
+
+### How to add to the scope
+
+### Limitations
+
+Because this is a synchronous API, `getScope()` will be undefined after any `await`, and should not be used after an `await` as a result. A new rule to `eslint-plugin-ember` can help out here.
+
## How we teach this
-> What names and terminology work best for these concepts and why? How is this
-idea best presented? As a continuation of existing Ember patterns, or as a
-wholly new one?
+This is a low-level API, and the API Docs generated from the JSDoc for these newly expored functions should have some examples.
+
+It could also be worth demonstrating in the guides how to implement "Context" via these APIs -- for example:
+
+```ts
+// hypothetical ember-prototype-context library
+import { addToScope, getScope } from '@ember/renderer';
+import Component from '@glimmer/component';
+
+export class Provide extends Component {
+ constructor(owner, args) {
+ assert(`Must pass @context`, args.context);
+ assert(`Must pass a key`, args.key)
+
+ provide([args.key, args.context]);
+ }
+}
+
+export function provide(...args) {
+ if (args.length === 3) {
+ /**
+ * TC39's Stage 1 Decorator
+ */
+ return provideTC39Stage1Decorator(...args); // implementation omitted for brevity
+ }
+
+ if (args.length === 2 && 'kind' in args[1]) {
+ if (args[1].kind === 'field') {
+ /**
+ * TC39 "Field" Decorator
+ *
+ * @provide x = new State();
+ */
+ return (initialValue) => provide(initialValue.constructor, initialValue);
+ }
+
+ throw new Error(`Unsupported decorator usage for kind: ${args[1].kind}`);
+ }
+
+ /**
+ * provide(key, instance or state);
+ */
+ addToScope([key, context]);
+
+ return context;
+}
+
+export function consume(key: ClassType): ContextType {
+ let scope = getScope();
+
+ // search up until we find our key
+ for (let i = 0; i < scope.entries.length; i++) {
+ let entry = scope.entries[i];
+
+ if (!Array.isArray(entry)) continue;
+ if (entry[0] === key) return entry[1];
+ }
+}
-> Would the acceptance of this proposal mean the Ember guides must be
-re-organized or altered? Does it change how Ember is taught to new users
-at any level?
+export class Consume extends Component {
+ get context() {
+ assert(`Must pass a key`, this.args.key);
+
+ return consume(this.args.key);
+ }
+
+
+ {{yield this.context}}
+
+}
+```
+
+This supports both class providing and consuming as well as template-based providing and consuming.
+
+```gjs
+import { Consume, Provide, consume, provide } from 'hypothetical ember-prototype-context library';
+
+let id = 0;
+class StateA { foo = 'a'; id = id++; }
+class StateB { foo = 'b' }
+
+const newA = () => new StateA();
+const newB = () => new StateB();
+
+class CustomProvide extends Component {
+ @provide a = new StateA();
+}
+
+const CustomConsume =
+ {{yield (consume @key)}}
+;
+
+
+
+
+ {{a.foo}} === "a"
+ {{a.id}} === 0
+
+
+ {{#let (consume StateA) as |a|}}
+ {{a.foo}} === "a"
+ {{a.id}} === 0;
+ {{/let}}
+
+
+
+ {{#let (provide StateB (newB)) as |b|}}
+ {{b.foo}} === "b"
+
+
+ {{b.foo}} === "b"
+
+
+ {{a.foo}} === "a"
+ {{a.id}} === 1
+
+
+ {{/let}}
+
+
+ {{a.foo}} === "a"
+ {{a.id}} === 1
+
+
+
+ {{a.foo}} === "a"
+ {{a.id}} === 1;
+
+
+
+
+
+ {{#let (consume StateA) as |a|}}
+ {{a.foo}} === "a"
+ {{a.id}} === 2;
+ {{/let}}
+
+
+
+```
-> How should this feature be introduced and taught to existing Ember
-users?
-> Keep in mind the variety of learning materials: API docs, guides, blog posts, tutorials, etc.
## Drawbacks
-> Why should we *not* do this? Please consider the impact on teaching Ember,
-on the integration of this feature with other existing and planned features,
-on the impact of the API churn on existing apps, etc.
+We already track a "stack" in our current renderer, but depending on how this is implemented, it could accidentally double the memory usage of that stack -- however most "scopes" will be empty / reused between render nodes, as what is in the scope is not expected to change that often.
+
+Depending on implementation, there _could_ be a userland-induced memory leak, so we'll want to explore how to ensure the scope entries don't endlessly grow over time (we already manage this with the current renderer's stack (see second alternative below)).
-> There are tradeoffs to choosing any path, please attempt to identify them here.
+Adding more APIs is always more for people to learn, but many frontend frameworks already have similar features, so developers should have an easy time picking this up if they wish (or the future features enabled by this API).
## Alternatives
@@ -94,5 +384,4 @@ on the impact of the API churn on existing apps, etc.
## Unresolved questions
-> Optional, but suggested for first drafts. What parts of the design are still
-TBD?
+n/a (so far)
\ No newline at end of file
From 428047dc0533008b0d6093b71d84a0f5dbb2533f Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:39:49 -0500
Subject: [PATCH 03/23] More examples
---
...0-public-api-for-contextual-exploration.md | 40 ++++++++++++++++++-
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/text/0000-public-api-for-contextual-exploration.md b/text/0000-public-api-for-contextual-exploration.md
index 4c73994618..00b446c42c 100644
--- a/text/0000-public-api-for-contextual-exploration.md
+++ b/text/0000-public-api-for-contextual-exploration.md
@@ -228,7 +228,44 @@ Because this is a synchronous API, `getScope()` will be undefined after any `awa
This is a low-level API, and the API Docs generated from the JSDoc for these newly expored functions should have some examples.
-It could also be worth demonstrating in the guides how to implement "Context" via these APIs -- for example:
+It could also be worth demonstrating in the guides how to implement some use cases.
+
+### Example service access without injection
+
+```gjs
+import { getScope } from '@ember/renderer';
+import { getOwner } from '@ember/owner';
+
+// in a hypothetical library
+export function service(name) {
+ let scope = getScope();
+ let owner = getOwner(scope);
+
+ return owner.lookup(`service:${name}`);
+}
+
+/**
+ * We no longer need class-based helpers to access services
+ */
+export function currentRouteName() {
+ return service('router').currentRouteName;
+}
+```
+
+Usage:
+```gjs
+
+ {{#let service "router") as |router|}}
+ {{router.currentRouteName}}
+ {{/let}}
+
+ {{ (currentRouteName) }}
+
+```
+
+Both of these usages would be reactive as teh router changes routes.
+
+### Example Context Implementation and Usage
```ts
// hypothetical ember-prototype-context library
@@ -368,7 +405,6 @@ const CustomConsume =
```
-
## Drawbacks
We already track a "stack" in our current renderer, but depending on how this is implemented, it could accidentally double the memory usage of that stack -- however most "scopes" will be empty / reused between render nodes, as what is in the scope is not expected to change that often.
From e389ee2536cfca928ed1541758483e57b4461ea4 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:40:31 -0500
Subject: [PATCH 04/23] Typo
---
text/0000-public-api-for-contextual-exploration.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/text/0000-public-api-for-contextual-exploration.md b/text/0000-public-api-for-contextual-exploration.md
index 00b446c42c..ccbd6b1ec3 100644
--- a/text/0000-public-api-for-contextual-exploration.md
+++ b/text/0000-public-api-for-contextual-exploration.md
@@ -204,7 +204,7 @@ And similar to how auto-tracking works, we'd enable access to the scope via:
// psuedocode
// Evaluating an "Invokable" ( a curly expression, component, etc )
-globalThis.scope = currentScope(); // implementation depends on renderer strategy
+globalThis.scope = currentScope(); // implementation may depend on renderer strategy
invoke()
delete globalThis.scope;
From 38d6788b9e43397022a3f0380c5387f0f4349341 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:41:35 -0500
Subject: [PATCH 05/23] Change title
---
... 0000-public-api-for-render-tree-based-scope-exploration.md} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename text/{0000-public-api-for-contextual-exploration.md => 0000-public-api-for-render-tree-based-scope-exploration.md} (99%)
diff --git a/text/0000-public-api-for-contextual-exploration.md b/text/0000-public-api-for-render-tree-based-scope-exploration.md
similarity index 99%
rename from text/0000-public-api-for-contextual-exploration.md
rename to text/0000-public-api-for-render-tree-based-scope-exploration.md
index ccbd6b1ec3..bb919141fd 100644
--- a/text/0000-public-api-for-contextual-exploration.md
+++ b/text/0000-public-api-for-render-tree-based-scope-exploration.md
@@ -32,7 +32,7 @@ suite: Leave as is
-# Public API for render-tree-based contextual exploration
+# Public API for render-tree-based scope exploration
## Summary
From c8f45513b7d152f7b8587403ef4d3a2dde483073 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:43:35 -0500
Subject: [PATCH 06/23] Update meta
---
...-public-api-for-render-tree-based-scope-exploration.md} | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
rename text/{0000-public-api-for-render-tree-based-scope-exploration.md => 1154-public-api-for-render-tree-based-scope-exploration.md} (98%)
diff --git a/text/0000-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
similarity index 98%
rename from text/0000-public-api-for-render-tree-based-scope-exploration.md
rename to text/1154-public-api-for-render-tree-based-scope-exploration.md
index bb919141fd..cbec3dc3ef 100644
--- a/text/0000-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -1,17 +1,14 @@
---
stage: accepted
-start-date: # In format YYYY-MM-DDT00:00:00.000Z
+start-date: 2025-11-17T00:00:00.000Z
release-date: # In format YYYY-MM-DDT00:00:00.000Z
release-versions:
teams: # delete teams that aren't relevant
- - cli
- data
- framework
- learning
- - steering
- - typescript
prs:
- accepted: # Fill this in with the URL for the Proposal RFC PR
+ accepted: https://github.com/emberjs/rfcs/pull/1154
project-link:
suite:
---
From 58e8108d5da949fd734ab84cde2b7bb7df1eb6ff Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:48:55 -0500
Subject: [PATCH 07/23] Motivation updates
---
...-public-api-for-render-tree-based-scope-exploration.md | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index cbec3dc3ef..bc8816ae35 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -37,9 +37,13 @@ This RFC proposes a public API that enables safe experimentation with render-tre
## Motivation
-The Ember community has long desired a Context API to share state across the render tree without prop drilling, but developers currently must resort to [abusing private Glimmer APIs](https://github.com/customerio/ember-provide-consume-context/blob/def6d34f639d56ebec1c7c8c888f86ec524b8688/ember-provide-consume-context/src/-private/override-glimmer-runtime-classes.ts#L1), creating upgrade risks and maintenance burdens. This RFC provides a public API that enables safe experimentation with Context patterns for use cases like theme systems, authentication state, and feature flags. The expected outcome is to establish a stable foundation for community exploration of contextual data access patterns while gathering real-world feedback to inform future official Context API design.
+The Ember community has long desired a Context API to share state across the render tree without prop drilling -- and currently developers must resort to [abusing private Glimmer APIs](https://github.com/customerio/ember-provide-consume-context/blob/def6d34f639d56ebec1c7c8c888f86ec524b8688/ember-provide-consume-context/src/-private/override-glimmer-runtime-classes.ts#L1), creating upgrade risks and [maintenance burdens](https://github.com/customerio/ember-provide-consume-context/pull/49). The last action item for the [Context RFC, #975](https://github.com/emberjs/rfcs/pull/975) is to propose a public API for experimentation.
+
+This RFC does not propose a solution for Context directly.
+
+This RFC provides a public API that enables safe experimentation with Context patterns as well aligning with some feature design discussed in Discord as well as spec meetings (all public) - enabling exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
+
-Additionally, this also enables exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
## Detailed design
From d3b52be4c78da88c522556b4cb039c6f45984fb7 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:52:55 -0500
Subject: [PATCH 08/23] Updates
---
...c-api-for-render-tree-based-scope-exploration.md | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index bc8816ae35..1c26aa9766 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -168,7 +168,7 @@ function accessIt() {
```ts
import type Owner from '@ember/owner';
-function getScope(): Scope | undefined;
+export function getScope(): Scope | undefined;
interface Scope {
/**
@@ -192,6 +192,8 @@ interface Scope {
*/
entries: unknown[];
}
+
+export function addToScope(x: unknown);
```
@@ -213,6 +215,15 @@ delete globalThis.scope;
export function getScope() {
return globalThis.scope;
}
+
+export function addToScope(x) {
+ let scope = getScope();
+
+ assert('cannot add to scope when there is no current scope', scope);
+ // It will probably be better to make this readonly from the outside and have some other way of
+ // manipulating the entries
+ scope.entries.push(x);
+}
```
> [!NOTE]
From 16f3a154b3f2e5ce5b8d972fbe66f874b08c3bb8 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 17:54:16 -0500
Subject: [PATCH 09/23] Typos
---
...54-public-api-for-render-tree-based-scope-exploration.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 1c26aa9766..7207110c44 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -48,7 +48,7 @@ This RFC provides a public API that enables safe experimentation with Context pa
## Detailed design
> [!NOTE]
-> This RFC does not intend to tie is to any implementation details in our renderer, as experimentation in this area should be possible without changing existing behavior for pre-exitsing apps, and such renderer changes would not change the behavior of what this RFC proposes.
+> This RFC does not intend to tie is to any implementation details in our renderer, as experimentation in this area should be possible without changing existing behavior for pre-existing apps, and such renderer changes would not change the behavior of what this RFC proposes.
### The Public API
@@ -200,7 +200,7 @@ export function addToScope(x: unknown);
### High-level "how it works"
-Simular to the exiting debug-render-tree, we'd keep track of a set of "scope" objects throughout the render hierarchy.
+Similar to the exiting debug-render-tree, we'd keep track of a set of "scope" objects throughout the render hierarchy.
And similar to how auto-tracking works, we'd enable access to the scope via:
```js
@@ -218,7 +218,7 @@ export function getScope() {
export function addToScope(x) {
let scope = getScope();
-
+
assert('cannot add to scope when there is no current scope', scope);
// It will probably be better to make this readonly from the outside and have some other way of
// manipulating the entries
From 86a339a0e1fa47583742f2533449c29675d3662f Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 18:10:34 -0500
Subject: [PATCH 10/23] Typos
---
...-for-render-tree-based-scope-exploration.md | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 7207110c44..221e9fe079 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -48,7 +48,7 @@ This RFC provides a public API that enables safe experimentation with Context pa
## Detailed design
> [!NOTE]
-> This RFC does not intend to tie is to any implementation details in our renderer, as experimentation in this area should be possible without changing existing behavior for pre-existing apps, and such renderer changes would not change the behavior of what this RFC proposes.
+> This RFC does not intend to tie us to any implementation details in our renderer, as experimentation in this area should be possible without changing existing behavior for pre-existing apps, and such renderer changes would not change the behavior of what this RFC proposes.
### The Public API
@@ -165,6 +165,8 @@ function accessIt() {
### Interface
+Once implemented, this would be the stable public API:
+
```ts
import type Owner from '@ember/owner';
@@ -200,7 +202,7 @@ export function addToScope(x: unknown);
### High-level "how it works"
-Similar to the exiting debug-render-tree, we'd keep track of a set of "scope" objects throughout the render hierarchy.
+Similar to the existing debug-render-tree, we'd keep track of a set of "scope" objects throughout the render hierarchy.
And similar to how auto-tracking works, we'd enable access to the scope via:
```js
@@ -229,6 +231,14 @@ export function addToScope(x) {
> [!NOTE]
> `globalThis.scope` is not literally being suggested here -- this variable should be private, and un findable by means other than the exported `getScope` function.
+### Inspector
+
+todo
+
+### Testing
+
+todo
+
### How to add to the scope
### Limitations
@@ -238,7 +248,7 @@ Because this is a synchronous API, `getScope()` will be undefined after any `awa
## How we teach this
-This is a low-level API, and the API Docs generated from the JSDoc for these newly expored functions should have some examples.
+This is a low-level API, and the API Docs generated from the JSDoc for these newly exported functions should have some examples.
It could also be worth demonstrating in the guides how to implement some use cases.
@@ -275,7 +285,7 @@ Usage:
```
-Both of these usages would be reactive as teh router changes routes.
+Both of these usages would be reactive as the router changes routes.
### Example Context Implementation and Usage
From f7526637668c8583076720f1d2fef3ff6461f5e9 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Mon, 17 Nov 2025 22:00:21 -0500
Subject: [PATCH 11/23] Be clear about difference between Alternatives and
Prior Art
---
...api-for-render-tree-based-scope-exploration.md | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 221e9fe079..36df7331a9 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -437,8 +437,21 @@ Adding more APIs is always more for people to learn, but many frontend framework
## Alternatives
+None.
+
+### Prior Art
+
+Context Explorations
+
- [ember-provide-consume-context](https://github.com/customerio/ember-provide-consume-context)
-- [passing a third argument to component constructors that is the VM Stack](https://github.com/rtablada/ember-context-experiment/blob/main/app/components/UserName.gjs)
+- [experiment passing the component tree to component managers](https://github.com/rtablada/ember-context-experiment/blob/main/app/components/UserName.gjs)
+ - for this RFC, we don't want to change how component managers work, because this scope feature should work for _all_ invokables and _all_ `{{}}` regions
+
+
+Service-like things with non-string keys:
+
+- [createStore](https://ember-primitives.pages.dev/6-utils/createStore.md)
+- [ember-polaris-service](https://github.com/chancancode/ember-polaris-service)
## Unresolved questions
From 7491fad88e547ad16502cb7f67ac231082742b8a Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:06:38 -0500
Subject: [PATCH 12/23] Some clarifications
---
...for-render-tree-based-scope-exploration.md | 45 ++++++++++++-------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 36df7331a9..8895873ae8 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -184,15 +184,11 @@ interface Scope {
get [OwnerSymbol](): Owner;
/**
- * Each rendering layer will push into this array,
- * we can detect usage of `addToScope`, and pop when we exit rendering the thing that called `addToScope`.
+ * For iterating up the render tree.
*
- * This array should contain references *only* (but we can't enforce that).
- * For each invokable, we'll associate the scope with the invokable during its creation.
- *
- * This means that modifications to the scope *cannot* occur during updates.
+ * This the data within should contain references *only* (but we can't enforce that).
*/
- entries: unknown[];
+ entries: Iterator;
}
export function addToScope(x: unknown);
@@ -207,6 +203,7 @@ Similar to the existing debug-render-tree, we'd keep track of a set of "scope" o
And similar to how auto-tracking works, we'd enable access to the scope via:
```js
// psuedocode
+// for demonstration only, not actual code
// Evaluating an "Invokable" ( a curly expression, component, etc )
globalThis.scope = currentScope(); // implementation may depend on renderer strategy
@@ -222,24 +219,37 @@ export function addToScope(x) {
let scope = getScope();
assert('cannot add to scope when there is no current scope', scope);
- // It will probably be better to make this readonly from the outside and have some other way of
- // manipulating the entries
- scope.entries.push(x);
+
+ // Implementation ommitted for brevity
+ setScopeData(scope, x);
}
```
> [!NOTE]
> `globalThis.scope` is not literally being suggested here -- this variable should be private, and un findable by means other than the exported `getScope` function.
+
+In renderer code, we already know the render tree, but none of it is exposed to users (it is all private API, and the debugRenderTree uses this for inspector support). Each rendering node will have the opportunity to set some userland metadata via `addToScope`. This userland metadata is privately stored on the rendering node, and can only be accessed via `getScope`.
+
+For crawling up the userland metadata of the render tree, you'd iterate over the [entries Iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/Iterator) looking for whatever you need.
+
+### What's in `scope.entries`?
+
+- At a minimum, the `scope.entries` will contain a _root metadata_, the root of the application (containing the `owner`).
+- Iterating `scope.entries` will always have _one_ iteration, unless `addToScope` is called during rendering.
+- `scope.entries` is lazy, in that when rendering, we don't eagerly calculate what can be found within, nor while iterating (unless iteration completes, and hits the _root metadata_)
+- For each render node, the metadata is undefined until set, so that iteration can skip over empty metadatas
+
+
### Inspector
-todo
+Because the inspector uses the debugRenderTree, and the debugRenderTree has access to everything that can have a scope -- the inspector can display the scope in the object inspector.
### Testing
-todo
+Testing with scope is the same as using in the application or library code.
-### How to add to the scope
+If you want to use a separate value or implementation of something higher up in the render tree, the test rendered code should be wrapped wiht a test implementation which sets the test-specific scope value.
### Limitations
@@ -429,9 +439,7 @@ const CustomConsume =
## Drawbacks
-We already track a "stack" in our current renderer, but depending on how this is implemented, it could accidentally double the memory usage of that stack -- however most "scopes" will be empty / reused between render nodes, as what is in the scope is not expected to change that often.
-
-Depending on implementation, there _could_ be a userland-induced memory leak, so we'll want to explore how to ensure the scope entries don't endlessly grow over time (we already manage this with the current renderer's stack (see second alternative below)).
+This isn't _Context_, and _Context_ is what our users want, but I think we want strong public APIs so that we can explore userland APIs, and then RFC what those end up being, what the requiremnts are, and then add that to the framework once the idea and capabilities is stable.
Adding more APIs is always more for people to learn, but many frontend frameworks already have similar features, so developers should have an easy time picking this up if they wish (or the future features enabled by this API).
@@ -444,8 +452,11 @@ None.
Context Explorations
- [ember-provide-consume-context](https://github.com/customerio/ember-provide-consume-context)
+ - proposed in [RFC#975](https://github.com/emberjs/rfcs/pull/975)
- [experiment passing the component tree to component managers](https://github.com/rtablada/ember-context-experiment/blob/main/app/components/UserName.gjs)
- for this RFC, we don't want to change how component managers work, because this scope feature should work for _all_ invokables and _all_ `{{}}` regions
+ - an RFC about this approach was opened at [RFC#1155](https://github.com/emberjs/rfcs/pull/1155)
+ - This RFC focuses on changing component manager APIs (additively), which means that only components can interact with the context.
Service-like things with non-string keys:
@@ -455,4 +466,4 @@ Service-like things with non-string keys:
## Unresolved questions
-n/a (so far)
\ No newline at end of file
+- other names for `entries`? `hierarchy`? `ancestry`?
\ No newline at end of file
From 962fdf9d63b30a79beae34407edbd41df73071c5 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:15:40 -0500
Subject: [PATCH 13/23] Typos
---
...4-public-api-for-render-tree-based-scope-exploration.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 8895873ae8..a879849c21 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -41,7 +41,7 @@ The Ember community has long desired a Context API to share state across the ren
This RFC does not propose a solution for Context directly.
-This RFC provides a public API that enables safe experimentation with Context patterns as well aligning with some feature design discussed in Discord as well as spec meetings (all public) - enabling exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
+This RFC provides a public API that enables safe experimentation with Context patterns as well as aligning with some feature design discussed in Discord as well as spec meetings (all public) - enabling exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
@@ -220,7 +220,7 @@ export function addToScope(x) {
assert('cannot add to scope when there is no current scope', scope);
- // Implementation ommitted for brevity
+ // Implementation omitted for brevity
setScopeData(scope, x);
}
```
@@ -439,7 +439,7 @@ const CustomConsume =
## Drawbacks
-This isn't _Context_, and _Context_ is what our users want, but I think we want strong public APIs so that we can explore userland APIs, and then RFC what those end up being, what the requiremnts are, and then add that to the framework once the idea and capabilities is stable.
+This isn't _Context_, and _Context_ is what our users want, but I think we want strong public APIs so that we can explore userland APIs, and then RFC what those end up being, what the requirements are, and then add that to the framework once the idea and capabilities is stable.
Adding more APIs is always more for people to learn, but many frontend frameworks already have similar features, so developers should have an easy time picking this up if they wish (or the future features enabled by this API).
@@ -457,6 +457,7 @@ Context Explorations
- for this RFC, we don't want to change how component managers work, because this scope feature should work for _all_ invokables and _all_ `{{}}` regions
- an RFC about this approach was opened at [RFC#1155](https://github.com/emberjs/rfcs/pull/1155)
- This RFC focuses on changing component manager APIs (additively), which means that only components can interact with the context.
+ - It exposes some currently internal private values for existing internal component managers, which are not meant for extension (both for safety and maintenance reasons).
Service-like things with non-string keys:
From 4c1843dae31cb7470648d630bc6bb97ac382f76f Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:27:56 -0500
Subject: [PATCH 14/23] Updates
---
...-public-api-for-render-tree-based-scope-exploration.md | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index a879849c21..f4df1c5acc 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -180,6 +180,9 @@ interface Scope {
* there are two ways this could be implemented:
* - the framework could add the owner into 'entries' whenever it would change
* - since the renderer _always_ knows the current owner, we reference that
+ *
+ * This "OwnerSymbol" is a placeholder for the Symbol used by `setOwner`,
+ * which enables `getOwner(scope)`
*/
get [OwnerSymbol](): Owner;
@@ -241,6 +244,8 @@ For crawling up the userland metadata of the render tree, you'd iterate over the
- For each render node, the metadata is undefined until set, so that iteration can skip over empty metadatas
+
+
### Inspector
Because the inspector uses the debugRenderTree, and the debugRenderTree has access to everything that can have a scope -- the inspector can display the scope in the object inspector.
@@ -467,4 +472,5 @@ Service-like things with non-string keys:
## Unresolved questions
-- other names for `entries`? `hierarchy`? `ancestry`?
\ No newline at end of file
+- other names for `entries`? `hierarchy`? `ancestry`?
+- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
\ No newline at end of file
From 06a172e64e8aa79f81446ccc60a879ebc0a70e5e Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:28:56 -0500
Subject: [PATCH 15/23] Updates
---
...1154-public-api-for-render-tree-based-scope-exploration.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index f4df1c5acc..0517a68dba 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -351,9 +351,7 @@ export function consume(key: ClassType): ContextType {
let scope = getScope();
// search up until we find our key
- for (let i = 0; i < scope.entries.length; i++) {
- let entry = scope.entries[i];
-
+ for (let entry of scope.entries) {
if (!Array.isArray(entry)) continue;
if (entry[0] === key) return entry[1];
}
From 6858deb2f12621e9c9cce6f35db2e234c3a1c03d Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:36:06 -0500
Subject: [PATCH 16/23] Clarification
---
...154-public-api-for-render-tree-based-scope-exploration.md | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 0517a68dba..c298af10ab 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -456,11 +456,14 @@ Context Explorations
- [ember-provide-consume-context](https://github.com/customerio/ember-provide-consume-context)
- proposed in [RFC#975](https://github.com/emberjs/rfcs/pull/975)
+ - only allows use in components
+ - relies on tight coupling to the VM's current implementation
- [experiment passing the component tree to component managers](https://github.com/rtablada/ember-context-experiment/blob/main/app/components/UserName.gjs)
- for this RFC, we don't want to change how component managers work, because this scope feature should work for _all_ invokables and _all_ `{{}}` regions
- an RFC about this approach was opened at [RFC#1155](https://github.com/emberjs/rfcs/pull/1155)
- This RFC focuses on changing component manager APIs (additively), which means that only components can interact with the context.
- It exposes some currently internal private values for existing internal component managers, which are not meant for extension (both for safety and maintenance reasons).
+
Service-like things with non-string keys:
@@ -471,4 +474,4 @@ Service-like things with non-string keys:
## Unresolved questions
- other names for `entries`? `hierarchy`? `ancestry`?
-- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
\ No newline at end of file
+- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
From a012d095a2c2f7d9e5de0905076e3a5495cca407 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:41:09 -0500
Subject: [PATCH 17/23] Talk about cleanup and reactivity
---
text/1154-public-api-for-render-tree-based-scope-exploration.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index c298af10ab..1a2ed1bc29 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -242,7 +242,7 @@ For crawling up the userland metadata of the render tree, you'd iterate over the
- Iterating `scope.entries` will always have _one_ iteration, unless `addToScope` is called during rendering.
- `scope.entries` is lazy, in that when rendering, we don't eagerly calculate what can be found within, nor while iterating (unless iteration completes, and hits the _root metadata_)
- For each render node, the metadata is undefined until set, so that iteration can skip over empty metadatas
-
+- Changes to this `scope.entries` are _not_ reactive, because reactivity is not needed. The access of `scope.entries` is always just-in-time, because access-order is the same as render-order, and cleanup / "removal" happens in-tandem with render node cleanup (which only happens when all render children are cleaned up).
From c6a5a78fc84293eeb67f8283a73b280ec1d6e234 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:57:06 -0500
Subject: [PATCH 18/23] Add render component example with custom local owner
---
...for-render-tree-based-scope-exploration.md | 48 ++++++++++++++++++-
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 1a2ed1bc29..c2c955f501 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -163,6 +163,51 @@ function accessIt() {
+Usage with renderComponent
+
+```gjs
+import Component from '@glimmer/component';
+import { getScope, renderComponent } from '@ember/renderer';
+import { getOwner } from '@ember/owner';
+
+class Demo extends Component {
+ // equiv of @service router;
+ get name() {
+ let scope = getScope();
+ let owner = getOwner(scope);
+ return owner.lookup('service:router')?.currentRouteName ?? 'no router';
+ }
+
+
+ {{this.name}}
+
+}
+
+function customRender() {
+ let element = document.createElement('div');
+
+ renderComponent(Demo, {
+ into: element,
+ owner: {
+ lookup(name) {
+ // not implemented
+ return;
+ }
+ }
+ });
+
+ return element;
+}
+
+
+ {{ (customRender) }} {{! renders "no router"}}
+
+ {{! renders "index", (if the URL is "/") }}
+
+```
+
+
+
### Interface
Once implemented, this would be the stable public API:
@@ -244,8 +289,6 @@ For crawling up the userland metadata of the render tree, you'd iterate over the
- For each render node, the metadata is undefined until set, so that iteration can skip over empty metadatas
- Changes to this `scope.entries` are _not_ reactive, because reactivity is not needed. The access of `scope.entries` is always just-in-time, because access-order is the same as render-order, and cleanup / "removal" happens in-tandem with render node cleanup (which only happens when all render children are cleaned up).
-
-
### Inspector
Because the inspector uses the debugRenderTree, and the debugRenderTree has access to everything that can have a scope -- the inspector can display the scope in the object inspector.
@@ -475,3 +518,4 @@ Service-like things with non-string keys:
- other names for `entries`? `hierarchy`? `ancestry`?
- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
+- should `scope` be an object that you _must_ set key-value pairs on? (right now it's just a single value that can be anything)
From f2cebf64ec3e0388ed509ac21093c218a53c880b Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 11:57:19 -0500
Subject: [PATCH 19/23] Add render component example with custom local owner
---
text/1154-public-api-for-render-tree-based-scope-exploration.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index c2c955f501..8783bd775f 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -163,7 +163,7 @@ function accessIt() {
-Usage with renderComponent
+Usage with renderComponent with owner override
```gjs
import Component from '@glimmer/component';
From 6eddf50c7843eff1bdde95fcec08968dc45b4c54 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 12:02:02 -0500
Subject: [PATCH 20/23] Updates
---
.../1154-public-api-for-render-tree-based-scope-exploration.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 8783bd775f..6f75537c2c 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -239,7 +239,7 @@ interface Scope {
entries: Iterator;
}
-export function addToScope(x: unknown);
+export function addToScope(x: unknown): void;
```
@@ -519,3 +519,4 @@ Service-like things with non-string keys:
- other names for `entries`? `hierarchy`? `ancestry`?
- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
- should `scope` be an object that you _must_ set key-value pairs on? (right now it's just a single value that can be anything)
+- testing details depend on how `scope` is used, but I could add samples based on the example implementations in "How we teach this" if folks think that's useful?
\ No newline at end of file
From cc099454a06508a56af9736fbe7a2fa10d689fbe Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 16:43:19 -0500
Subject: [PATCH 21/23] Specify new owner behavior
---
...pi-for-render-tree-based-scope-exploration.md | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 6f75537c2c..9b971fa461 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -57,12 +57,11 @@ A few examples of usage, once implemented,
Accessing the owner in a plain function
```gjs
-import { getScope } from '@ember/renderer';
import { getOwner } from '@ember/owner';
function currentRoute() {
- const scope = getScope();
- const owner = getOwner(scope);
+ // getOwner is now aware of the active scope
+ const owner = getOwner();
return owner.lookup('service:router').currentRouteName;
}
@@ -77,12 +76,11 @@ function currentRoute() {
Accessing the owner in a modifier
```gjs
-import { getScope } from '@ember/renderer';
+import { getOwner } from '@ember/owner';
import { modifier } from 'ember-modifier';
const dimensions = modifier((element) => {
- const scope = getScope();
- const owner = getOwner(scope);
+ const owner = getOwner();
const resize = owner.lookup('service:resize');
const callback => (entry) => {
element.textContent = JSON.stringify(entry);
@@ -105,13 +103,13 @@ const dimensions = modifier((element) => {
```gjs
import Component from '@glimmer/component';
-import { getScope } from '@ember/renderer';
import { getOwner } from '@ember/owner';
export default class Demo extends Component {
// equiv of @service router;
get router() {
- return getOwner(getScope()).lookup('service:router');
+ // NOTE: this is less safe than `getOwner(this)`
+ return getOwner().lookup('service:router');
}
@@ -519,4 +517,4 @@ Service-like things with non-string keys:
- other names for `entries`? `hierarchy`? `ancestry`?
- add `.owner` property/getter on the `scope`, instead of requiring `getOwner(scope)`
- should `scope` be an object that you _must_ set key-value pairs on? (right now it's just a single value that can be anything)
-- testing details depend on how `scope` is used, but I could add samples based on the example implementations in "How we teach this" if folks think that's useful?
\ No newline at end of file
+- testing details depend on how `scope` is used, but I could add samples based on the example implementations in "How we teach this" if folks think that's useful?
From a2dfd8cf3ce7487aeccb7726e47aca93a1f0e9af Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 16:45:51 -0500
Subject: [PATCH 22/23] Clarify
---
text/1154-public-api-for-render-tree-based-scope-exploration.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index 9b971fa461..a58a35e970 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -43,6 +43,8 @@ This RFC does not propose a solution for Context directly.
This RFC provides a public API that enables safe experimentation with Context patterns as well as aligning with some feature design discussed in Discord as well as spec meetings (all public) - enabling exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
+_`getOwner`_ can then also be updated to not require passing a `this` and still get owner -- which means `getOwner` can be used in plain functions, modifiers, etc.
+
## Detailed design
From 0b1741ae55c42a64e7d02e3a183900c427d4265f Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Tue, 18 Nov 2025 16:47:30 -0500
Subject: [PATCH 23/23] Clarify
---
...154-public-api-for-render-tree-based-scope-exploration.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/text/1154-public-api-for-render-tree-based-scope-exploration.md b/text/1154-public-api-for-render-tree-based-scope-exploration.md
index a58a35e970..ea88c56905 100644
--- a/text/1154-public-api-for-render-tree-based-scope-exploration.md
+++ b/text/1154-public-api-for-render-tree-based-scope-exploration.md
@@ -41,9 +41,10 @@ The Ember community has long desired a Context API to share state across the ren
This RFC does not propose a solution for Context directly.
-This RFC provides a public API that enables safe experimentation with Context patterns as well as aligning with some feature design discussed in Discord as well as spec meetings (all public) - enabling exploration of providing _owner_ access to plain function helpers, modifiers, (all invokables).
+This RFC provides:
+- New ability for _`getOwner`_: can be updated to not require passing a `this` and still get owner -- which means `getOwner` can be used in plain functions, modifiers, etc (all invokables).
+- safe experimentation with context patterns
-_`getOwner`_ can then also be updated to not require passing a `this` and still get owner -- which means `getOwner` can be used in plain functions, modifiers, etc.