| StructuredErrorDocument;
```
@@ -193,7 +216,7 @@ that it can then compose how it sees fit with its own response.
type NextFn = (req: RequestInfo) => Future
;
interface Handler {
- request(context: RequestContext, next: NextFn): T;
+ request(context: RequestContext, next: NextFn): Promise | Future;
}
```
@@ -326,8 +349,8 @@ applications by exporting the manager as an Ember service.
*services/request.ts*
```ts
-import { RequestManager } from '@ember-data/request';
-import { Fetch } from '@ember/data/request/fetch';
+import RequestManager from '@ember-data/request';
+import Fetch from '@ember/data/request/fetch';
import Auth from 'ember-simple-auth/ember-data-handler';
export default class extends RequestManager {
@@ -356,8 +379,8 @@ Alternatively to have a request service unique to the store:
```ts
import Store from '@ember-data/store';
-import { RequestManager } from '@ember-data/request';
-import { Fetch } from '@ember/data/request/fetch';
+import RequestManager from '@ember-data/request';
+import Fetch from '@ember/data/request/fetch';
export default class extends Store {
requestManager = new RequestManager();
@@ -376,8 +399,8 @@ like the above would need to be done by the consuming application in order to ma
```ts
import Store from '@ember-data/store';
-import { RequestManager } from '@ember-data/request';
-import { LegacyHandler } from '@ember-data/legacy-network-handler';
+import RequestManager from '@ember-data/request';
+import { LegacyNetworkHandler } from '@ember-data/legacy-compat';
export default class extends Store {
requestManager = new RequestManager();
@@ -454,6 +477,41 @@ be useful for both application code and the Ember Inspector. If you are interest
such support, we would accept an RFC. With the greatly improved flow this RFC brings we
expect that the overall design of the RequestStateService ought to be revisited.
+### Registering a CacheHandler
+
+While any handler could make use of a cache, there is a handler granted specialized
+status which effectively functions as the very first handler in the handler chain
+(some additional special priviledges may be afforded around timing).
+
+Only one such handler may exist, and an error will be thrown if more than one
+is attempted to be registered.
+
+This method should only be used by a consuming application when the RequestManager
+instance is not the same instance used by the `Store`. If using `@ember-data/store`,
+`@ember-data/store` configures a `CacheHandler` which utilizes the `Cache`, the `LifetimesService`
+and `cacheOptions` to gate whether the request continues down the handler chain.
+
+This same handler is what is responsible for updating the `Cache` via `Cache.put` once
+the request completes.
+
+```ts
+class RequestManager {
+ /**
+ * Register a handler to use for primary cache intercept.
+ *
+ * Only one such handler may exist. If using the same
+ * RequestManager as the Store instance the Store
+ * registers itself as a Cache handler.
+ *
+ * @method useCache
+ * @public
+ * @param {Handler[]} cacheHandler
+ * @returns {void}
+ */
+ useCache(cacheHandler: Handler): void;
+}
+```
+
### Cache Lifetimes
In the past, cache lifetimes for single resources were controlled by either
@@ -464,13 +522,16 @@ for `shouldReloadRecord`, `shouldReloadAll`, `shouldBackgroundReloadRecord` and
This behavior will now be controlled by the combination of either supplying `cacheOptions`
on the associated `RequestInfo` or by supplying a `lifetimes` service to the `Store`.
+Explicit `cacheOptions` will always take precedence over the `lifetimes` service.
+
```ts
class Store {
lifetimes: LifetimesService;
}
interface LifetimesService {
- isExpired(url: string, method: HTTPMethod) {}
+ isHardExpired(identifier: StableDocumentIdentifier): boolean;
+ isSoftExpired(identifier: StableDocumentIdentifier): boolean;
}
```
@@ -489,6 +550,11 @@ Adapter and Serializer methods. If no adapter exists for the type (including no
handler would call `next`. In this manner an app can incrementally migrate request-handling to this
new paradigm on a per-type basis as desired.
+The legacy handler would only attempt to handle requests with an `op` and no `url`. Requests with a `url`
+would be forwarded on via `next`. In this way, individual requests can be migrated away from legacy by
+either directly invoking `store.request` with the correct args or by utilizing a request builder which
+assigns the url to the request object.
+
The package `ember-data` would automatically configure this handler. If not using `ember-data`
this configuration would need to be done explicitly.
@@ -649,4 +715,5 @@ instead encouraging data-transformation to be done within the Adapter. In fact,
is fully possible today, we could just better document it and do nothing more. However, this
approach does not solve the need for more general request management, nor does it interact
well with common development paradigms such as GraphQL query building, nor does it allow us
-to introduce pagination-by-default.
\ No newline at end of file
+to introduce pagination-by-default, and finally it does very little to advance the goal of being
+a document centric cache.
\ No newline at end of file
diff --git a/text/0907-pnpm-support.md b/text/0907-pnpm-support.md
new file mode 100644
index 0000000000..98600de6d2
--- /dev/null
+++ b/text/0907-pnpm-support.md
@@ -0,0 +1,167 @@
+---
+stage: accepted
+start-date: 2023-03-06T14:09:00.000Z
+release-date: # In format YYYY-MM-DDT00:00:00.000Z
+release-versions:
+teams: # delete teams that aren't relevant
+ - cli
+ - learning
+prs:
+ accepted: https://github.com/emberjs/rfcs/pull/907
+project-link:
+suite:
+---
+
+
+
+# `pnpm` support
+
+## Summary
+
+Enable Ember CLI users to opt into using `pnpm` for package management.
+
+## Motivation
+
+[`pnpm`](https://pnpm.io/) is a popular alternative to both `npm` and `yarn` that prioritizes correctness, especially for `peerDependencies` and monorepos.
+
+`pnpm` has very active maintainance, support, and financial funding.
+Their [website](https://pnpm.io/) states that `pnpm` is:
+ - Fast: `pnpm` is up to 2x faster than the alternatives
+ - Efficient: Files inside `node_modules` are cloned or hard linked from a single content-addressable storage
+ - Supports monorepos: `pnpm` has built-in support for multiple packages in a repository
+ - Strict: `pnpm` creates a non-flat `node_modules` by default, so code has no access to arbitrary packages.
+
+For folks with lots of projects on their computers, `pnpm` is _extremely_ space-efficient.
+Where `npm` and `yarn` would duplicate `node_modules` per-project, `pnpm` will only download a package (at a specific version) once across your whole machine.
+
+Additionally, `npm` and `yarn` repeatedly have demonstrated that their strategies with `peerDependencies` are not correct, and it is vitally important we use and support a tool that can guide folks towards correctly creating addons. For example, `@embroider/macros` relies on node's resolution algorithm, so having `peerDependencies` resolved correctly is important for `dependencySatisfies` to work as expected in monorepos.
+
+Ember CLI currently only supports `npm` (default) and `yarn` for project initialization as well as various commands. At present, projects work with `pnpm`, but the tooling is unaware.
+
+
+
+## Detailed design
+
+Enabling `pnpm` is designed as opt-in to prevent disruptions to developer's current workflow, much the same as `yarn`.
+
+There are a few integration points that we must support for `pnpm` (and any package manager):
+ - `ember install`
+ - `ember init`, `ember new`, `ember addon`
+ - `ember try:one`, `ember try:each`
+ - generated C.I. configs
+ - Documenation
+
+### `ember install`
+
+There are two mechanisms through which to opt-in.
+The first one is the presence of a `pnpm-lock.yaml` file in the project root.
+
+The `pnpm-lock.yaml` file is generated by `pnpm` when you run `pnpm install` (or the shorter `pnpm i`),
+so we assume that its presence means the developer intends to use `pnpm` to manage their dependencies.
+
+Alternatively you, you can force Ember CLI to use `pnpm` with the `--pnpm` flag, and symmetrically,
+you can force Ember CLI to not use `pnpm` with the `--no-pnpm` flag.
+
+To recap:
+
+- `ember install ember-resources` with `pnpm-lock.yaml` present will use `pnpm`
+- `ember install ember-resources` without `pnpm-lock.yaml` present will use npm
+- `ember install ember-resources --pnpm` will use `pnpm`
+- `ember install ember-resources --no-pnpm` will use npm
+
+### `ember init`, `ember new`, `ember addon`
+
+Since this triad of commands is generally ran before a project is set up, there is no `pnpm-lock.yaml` file presence to check.
+This means we are left with the `--pnpm`/`--no-pnpm` pair of flags, that will also be added to these commands:
+
+- `ember new my-app` will use npm
+- `ember new my-app --pnpm` will use `pnpm`
+
+The above also applies to `ember addon` and `ember init`, noting that `ember init` doesn't receive any arguments.
+
+#### `--skip-npm`
+
+The `--skip-npm` flag _actually means_ "skip installation of dependencies" when using `ember addon` and `ember new`,
+including skipping installation with both `npm` and `yarn`.
+This will need to be extended to also skip installation of dependencies when `pnpm` is used.
+
+For example:
+```bash
+ember new my-app --pnpm --skip-npm
+```
+
+
+### `ember try:one`, `ember try:each`
+
+At the time of writing this RFC, `ember-try` already supports `pnpm`, but it is undocumented in [the README](https://github.com/ember-cli/ember-try).
+Documentation will need to be added to the README,
+as well as the relevant `ember-cli` blueprints will need to correctly configure `usePnpm: true` in the `ember-try.js` config file when the `pnpm` flag is present.
+
+
+### generated C.I. configs
+
+At the time of writing this RFC, `ember-cli` supports two C.I. environments: Travis and GitHub Actions.
+
+Both the `.travis.yml` and `.github/workflows/ci.yml` config files for relevant blueprints will need to support the `pnpm` option such that C.I. passes on new projects using `pnpm`.
+
+### for addons
+
+Addons should be stricter than defaults, so that they are good stewards of the ecosystem and don't leak accidental uncertainty to their consumers.
+
+In addon projects, the `.npmrc` will need the following defaults:
+```
+# all peer dependencies must be declared or forwarded to the consumer
+auto-install-peers=false
+
+# we want true isolation in addons -- if a dependency is not declared, we want an error
+reslove-peers-from-workspace-root=false
+```
+
+### Documentation
+
+These pages presently mention `npm` / `yarn` and will need to be updated to include `pnpm`
+ - https://cli.emberjs.com/release/basic-use/assets-and-dependencies/
+ - https://guides.emberjs.com/release/addons-and-dependencies/
+
+## How we teach this
+
+The Ember Guides should be updated to reflect the new flags, where applicable,
+as well as the new behavior of `ember install` in the presence of a `pnpm-lock.yaml` -- though most of the guides use `ember` as the CLI tool for managing packages.
+
+We may want to consider updating the [tutorial](https://guides.emberjs.com/release/tutorial/part-1/orientation/) (and its automation) to use `pnpm`, as `npm` is very slow.
+
+
+In addition, the built-in instructions for `ember help` should be updated to reflect the new flags.
+
+
+## Drawbacks
+
+- `pnpm` is very strict about peers and what dependencies are allowed in a project and will error if a project's package.json is incorrect for a given scenario. `pnpm` is very clear about these errors and what to do for action items, but it means that we'll need to make sure that `pnpm` is tested in `ember-cli` when generating new projects so that we can be certain that folks' "first time experience" is smooth
+- There may be other package managers in the future, but we cannot see the future. There have been talks about making ember-cli somehow generically handle package-managers, but it is unknown how that would work, and is unneeded for now.
+
+
+## Alternatives
+
+- Figure out a way to generically handle any package manager
+- Continue with the partial pnpm support we have today
+
+## Unresolved questions
+
+- Are there any other references in the guides to `npm` or `yarn`?
+ The only place I could find that _mentioned_ `yarn` is here: https://guides.emberjs.com/release/addons-and-dependencies/
+- Is there a `--package-manager` flag / option in `ember-cli`? for blueprint authors, that may be useful.
+- Should `--skip-npm` be aliased to `--skip-install`?
+
+
diff --git a/text/0931-template-compiler-api.md b/text/0931-template-compiler-api.md
new file mode 100644
index 0000000000..8796f9eff8
--- /dev/null
+++ b/text/0931-template-compiler-api.md
@@ -0,0 +1,436 @@
+---
+stage: accepted
+start-date: 2023-05-31
+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: https://github.com/emberjs/rfcs/pull/931
+project-link:
+suite:
+---
+
+
+
+# JS Representation of Template Tag
+
+## Summary
+
+Formalize a Javascript-spec-compliant representation of template tag.
+
+## Motivation
+
+The goal of this RFC is to improve the plain-Javascript representation of the Template Tag (aka "first-class component templates") feature in order to:
+
+- reduce the number and complexity of API calls required to represent a component
+- efficiently coordinate between different layers of build-time and static-analysis tooling that need to use preprocessing to understand our GJS syntax extensions.
+- avoid exposing a "bare template" as a user-visible value
+- provide a declarative way to opt-in to run-time (as opposed to build-time) template compilation.
+- enable support for class private fields in components
+
+As an illustrative example, currently this template tag expression:
+
+```js
+let x = Hello {{ message }};
+```
+
+Has the plain javascript representation:
+
+```js
+import { precompileTemplate } from "@ember/component";
+import templateOnlyComponent from "@ember/component/template-only";
+import { setComponentTemplate } from "@ember/component";
+let x = setComponentTemplate(
+ precompileTemplate("Hello {{message}}", {
+ strictMode: true,
+ scope: () => ({ message }),
+ }),
+ templateOnlyComponent()
+);
+```
+
+This RFC proposes simplifying the above case to:
+
+```js
+import { template } from "@ember/template-compiler";
+let x = template("Hello {{message}}", {
+ scope: () => ({ message }),
+});
+```
+
+As a second illustrative example, currently this class member template:
+
+```js
+class Example extends Component {
+ Hello {{message}}
+}
+```
+
+Has the plain javascript representation:
+
+```js
+import { precompileTemplate } from "@ember/component";
+import { setComponentTemplate } from "@ember/component";
+class Example extends Component {}
+setComponentTemplate(
+ precompileTemplate("Hello {{message}}", {
+ strictMode: true,
+ scope: () => ({ message }),
+ }),
+ Example
+);
+```
+
+This RFC proposes simplifying the above case to:
+
+```js
+import { template } from "@ember/template-compiler";
+class Example extends Component {
+ static {
+ template(
+ "Hello {{message}}",
+ {
+ component: this,
+ scope: () => ({ message }),
+ },
+ );
+ }
+}
+```
+
+## Detailed design
+
+This RFC introduces two new importable APIs:
+
+```js
+// The ahead-of-time template compiler:
+import { template } from "@ember/template-compiler";
+
+// The runtime template compiler:
+import { template } from "@ember/template-compiler/runtime";
+```
+
+They are intended to be drop-in replacements for each other _except_ for the differences summarized in this table:
+
+| | Template Contents | Scope Param | Syntax Errors | Payload |
+| ------------- | ---------------------- | -------------------------------------------- | ------------------------ | ---------------- |
+| Ahead-of-Time | Restricted to literals | Restricted to a few explicitly-allowed forms | Stops your build | Smaller & Faster |
+| Runtime | Unrestricted | Unrestricted | Can by caught at runtime | Larger & Slower |
+
+By putting these two implementations in different importable modules, the problem of "how do you opt-in to including the template compiler in your app?" goes away. If you import it, you will have it, if you don't, you won't.
+
+The remainder of this design only uses examples with the ahead-of-time template compiler, because everything about the runtime template compiler's API is the same.
+
+### Scope Access
+
+To give templates access to the relevant Javascript scope, we offer **two different forms** for two different use cases. A critical feature of this design is that *both forms* have valid Javascript syntax **and** semantics. That means they can actually run when you want them to, with no further processing. And they are fully understandable by all spec-compliant Javascript tools. This is in contrast with intermediate forms like `[__GLIMMER_TEMPLATE("")]` in the current ember-template-imports implementation or the proposed:
+
+```js
+template``
+```
+
+from [RFC 813](https://github.com/emberjs/rfcs/pull/813), which both lack any mechanism to access the surrounding scope, and therefore need "magic" beyond Javascript to make them run.
+
+#### Explicit Form
+
+The "Explicit Form" makes all data flow statically visible. It's the appropriate form to publish to NPM. To produce Explicit Form, build tools need to do a full parse of the template and a full lexical analysis of Javascript and Handlebars scopes.
+
+Examples of Explicit Form:
+
+```js
+import { template } from '@ember/template-compiler';
+
+// when nothing is needed from scope, no scope params are required:
+const Headline = template("{{yield}}
");
+
+// local variable access works the same as in current precompileTemplate
+const Section = template(
+ "{{@title}}",
+ {
+ scope: () => ({ Headline})
+ }
+);
+
+// in class member position, we can also put private fields in scope
+class extends Component {
+ static {
+ template(
+ "",
+ {
+ component: this,
+ scope: (instance) => ({
+ Section,
+ "#secret": instance.#secret
+ }),
+ },
+ )
+ }
+}
+```
+
+> This RFC is focused on making sure the scope accessors can do everything javascript can do, which is why we're including private fields. However, additional work beyond this RFC is required to make the template compiler correctly parse expressions like `{{this.#secret}}`.
+
+#### Implicit Form
+
+The "Implicit Form" is cheaper and easier to produce because it doesn't need to do any lexical analysis and doesn't need to parse the handlebars at all.
+
+The downside is that data flow is not all statically visible, because it relies on `eval`.
+
+Implicit Form has two key use cases:
+ - as an intermediate format between a preprocessor stage (which can eliminate all GJS special syntax and semantics) and the rest of a standard Javascript toolchain.
+ - as the implementation format in sandbox-like environments where dynamic code execution is the whole point.
+
+Examples of Implicit Form:
+
+```js
+import { template } from '@ember/template-compiler';
+
+// Notice that all of these have the exact same
+// `params` argument. It's always the same.
+// That's why it's easy to produce.
+
+const Headline = template(
+ "{{yield}}
",
+ {
+ eval() { return eval(arguments[0]); }
+ }
+);
+
+const Section = template(
+ "{{@title}}",
+ {
+ eval() { return eval(arguments[0]); }
+ }
+);
+
+class extends Component {
+ static {
+ template(
+ "",
+ {
+ component: this,
+ // this handles private fields just fine,
+ // see Appendix A.
+ eval() { return eval(arguments[0]); }
+ },
+ )
+ }
+}
+```
+
+> _eval seems bad, what about Content Security Policy?_
+> Typical apps never needs to actually _run_ the eval. This is a communication format between layers of build tooling. You _can_ run it, if you're making something like an interactive development sandbox. But that is a case that already requires `eval` anyway.
+
+> _Why `arguments[0]` instead of an explicit argument?_
+> If we picked a local name to use for the argument, we would shadow that name in the surrounding scope. Whereas `arguments` is already a keyword that exists for this purpose, and can never collide with other local bindings.
+
+
+### Type Signature
+
+```ts
+import { ComponentLike } from '@glint/template';
+
+declare function template(
+ templateContent: string,
+ params?: Params
+): ComponentLike;
+
+declare function template>(
+ templateContent: string,
+ params: Params
+): C;
+
+interface Params {
+ component?: ComponentClass;
+ strict?: boolean;
+ moduleName?: string;
+ eval?: () => Record;
+ scope?: (
+ instance: ComponentClass extends ComponentLike
+ ? InstanceType
+ : never
+ ) => Record;
+}
+
+```
+
+### Strict defaults to true
+
+Unlike `precompileTemplate`, our `strict` param defaults to true instead of false if it's not provided. This is aligned with the expectation that our main programming model is moving everyone toward handlebars strict mode by default.
+
+This also addresses the naming confusing between earlier RFCs (which used "strict") and the implementations in the ecosystem (which used "strictMode").
+
+### Always Returns a Component
+
+A key difference between `precompileTemplate` and our new `template` is that its return value is always a _component_, never a "bare template". In this sense, the implementation combines the jobs of `precompileTemplate` and `setComponentTemplate`.
+
+Bare templates are a historical concept that we'd like to move away from, in order to have fewer things to teach.
+
+When the `component` argument is passed, the return value is that backing class, with the template associated, just like `setComponentTemplate`. When the `component` argument is not provided, it creates and returns a new template-only component.
+
+> _Aren't route templates "bare templates"? What about them?
_
+> Yes, this RFC deliberately doesn't say anything about route templates. We expect a future routing RFC to use components to express what today's route templates express. This RFC also doesn't deprecate `precompileTemplate` yet -- although that will clearly be a good goal _after_ a new routing design addresses route templates.
+
+### Syntactic Restrictions
+
+The runtime template compiler has no syntactic restrictions.
+
+The ahead-of-time template compiler has syntactic restrictions on `templateContents`, `params.scope`, and `params.eval`.
+
+`templateContents` must be one of:
+
+- a string literal
+- a template literal with no expressions
+
+If provided, `params.scope` must be:
+
+- an arrow function expression or function expression
+ - that accepts zero or one arguments
+ - with body containing either
+ - an expression
+ - or a block statement that contains exactly one return statement
+ - where the return value is an object literal
+ - whose properties are all non-computed
+ - whose values are all either
+ - identifiers
+ - or private field member expressions on our argument identifier
+
+If provided, `params.eval` must be:
+ - an object method
+ - whose body contains exactly one return statment.
+ - where the return value must be exactly `eval(arguments[0])`.
+
+
+### Older things that are intentionally dropped
+
+`precompileTemplate` and its predecessors like `import { hbs } from 'ember-cli-htmlbars'` accepted some additional params that we are choosing not to keep.
+
+ - `insertRuntimeErrors`: instead you should use `@ember/template-compiler/runtime` and catch the exception thrown by `template()`.
+
+## How we teach this
+
+Mentioning these APIs is appropriate when introducing the template tag feature in the guides. We can explain template tag as a convenience over these lower-level APIs and show side-by-side how a given template tag "really means" a call to `template()`. These examples should probably use the Explicit Form.
+
+We can also mention that fully runtime template compilation is possible using `@ember/template-compiler/runtime` and show this example in Implicit Form, since that pairs well with a dynamic, REPL-like environment.
+
+## Drawbacks
+
+
+
+## Alternatives
+
+This RFC builds off the proposal in
+https://github.com/emberjs/rfcs/pull/813.
+
+The main difference is that RFC 813 offered a form:
+
+```
+template``
+```
+
+that converts `` into valid JS syntax _without_ working JS semantics.
+
+### Type Strictness Alternative
+
+The typescript types as written above don't prevent you from using `scope` and
+`eval` simultaneously. We could use more complicated types to enforce that. See [example](https://www.typescriptlang.org/play?#code/PTAEFpM0GUEsDmA7AhgFwK4CcCmoAmOAZnEnGnAPZIRTiggBQjcAtgA6VZqgDkAAggA2pNMBxIAbnCzVWEtOBysARjizghlSgGccvANwsOXHgG9QAYUomkCgDJwA1ngC+oIrNZ9BIpGLRldiF0fSM2Tm4rG047fw8vH2E2eSxgAGMY6gVDZkJ0kNwPDCR0impQQI4QwIAeGAA+AApGUEqgmpxrfwUALlAdNCxSBAAaVtB2FCwUVh0Afn6YIbgygFUyalqAUQAPYNXyAAVp2Z0AMS4AFQ7QgHkkIQBPUAAfUABJasO0E5m5hqMACU-Wstgczhw9QaRnyhTwRBKZSoNCqwVCtUsoBwu0CSHwOmi4P8jhctRQSCeDWaEzRnW6eLQ-UGwyQYwmKhQ6ScI0sIR0OlB4zaU3+CyWK3WmyQO32InSx1Oc0uWD5KAFACEuS58JiGm9Pt8Fb8lTpASCrEYWD0sEQuXgtXo-mdQGYJizVmhFqAVNohDgKUY2qxKPgMP6AHKzHDej1soyuZiidR29J4PYHY3O5XXW6BB7PbG4iQE0COnDZwluto6TLsGP9JpA0AAXn1ACUcJksLq42NQCUnEhKAB3JAwxiJ62BW320AZ+WKsUqtWa7U4XVYnF40tg2IQskUqmAtrbkuE8uV13uusN0BNUiDClp-ofJBP0o4K5Pet65tt0BO27XsVjZUYByQIdR3HBMkxtVM8C+TMlxdM98QvdUK1Na9T0kFAhEbf99UHYcx1gxg0B-PANhRABpHAnh0Worn1FtQCuIsd0JDj5lAFwnkoIh2NAfo7EkdQjEo+tYElNAaOoAAJHAhHrLBmPAq4AEEhCEVjhLQ0sjwmXiOIAMlAP4KHw2ogK4XU9gKDBCFqeSkHoxjmO03TwP4wT2IacCSkIEg7HwakJlEnBxKwSSqJk4YpRRZi9OWBK5OlJSVPUdT-KtEBaCgeddlmYIcEJOh6CYRhMnfHgtHSfDWz4EcuCEfBckYRFSnKGgcQKFA2CaQUBlAhBm2rUBcEwLAaAAAwAdQAC0oFAAEJQAAEjMHRXFm8j8sAGXJGHy-g0B0JR9i7RR1FkLBaFAEc8AapBhx4KYBR9Sg0EWgZb1ACl8GxPChAAOjBii8xwJpZtqdgGkyrRwLMMx6vw1xXFW2pgDh2akYmKL8KbHC2kmnBpt64GmmmBAMHkfwdAAbQABgAXSBINQFcYVfsoetCNbfUmgsVGhE5oFxlcdnmHywBQcgh6pQmh2H4eUxHXRRygGqEdHMexhpceJ2teZwfmAKF0ARbFiWpeOsA5bpRWYbhhHKCRjWtZ1rGcbx3DCfGiY2im7AKcJ6naYURnWaltoucnG3Zeq-lCT2Er-QARk488iX3fxagsTSsAQYaLFQeRmVGgx-oQE3QCQWm1Du9xXH1Cbq54ABiQhaybcvWQQYnA7J4PQFmrbvrgHQQepyfS5wdwJ82sxx8n6ep+r9wngDLBCUoNqQb2iYpxrNB0FWAf2gVwIlbh5G+pCNhKkWieQc7sr0nRr39fA5efZJmtb0bI+E+n4iL3gmn-U8ux+psG5hAvgr9ay8H6EA58OAX5d3SLAkmkssGSw5omKcCd+ofRTtUHAAAmTO6Fs7ZFzvnQuxda7Rl7iMSuKBq6iXruoTmnMW4TDbqABB6Qe4jT7ufIOM0R5jyfivBhINZ7z0JNI5+q92Fz1AJvaYO894HxjswY+p90jnwdlfJ2DRb5QPvt4Ze6C34fz1gbH+59fZCCJuAiBEiQ6uLDnTM6zM2Ycz-rHIJ0dOaTmlmAA6909B4FengCos0CZCFmj6ZSo5E7qmTsVMhABmKhu4shxDQHnUABci79BLsw0RrCq41zrqobhTc+FtAEUIkRfZxFD0kaPJeMip5yIUaABeyjZFFzXuozR29QC73wPvfB+iRqGOMZDa+5izB3wGtYvpQj7He0fhPX+f8jZ83vCgkBAswEBwgRsmBVy-68CEUgoZtVUG2NrFgmO4s7kMDAKdc6OJ6xlCUFgW691HqgGeq9SYmTPrfR5tJAGQN8JgxBt8pJbjvmD3Jki7xhdw7038aEoJuDQkEMYEAA) courtesy of @chriskrycho. I didn't go with that in the RFC because it's harder to read and explain, and I don't think this low-level API present much practical risk that people will be accidentally including both together.
+
+
+## Unresolved questions
+
+### Appendix A: Field Access Patterns
+
+This is a fully-working example that can run in a browser. It uses a toy rendering engine just to illustrate how scope access is working.
+
+```html
+
+```