From 5d24e4a56cb987d73498f5ec40f35f0053b44fa0 Mon Sep 17 00:00:00 2001 From: Mehul Kiran Chaudhari Date: Fri, 22 Jul 2022 11:40:45 +0530 Subject: [PATCH 001/292] add: standardize npm yarn use RFC --- images/ember_test.png | Bin 0 -> 15853 bytes images/npm_test.png | Bin 0 -> 26486 bytes text/0000-standardize-use-npm-yarn.md | 112 ++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 images/ember_test.png create mode 100644 images/npm_test.png create mode 100644 text/0000-standardize-use-npm-yarn.md diff --git a/images/ember_test.png b/images/ember_test.png new file mode 100644 index 0000000000000000000000000000000000000000..99a50b8f9b593a4f0b07f67f44406725e47e697c GIT binary patch literal 15853 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 Fe*yVDA;JIv literal 0 HcmV?d00001 diff --git a/images/npm_test.png b/images/npm_test.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd16e7c6daf0694ddf4740096d42278c80005ad GIT binary patch literal 26486 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 + +# +Standardize the use of yarn and npm scripts in the Ember experience + +## Summary + +This change encourages developers to use `npm` or `yarn` +for certain commands when working with Ember +applications, rather than using global Ember CLI commands like `ember serve`. +This aligns Ember with norms in the JavaScript community, and +helps in reducing the confusion around Ember-specific commands. + +## Motivation + +In many JavaScript projects, the following commands are very common: + +``` +npm start +npm test +``` + +These scripts are defined in the `package.json` of Ember apps, however, +Ember's documentation tells developers to run these commands instead: + +``` +ember serve +ember test +``` + +Notably, `ember test` and `npm test` give different results. + +When we run `ember test`, it sets the environment to test and performs Ember.onerror validation by default. +Whereas, In the case of `npm test`, there is an abstraction of the underlying commands that allows the user to run extra checks such as lint tests across the files and finally performs `ember test`. +This is useful in carrying on a sequence of instructions and using them without having to worry about how they function behind the hood. +As a result, a lot of developer time is saved and it also reduces the human error that might have been made if the abstract tooling was not used. + +`ember test` +![Ember test](/images/ember_test.png) + +`npm test` +![Npm test](/images/npm_test.png) + +If documentation encouraged using `yarn` or `npm`, this would allow developers to customize the scripts +themselves while also having a standard command that everyone can run in any project +and get an expected output, regardless of what's going on under the hood. + +Consider cases where the author of an addon sets up yarn test to run with ember-exam. +Un such cases, one shouldn't be manually changing the default documentation for a script that already existed. + +In another case of using the `package.json` script for start/test, it allows teams to abstract details about their specific dev environment, +which makes developers' jobs easier. They can use "yarn start" or +"pnpm start" without actually having to know which command starts the server. +Moreover, using tooling abstraction provided by npm/yarn helps in staying consistent with industry standards rather than having to use bespoke +tools. + +## Detailed design + +This will involve two steps + +1. We should decide whether we want a Standardize the use of yarn/npm scripts. + +2. Then we make the changes in readmes, contributing guides, CLI output, and in learning docs. + +## How we teach this + +The following resources would need to change: + +* Ember-cli guides +* Ember guides +* Ember API documentation +* The Super Rentals tutorial +* Readme.md and contributing.md of repos +* Blueprints in ember-cli + +## 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. +https://github.com/ember-cli/ember-cli/issues/8969#issuecomment-1167894022 + +> There are tradeoffs to choosing any path, please attempt to identify them here. + +## Alternatives + +* No change + +## Unresolved questions + +* How does the difference between yarn 1, 2, and 3 affect us if we made this change? +* Should we show yarn and npm for every example? \ No newline at end of file From 95f23023f515b8d6bbe1c8de8b1fac1908c62279 Mon Sep 17 00:00:00 2001 From: Mehul Kiran Chaudhari Date: Fri, 22 Jul 2022 19:06:20 +0530 Subject: [PATCH 002/292] updated PR link --- text/0000-standardize-use-npm-yarn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-standardize-use-npm-yarn.md b/text/0000-standardize-use-npm-yarn.md index 9d4680b40a..17bc2deb70 100644 --- a/text/0000-standardize-use-npm-yarn.md +++ b/text/0000-standardize-use-npm-yarn.md @@ -6,7 +6,7 @@ Release Versions: ember-source: vX.Y.Z ember-data: vX.Y.Z Relevant Team(s): Learning team, CLU -RFC PR: +RFC PR: https://github.com/emberjs/rfcs/pull/831 --- + +# Introduce a Wildcard Module Import API + +## Summary + +Introduce `import.meta.glob()` for use in all Ember apps and addons. + +## Motivation + +This RFC is siblings with [an RFC](#fixme) that deprecates all usage of Ember's traditional AMD infrastructure. That necessarily means we will remove `requirejs.entries` and `requirejs._eak_seen`. So we need to explain what you're supposed to use instead if you need to enumerate modules. `import.meta.glob()` is one answer to that question. + +## Detailed design + +First, an illustrative example: + +```js +// If you type this in your app: +const widgets = import.meta.glob('./widgets/*.js') + +// It gets automatically converted into something like this: +const widgets = { + './widgets/first.js': () => import('./widgets/first.js'), + './widgets/second.js': () => import('./widgets/second.js'), +} +``` + +This design builds off [Vite's Glob Import Feature](https://vitejs.dev/guide/features.html#glob-import), but since that feature is non-standard and offers a rather wide API surface area, we're picking a well-defined subset that we're committed to supporting, not just under Vite but under all build tooling that we support, including today's classic builds. + +`import.meta.glob()` is a special function that: + - can only be used with a string-literal argument + - can only be invoked directly as `import.meta.glob()`. You cannot pass it as a value, nor can you pass `import.meta` as a value and then try to call `.glob()` on that. + +The string argument **must** start with `./` or `../`. Only relative imports are supported. + +Escaping your own package via repeated `../` is not allowed. + + - For Ember apps, your package is the `/app` directory. + - For classic (v1) Ember addons, your package is the `/addon` directory. + - For v2 Ember Addons, your package is your actual NPM package. + +### Pattern Matching Specifics + +The pattern always uses `/` as the path separator, regardless of operating system. + +No automatic file extension resolution is performed -- to match `.js`, your pattern should end in `.js`. + + - You should think of this happening *before* any transpilation renames your files. If you're authoring typescript, you should write `import.meta.glob('./files/*.ts')` and it will give you back an object whose keys also end in `".ts"`. Similarly, when targeting `.gjs` or `.gts` files you should say so explicitly, like `import.meta.glob('./files/*.gjs')`. + + - However, due to the way template-only components work, you should think of this happening *after* the automatically-created Javascript representation of a template-only component is created. That is, if you want to import a directory full of components, even if some of them are template-only components represented by `.hbs` files, you should still `import.meta.glob('./components/*.js')` as that will match the automatically-created components. + + > An import with an explicit `.hbs` extension has a specific historical meaning that is *not* a component, it's a bare template. You almost never want to do that manually. It's an implementation detail of template co-location and a historical compatibility feature. So if you tried to do `import.meta.glob('./components/*.{js,hbs}')` you would get back a mix of components and things-that-are-not-really-components. + > + > Ultimately this is a concern that goes away once you adopt `.gjs` and that would be our recommendation going forward. + +`*` matches everything except: + - path separators + - names starting with "." (hidden files) + +`**` matches zero or more directories + +`?` matches any single character except path separators + +`[abc]`: a sequence of characters inside `[]` match any character in that sequence + +`{.js,.gjs}`: bash-style brace expansion + +### Lazy Loading + +`import.meta.glob()` is designed to work nicely in systems that lazily load code. However, it does not promise to *introduce* laziness where laziness does not already exist. + +When building with the classic build pipeline, all your own app code is always included in the bundle regardless of whether anyone imports it or not, and that remains true regardless of whether you use `import.meta.glob()` to access some modules. + +When building with Embroider, you can achieve lazy loading by using `import.meta.glob()` in combination with other features like `staticAppPaths` or `staticComponents`. + +The return value from `import.meta.glob()` is the same either way -- you always get functions that return `Promise`. + +### Replacing cross-package usages + +Historically, people have used `requirejs.entries` to have complete global access to everywhere from everywhere. `import.meta.glob` is deliberately more restrictive. For example, an addon cannot use `import.meta.glob` to load code out of the consuming application. Instead, addon authors will need to ask apps to pass them what they need. + +For example, a future version of `ember-cli-mirage` might tell app authors to put this code into their app and/or tests as a way to dynamically gain access to all the Mirage-specific models, adapters, serializers, etc that the user has written: + +```js +import { setup } from 'ember-cli-mirage'; + +setup(import.meta.glob('./mirage/**/*.js')) +``` + +Similarly, to do auto-discovery of ember-data models, an existing API like `discoverEmberDataModels()` would now accept them explicitly: + +```js +import { discoverEmberDataModels } from 'ember-cli-mirage'; + +discoverEmberDataModels(import.meta.glob('../models/*.{js,ts}')); +``` + +### Not allowed in publication format + +Addons are free to use `import.meta.glob` in their own code, but our tooling should implement it within the addon's own build, *before* publishing to NPM. `import.meta.glob` is not allowed in published addons on NPM. + +This greatly reduces future compatibility concerns, and it doesn't cost us anything in terms of flexibility, given that this spec says `import.meta.glob` is not allowed to cross package boundaries anyway. That is: at publish time, the full list of files that any `import.meta.glob()` expands into is statically known. + +### Types + +`import.meta.glob` has this signature: + +```ts +(pattern: string): Record> +``` + +When you know that the things you're importing have a shared interface, it will behoove you to cast to it: + +```ts +import { ComponentLike } from '@glimmer/template'; + +type Button = ComponentLike<{ + Args: { "onClick": () => void }, + Element: HTMLButtonElement, + Blocks: { default: [] } +}>; + +const buttons: Record> = import.meta.glob('./buttons/*.js'); +``` + + +## How we teach this + +We probably do not want to introduce this feature immediately to new users. In typical application development you won't often need it in your own code. So I don't think we need to bring it up in initial tutorial-level content. + +In the guides, I think we should add a section titled "ES Modules: Imports and Exports" to the page [Working with HTML, CSS, and JavaScript](https://guides.emberjs.com/release/getting-started/working-with-html-css-and-javascript/). Right now "Modules" exist as a bullet point that directs you to MDN. Similar to what we currently do with classes, we can add a dedicated section with more details. + +> ### Modules: Imports and Exports +> Ember apps are authored as JavaScript Modules (also know as "ES Modules"). By convention, your app's modules live in the `/app` directory, so if you see an import like `import Article from "your-app/models/article"`, that is referring to `/app/models/article.js`. If you install dependencies from NPM you can import from them as well. +> +> In a default Ember app, you can use dynamic `import()` to load third-party modules from NPM on demand, but you can't use it on your own app code. (That feature is available if you're building with [Embroider](https://github.com/embroider-build/embroider/), but that is not the default experience yet.) +> +> If you need to import many modules at once, Ember apps support an extension on top of ES modules called `import.meta.glob()`. For example, `import.meta.glob('./widgets/*.js')` will give you access to all the matching files. You can only use `import.meta.glob()` on files within your own package. + +The more detailed nuances of what `import.meta.glob` supports should be taught through good error messages. For example, all of these need to give clear explanation in an error messages: + + - trying to pass a non-string-literal to `import.meta.glob` + - trying to escape your package via `../` + - trying to import a pattern that doesn't start with `./` or `../` + +## Drawbacks + +As designed, this is not a drop-in replacement for the old system. Addons that relied on the looseness of the old system are going to need to make breaking changes to their public API to adapt to this change. I think those breaking changes are likely to be "constant cost" changes that are not expensive, even for big application, so I consider this worth it in order to get us into a more long-term-supportable position that is compatible with standard Javascript. + +## Alternatives + +### Globally powerful import.meta.glob + +We could attempt to allow more globally-powerful `import.meta.glob`. For example, it might be possible to make patterns starting with `/` always search the current application, even when an addon is asking. This would give addon authors more of the power they're used to having, but I think it's a much riskier feature to enable across the ecosystem. I'm not convinced we could make it work at reasonable cost in even all current build systems, never mind future ones. As written, this RFC has low-risk of causing compatibility problems in the future since the feature is not allowed in addon publication format. This makes it much easier to evolve the feature over time without breaking the universe. + +### Additional Vite feature space + +Features from Vite's implementation that I didn't incorporate because I don't want to sign us up to reimplement them in every build system: + + - absolute imports, starting with `/`. This is not a well-defined concept in today's Ember apps because they do not have a single directory representing the app's web root. + - eager mode, so that you gain synchronous access to the matching modules + - `as: 'raw'` which gives you the raw source code of matching files + - `as: 'url'` which gives you URLs to the matching files + - named imports mode, which allows you to ask for specific names instead of whole modules + - custom queries + +None of these are necessarily bad, but they aren't strictly necessary to meet our needs and a more minimalist spec is more likely to remain stable and supported over the long term. An app that's using Vite is free to use Vite-specific extensions if they choose to be accept that dependency. + From d13fb2b343045d1bc5ddb386ed0458510f290f15 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 26 Jul 2023 20:43:00 -0400 Subject: [PATCH 036/292] updating links --- text/0000-import-glob.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/text/0000-import-glob.md b/text/0000-import-glob.md index 743007c28a..ed1d741a1e 100644 --- a/text/0000-import-glob.md +++ b/text/0000-import-glob.md @@ -1,17 +1,15 @@ --- stage: accepted -start-date: # In format YYYY-MM-DDT00:00:00.000Z +start-date: 2023-07-27T00:42:02.085Z 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/939 project-link: suite: --- @@ -38,7 +36,7 @@ Introduce `import.meta.glob()` for use in all Ember apps and addons. ## Motivation -This RFC is siblings with [an RFC](#fixme) that deprecates all usage of Ember's traditional AMD infrastructure. That necessarily means we will remove `requirejs.entries` and `requirejs._eak_seen`. So we need to explain what you're supposed to use instead if you need to enumerate modules. `import.meta.glob()` is one answer to that question. +This RFC is siblings with [an RFC](https://github.com/emberjs/rfcs/pull/938) that deprecates all usage of Ember's traditional AMD infrastructure. That necessarily means we will remove `requirejs.entries` and `requirejs._eak_seen`. So we need to explain what you're supposed to use instead if you need to enumerate modules. `import.meta.glob()` is one answer to that question. ## Detailed design From 0dde02ede0854c95bec3f9f119b810990807694a Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Thu, 27 Jul 2023 09:54:48 -0400 Subject: [PATCH 037/292] renaming to match pr number --- text/{0000-import-glob.md => 0939-import-glob.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{0000-import-glob.md => 0939-import-glob.md} (100%) diff --git a/text/0000-import-glob.md b/text/0939-import-glob.md similarity index 100% rename from text/0000-import-glob.md rename to text/0939-import-glob.md From e84b77267f1301b8e8ce05784436d9a6873bc663 Mon Sep 17 00:00:00 2001 From: wagenet Date: Fri, 2 Jun 2023 18:53:49 +0000 Subject: [PATCH 038/292] Advance RFC {{ inputs.rfc-number }} to Stage ready-for-release --- text/0907-pnpm-support.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/text/0907-pnpm-support.md b/text/0907-pnpm-support.md index 98600de6d2..8a911ad096 100644 --- a/text/0907-pnpm-support.md +++ b/text/0907-pnpm-support.md @@ -1,15 +1,15 @@ --- -stage: accepted +stage: ready-for-release start-date: 2023-03-06T14:09:00.000Z -release-date: # In format YYYY-MM-DDT00:00:00.000Z +release-date: release-versions: -teams: # delete teams that aren't relevant +teams: - cli - learning prs: - accepted: https://github.com/emberjs/rfcs/pull/907 + accepted: 'https://github.com/emberjs/rfcs/pull/907' project-link: -suite: +suite: --- + +# Deprecate Support for Travis CI + +## Summary + +This RFC proposes to officially deprecate support for generating a Travis CI +config file when creating a new app or addon. + +## Motivation + +Since Travis CI announced the end of its unlimited support for open-source +projects, most of the (the entire?) Ember community has switched over to using +GitHub Actions instead. This basically leaves the `.travis.yml` files in the +`app` and `addon` blueprints unused. Even though the maintenance cost of keeping +these files around is pretty low, not having to maintain them would be even +better. It would make [PRs like this](https://github.com/ember-cli/ember-cli/pull/10222) +slightly less cumbersome. Also, since almost no one actually uses these files, +it becomes harder to know/ensure they are up to date and follow the current best +practices. + +## Transition Path + +We should: + +- Show a deprecation warning when creating a new app or addon using the +`--ci-provider=travis` option +- Show a deprecation warning when picking the `Travis CI` option during the +interactive new flow +- Add a comment to the `.travis.yml` files in the `app` and `addon` blueprints +mentioning that they are deprecated - Adding a comment is the easiest thing to +do implementation wise and people who _do_ wish to continue using Travis CI, can +simply remove the comment again + +## How We Teach This + +I _think_ we would only need to remove all references to Travis CI from the +learning materials. + +## Drawbacks + +Can't think of any at the moment. + +## Alternatives + +Continue supporting Travis CI. + +## Unresolved questions + +None at the moment. \ No newline at end of file From 6f830fa15446e35c31de766fd7ec3589a05364e0 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:31:03 -0400 Subject: [PATCH 055/292] Remove mentions of `--no-pnpm` as implementation was not explicitly done or needed --- text/0907-pnpm-support.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/text/0907-pnpm-support.md b/text/0907-pnpm-support.md index 136307e5b3..65165f6f2d 100644 --- a/text/0907-pnpm-support.md +++ b/text/0907-pnpm-support.md @@ -73,20 +73,18 @@ 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. +Alternatively you, you can force Ember CLI to use `pnpm` with the `--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: +This means we are left with the `--pnpm` flag, which will also be added to these commands: - `ember new my-app` will use npm - `ember new my-app --pnpm` will use `pnpm` From a838ed7c72fa0478be915119b82720386b6dd857 Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 3 Feb 2023 19:25:41 +0000 Subject: [PATCH 056/292] Advance RFC to Stage ready-for-release --- text/0774-implicit-record-route-loading.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/text/0774-implicit-record-route-loading.md b/text/0774-implicit-record-route-loading.md index 3a5ae917d5..27b5b6295e 100644 --- a/text/0774-implicit-record-route-loading.md +++ b/text/0774-implicit-record-route-loading.md @@ -1,12 +1,12 @@ --- -stage: accepted -start-date: 2021-11-14 -release-date: +stage: ready-for-release +start-date: 2021-11-14T00:00:00.000Z +release-date: release-versions: -teams: # delete teams that aren't relevant +teams: - framework prs: - accepted: https://github.com/emberjs/rfcs/pull/774 + accepted: 'https://github.com/emberjs/rfcs/pull/774' --- # Deprecate Implicit Record Loading in Routes From 194d987d2f639ab1736c846cff3716e95331a2a9 Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 3 Feb 2023 19:25:45 +0000 Subject: [PATCH 057/292] Update RFC 0774 ready-for-release PR URL --- text/0774-implicit-record-route-loading.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0774-implicit-record-route-loading.md b/text/0774-implicit-record-route-loading.md index 27b5b6295e..6d336ecf0d 100644 --- a/text/0774-implicit-record-route-loading.md +++ b/text/0774-implicit-record-route-loading.md @@ -7,6 +7,7 @@ teams: - framework prs: accepted: 'https://github.com/emberjs/rfcs/pull/774' + ready-for-release: 'https://github.com/emberjs/rfcs/pull/900' --- # Deprecate Implicit Record Loading in Routes From 33e864c8450399fde3cf4f381ecd4c1ac2036dd2 Mon Sep 17 00:00:00 2001 From: achambers Date: Fri, 1 Sep 2023 14:09:02 +0000 Subject: [PATCH 058/292] Advance RFC {{ inputs.rfc-number }} to Stage released --- text/0774-implicit-record-route-loading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0774-implicit-record-route-loading.md b/text/0774-implicit-record-route-loading.md index 6d336ecf0d..8b67d79a1d 100644 --- a/text/0774-implicit-record-route-loading.md +++ b/text/0774-implicit-record-route-loading.md @@ -1,5 +1,5 @@ --- -stage: ready-for-release +stage: released start-date: 2021-11-14T00:00:00.000Z release-date: release-versions: From 1a66928b07b39ca3fa9f57df8733581e0391f2ae Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 1 Sep 2023 14:09:05 +0000 Subject: [PATCH 059/292] Update RFC 0774 released PR URL --- text/0774-implicit-record-route-loading.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0774-implicit-record-route-loading.md b/text/0774-implicit-record-route-loading.md index 8b67d79a1d..467ac2d7b3 100644 --- a/text/0774-implicit-record-route-loading.md +++ b/text/0774-implicit-record-route-loading.md @@ -8,6 +8,7 @@ teams: prs: accepted: 'https://github.com/emberjs/rfcs/pull/774' ready-for-release: 'https://github.com/emberjs/rfcs/pull/900' + released: 'https://github.com/emberjs/rfcs/pull/955' --- # Deprecate Implicit Record Loading in Routes From d79666669bcfd4f6c873dd4c9dc6ef972dc2dba1 Mon Sep 17 00:00:00 2001 From: wagenet Date: Fri, 10 Mar 2023 19:54:28 +0000 Subject: [PATCH 060/292] Advance RFC {{ inputs.rfc-number }} to Stage ready-for-release --- text/0858-deprecate-ember-mocha.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0858-deprecate-ember-mocha.md b/text/0858-deprecate-ember-mocha.md index 69954784d9..cb84251d2c 100644 --- a/text/0858-deprecate-ember-mocha.md +++ b/text/0858-deprecate-ember-mocha.md @@ -1,14 +1,14 @@ --- -stage: accepted -start-date: 2022-11-08 +stage: ready-for-release +start-date: 2022-11-08T00:00:00.000Z release-date: release-versions: -teams: # delete teams that aren't relevant +teams: - data - framework - learning prs: - accepted: https://github.com/emberjs/rfcs/pull/858 + accepted: 'https://github.com/emberjs/rfcs/pull/858' project-link: --- From b6c0a8d7c46fd9bc0fe8800ecd3b18ab6f2d176b Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 10 Mar 2023 19:54:36 +0000 Subject: [PATCH 061/292] Update RFC 0858 ready-for-release PR URL --- text/0858-deprecate-ember-mocha.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0858-deprecate-ember-mocha.md b/text/0858-deprecate-ember-mocha.md index cb84251d2c..060c1ceb24 100644 --- a/text/0858-deprecate-ember-mocha.md +++ b/text/0858-deprecate-ember-mocha.md @@ -9,6 +9,7 @@ teams: - learning prs: accepted: 'https://github.com/emberjs/rfcs/pull/858' + ready-for-release: 'https://github.com/emberjs/rfcs/pull/908' project-link: --- From d8e29841c9329ebb9003ea125efcabf52f3ee348 Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 8 Sep 2023 18:33:28 +0000 Subject: [PATCH 062/292] Advance RFC {{ inputs.rfc-number }} to Stage released --- text/0858-deprecate-ember-mocha.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0858-deprecate-ember-mocha.md b/text/0858-deprecate-ember-mocha.md index 060c1ceb24..dd62334634 100644 --- a/text/0858-deprecate-ember-mocha.md +++ b/text/0858-deprecate-ember-mocha.md @@ -1,5 +1,5 @@ --- -stage: ready-for-release +stage: released start-date: 2022-11-08T00:00:00.000Z release-date: release-versions: From 02c6342431baa992e9c410a9e640a0b30f2bb1b9 Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 8 Sep 2023 18:33:31 +0000 Subject: [PATCH 063/292] Update RFC 0858 released PR URL --- text/0858-deprecate-ember-mocha.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0858-deprecate-ember-mocha.md b/text/0858-deprecate-ember-mocha.md index dd62334634..a05b356234 100644 --- a/text/0858-deprecate-ember-mocha.md +++ b/text/0858-deprecate-ember-mocha.md @@ -10,6 +10,7 @@ teams: prs: accepted: 'https://github.com/emberjs/rfcs/pull/858' ready-for-release: 'https://github.com/emberjs/rfcs/pull/908' + released: 'https://github.com/emberjs/rfcs/pull/956' project-link: --- From 1338ac3ba64fd113dbfd0a512e13acdeaf486135 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 8 Sep 2023 21:49:50 -0400 Subject: [PATCH 064/292] renaming file --- ...andardize-use-npm-yarn.md => 0831-standardize-use-npm-yarn.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{0000-standardize-use-npm-yarn.md => 0831-standardize-use-npm-yarn.md} (100%) diff --git a/text/0000-standardize-use-npm-yarn.md b/text/0831-standardize-use-npm-yarn.md similarity index 100% rename from text/0000-standardize-use-npm-yarn.md rename to text/0831-standardize-use-npm-yarn.md From 3446fa410ecf35e6b82e88c5513acc7ddc5f6b4c Mon Sep 17 00:00:00 2001 From: Katie Gengler Date: Wed, 13 Sep 2023 17:40:17 -0400 Subject: [PATCH 065/292] Update automation to fix spurious "more than one RFC added or modified" - Fix an issue with interpolating RFC number in commits - Remove concurrency for "Newly added RFCs" CI in an attempt to fix most times where github shows a check as incomplete when it did run --- .../find-added-or-modified-rfcs/action.yml | 21 +++++-------------- .github/workflows/advance-rfc.yml | 2 -- .github/workflows/newly-added-rfcs.yml | 9 +------- .github/workflows/open-advancement-pr.yml | 2 +- 4 files changed, 7 insertions(+), 27 deletions(-) diff --git a/.github/actions/find-added-or-modified-rfcs/action.yml b/.github/actions/find-added-or-modified-rfcs/action.yml index df1c02ad8a..ade433494b 100644 --- a/.github/actions/find-added-or-modified-rfcs/action.yml +++ b/.github/actions/find-added-or-modified-rfcs/action.yml @@ -17,31 +17,20 @@ outputs: value: ${{ steps.modified-rfc.outputs.path }} modified-rfcs-count: description: "The count of how many RFCs were added or modified" - value: ${{ steps.counts.outputs.all_changed }} + value: ${{ steps.rfcs.outputs.all_changed_files_count }} added-rfcs-count: description: "The count of how many RFCs that were added" - value: ${{ steps.counts.outputs.added }} + value: ${{ steps.rfcs.outputs.added_files_count }} runs: using: "composite" steps: - name: Find added or modified RFCs id: rfcs - uses: tj-actions/changed-files@v31 + uses: tj-actions/changed-files@v39 with: - path: 'text' - json: 'true' - sha: ${{ inputs.sha }} - base_sha: ${{ inputs.base-sha }} - - - name: Get counts of changed and added RFCs - id: counts - shell: bash - run: | - changed_len=`echo "${{ steps.rfcs.outputs.all_changed_files }}" | jq '. | length'` - echo "all_changed=$changed_len" >> $GITHUB_OUTPUT - added_len=`echo "${{ steps.rfcs.outputs.added_files }}" | jq '. | length'` - echo "added=$added_len" >> $GITHUB_OUTPUT + files: text + json: true - name: Find modified or added RFC info id: modified-rfc diff --git a/.github/workflows/advance-rfc.yml b/.github/workflows/advance-rfc.yml index a084753ab8..cf9a4bebb5 100644 --- a/.github/workflows/advance-rfc.yml +++ b/.github/workflows/advance-rfc.yml @@ -26,8 +26,6 @@ jobs: - name: RFCs Added or Changed id: rfcs uses: ./.github/actions/find-added-or-modified-rfcs - with: - base-sha: ${{ github.event.before }} - name: Fail if more than 1 RFC is added or modified if: steps.rfcs.outputs.modified-rfcs-count > 1 diff --git a/.github/workflows/newly-added-rfcs.yml b/.github/workflows/newly-added-rfcs.yml index bf6266a2f4..bd33c68bce 100644 --- a/.github/workflows/newly-added-rfcs.yml +++ b/.github/workflows/newly-added-rfcs.yml @@ -8,13 +8,6 @@ on: paths: - 'text/*.md' -concurrency: - # Events within 5 minutes are not guaranteed to run in order, and so when removing S-Proposed and adding S-Exploring - # we can't guarantee that the run of the workflow will be the one where S-Exploring is added. Adding `github.event_name` - # to the concurrency allows both workflows to complete and the PR to eventually have successful checks. - group: newly-added-rfc-${{ github.head_ref || github.ref }}-${{ github.event_name }} - cancel-in-progress: true - jobs: check-rfcs: name: Does PR add RFCs? @@ -76,7 +69,7 @@ jobs: - name: Fail if more than 1 RFC is added or modified if: ${{ needs.check-rfcs.outputs.rfcs-changed > 1}} run: | - echo "::error::More than 1 RFC is added in this PR; will be unable to automatically open PRs for advancement" + echo "::error::More than 1 RFC is added or modified in this PR; will be unable to automatically open PRs for advancement" exit 1 frontmatter-stage-is-accepted: diff --git a/.github/workflows/open-advancement-pr.yml b/.github/workflows/open-advancement-pr.yml index 9141138b1b..14377a7ddf 100644 --- a/.github/workflows/open-advancement-pr.yml +++ b/.github/workflows/open-advancement-pr.yml @@ -61,7 +61,7 @@ jobs: uses: peter-evans/create-pull-request@v4.2.0 with: token: ${{ secrets.personal-access-token }} - commit-message: "Advance RFC {{ inputs.rfc-number }} to Stage ${{ inputs.new-stage }}" + commit-message: "Advance RFC ${{ inputs.rfc-number }} to Stage ${{ inputs.new-stage }}" add-paths: 'text' branch: "advance-rfc-${{ inputs.rfc-number }}" title: "Advance RFC #${{ inputs.rfc-number}} `${{ steps.pr-variables.outputs.title }}` to Stage ${{ steps.pr-variables.outputs.pretty-stage }}" From 467144c387f46073ffb36543fb84b17260cf50ec Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 15 Sep 2023 14:56:10 -0400 Subject: [PATCH 066/292] Update text/0858-deprecate-ember-mocha.md --- text/0858-deprecate-ember-mocha.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/text/0858-deprecate-ember-mocha.md b/text/0858-deprecate-ember-mocha.md index a05b356234..a1d8d81f61 100644 --- a/text/0858-deprecate-ember-mocha.md +++ b/text/0858-deprecate-ember-mocha.md @@ -1,8 +1,9 @@ --- stage: released start-date: 2022-11-08T00:00:00.000Z -release-date: -release-versions: +release-date: 2023-05-15T00:00:00.000Z +release-versions: + ember-source: 5.0.0 teams: - data - framework From 81d93003780fb7e65947f6072f5a257debe5900c Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 15 Sep 2023 18:58:03 +0000 Subject: [PATCH 067/292] Advance RFC 0831 to Stage ready-for-release --- text/0831-standardize-use-npm-yarn.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/0831-standardize-use-npm-yarn.md b/text/0831-standardize-use-npm-yarn.md index b557d692ea..0bc368e893 100644 --- a/text/0831-standardize-use-npm-yarn.md +++ b/text/0831-standardize-use-npm-yarn.md @@ -1,15 +1,15 @@ --- -stage: accepted -start-date: 2022-07-22 +stage: ready-for-release +start-date: 2022-07-22T00:00:00.000Z release-date: Unreleased release-versions: -teams: # delete teams that aren't relevant +teams: - cli - learning prs: - accepted: https://github.com/emberjs/rfcs/pull/831 -project-link: https://github.com/ember-learn/cli-guides/issues/272 -suite: + accepted: 'https://github.com/emberjs/rfcs/pull/831' +project-link: 'https://github.com/ember-learn/cli-guides/issues/272' +suite: --- -# +# Standardize use of scripts in package.json for common tasks + Standardize the use of yarn and npm scripts in the Ember experience ## Summary From 3f0252797d954faacb0d2e5b26e11e52ca396ede Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 13 Aug 2021 16:22:51 -0400 Subject: [PATCH 082/292] Asset Import Spec --- text/0763-asset-importing-spec.md | 200 ++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 text/0763-asset-importing-spec.md diff --git a/text/0763-asset-importing-spec.md b/text/0763-asset-importing-spec.md new file mode 100644 index 0000000000..899fe6fbd0 --- /dev/null +++ b/text/0763-asset-importing-spec.md @@ -0,0 +1,200 @@ +--- +Stage: Accepted +Start Date: 2021-08-13 +Release Date: Unreleased +Release Versions: + ember-source: vX.Y.Z + ember-data: vX.Y.Z +Relevant Team(s): Ember.js, Ember CLI +RFC PR: https://github.com/emberjs/rfcs/pull/763 +--- + + + +# Asset Import Spec + +## Summary + +This RFC defines standard semantics for what it means to depend on files that are not Javascript or CSS, like images, fonts, and other media. It proposes that when your code needs to refer to an asset, you should import it, which will give you back a valid URL: + +```js +import myImage from './hello.png'; +class extends Component { + myImage = myImage +} +``` +```hbs + +``` + +## Motivation + +Apps and addons often need to refer to images, fonts, etc from within their JS, HBS,CSS, or HTML files. These references need to remain correct even as both the referring file and the referred-to file go through a build that might include fingerprinting and optimization. + +Today, the ecosystem mostly relies on [broccoli-asset-rev](https://github.com/ember-cli/broccoli-asset-rev). But broccoli-asset-rev has some major architectural problems and it doesn't take advantage of the newer capabilities we have in ember-auto-import and embroider. + +The biggest problem with broccoli-asset-rev is that it cannot achieve full correctness because it tries to detect inter-file references within arbitrary source code that is not statically analyzable. It's easy to accidentally refactor working code into code that works in development and test and then fails in production! For example, assuming broccoli-asset-rev is configured to fingerprint PNG assets, this refactor will look correct until you get into production and then have broken images: + +```diff +class extends Component { +- iconURL = "/icons/happy.png" ++ get iconURL() { ++ return `/icons/${this.args.emotion}.png` ++ } +} +``` + +The regular expressions that broccoli-asset-rev uses to do reference rewriting are effectively un-editable at this point. Any possible change you'd make to them breaks somebody's app. + +Another problem with broccoli-asset-rev is that it's "push based", meaning it handles files because they exist, rather than handling files because somebody is actually consuming them. It can't detect unused assets and it can't detect missing assets at build time. It exposes the underlying implementation of how assets get delivered, making it hard to change later without breaking app code. + +And because broccoli-asset-rev exposes assumptions about the exact layout of the final build output, it's not compatible with Embroider. Embroider allows different Javascript packagers to optimize the app delivery in any spec-compliant way. For example, small images might get inlined as `data:` URIs, CSS `@import()` might get inlined or not, etc. All these concerns really need to be integrated into the Javascript packager, because asset handling affects app-wide hashing & fingerprinting. + +In contrast, a pull-based design that lets code declare what assets it needs and then not worry about how those assets will get delivered is safer and easier to change in the future. + +## Detailed design + +Inter-file references take many forms. Here is a guide to inter-file references organized by which kind of file is doing the referring ("From Type") and which type of file it's referring to ("To Type"). Only the row containing **Proposed** is new in this RFC: + +From Type | To Type | Example Syntax | Semantics +--------------------|-----------------------|--------|--- +JS | JS | `import { stuff } from 'thing';`| ECMA with NodeJS resolving rules +JS | CSS | `import 'thing/style.css';` | [Embroider Spec CSS Rule](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md#css) (1) +JS| Other Asset (2) | `import url from 'thing/icon.png';`| **Proposed** URL Rule (3) +CSS | CSS | `@import("thing/style.css")` | [W3C](https://drafts.csswg.org/css-cascade/#at-import) plus NodeJS resolving rules +CSS | Other | `url("thing/icon.png");` | W3C plus NodeJS resolving rules +HTML | JS | `` | W3C +HTML | CSS | `` | W3C +HTML | Other | `` | W3C + + +1. Importing a file with an explicit `.css` extension guarantees that the given CSS will be loaded into the DOM before your module executes. We do not define any exported values, this is purely for side-effect. This rule is not part of the present RFC, it was already in RFC 507. +2. "Other Asset" means this rule applies to any JS import of a path that ends in an explicit file extension that is not `.js` or `.css`, meaning: + ```js + function isOther(theImportedPath) { + let extension = /\.([^.\/]+)$/.exec(theImportedPath)?.[1]?.toLowerCase(); + return extension && !['js', 'css'].includes(extension); + } + ``` + +3. Importing any "Other Asset" file gives you back a `default` export containing a valid URL to that file. + +### What about references from HBS? + +This RFC doesn't treat HBS separately because as far as the module system is concerned, HBS files are just JS files. They're transpiled into JS before any module traversal can happen. This RFC doesn't define any static syntax for use in templates because we should use whatever syntax is designed to go with [Strict Mode](https://github.com/emberjs/rfcs/blob/master/text/0496-handlebars-strict-mode.md). For example, in GJS you could say: + +```js +import myImageURL from './my-image.png'; + +``` + +Today, the recommendation should be to use the JS part of a component to import assets and pass the resulting URLs to the HBS part of the component. + +Using only Ember public API, it would also be possible to write an optional preprocessor that allows you to experiment with any authoring format you like for accessing assets from HBS. For example, you could rewrite this: + +```hbs +{{!-- for illustration purposes only, this + hypothetical "import-asset" helper is + not being proposed by this RFC, it's + just something you could layer on top. --}} + +``` + +To this: +```js +// this line is the only thing in this file that is newly proposed by this RFC +import url0 from './thing.png'; +// all the rest of this is existing low-level API from other merged RFCS: +import { setComponentTemplate } from '@ember/component'; +import { precompileTemplate } from '@ember/template-compilation'; +import templateOnlyComponent from '@ember/component/template-only'; +export default setComponentTemplate( + precompileTemplate('', { scope: () => ({ url0 }) }), + templateOnlyComponent() +); +``` + +### Extensibility + +There are many alternative competing ways to assign extra semantics to imports of non-JS files. Examples include: + + - importing `.graphql` files, which get preprocessed into a Javascript value, possibly with the side effect of tracking that this particular query is in use. + - doing "CSS in JS" where an imported CSS file comes back as a Javascript value. + +This RFC is not in conflict with these patterns, because they should be understood as authoring formats that can be compiled into a spec-compliant format for compatibility with the rest of the build system and ecosystem. In both the above cases, a preprocessor would rewrite these files to Javascript, and then they get completely standard handling from that point forward. + +App authors are still always free to configure their build tool with this kind of preprocessing. They may need to be careful to restrict their customizations to only run on their own code. For example, if you want imports of `.png` files to have a special behavior in your app, that's possible, but you shouldn't rewrite `.png` imports in your addons because they're expecting the standard behavior defined by this RFC. On the other hand, it's fair game to configure your build tool in ways that preserve semantics. For example, configuring your build to run all imported `.png` files through a compression optimizer would be OK even for images imported by addons. + +Addon authors should ideally run any preprocessing before publishing. If they want apps to also do some preprocessing, they should provide explicit instructions & utilities for app authors to configure preprocessing in their particular build tool. They should not try to automatically rewrite the app's build system configuration, because that way lies madness and ecosystem-wide lock-in. + +### Asset file location compatibility + +Under the Embroider v2 spec, there are no implementation restrictions on where you could put assets in your package. You can access them via relative imports regardless, and consumers of your package can access them under your package name, following Node's standard rules (including the `exports` key in package.json). + +But in today's v1 addons and apps, there are some compatibility issues with assets and their paths. Your module namespace is rooted not at the root of your package, but at the `/app` folder. So importing "your-app/logo.png" logically means "/app/logo.png". You cannot address anything in the traditional "/public" folder. + +This is actually fine: anything in `/public` is still "push-based", meaning it will end up in your final build regardless of whether it's consumed by anything, and we really *guarantee* that it will be there. Whereas any assets you import following this new spec are only included when they're used, and their actual final URL is not guaranteed to take any particular form (they may even be `data:` URIs with no real file in the build output). So we don't want these new-style assets to be under `/public`. + +My recommendation is that any asset file that is used by a single component should be co-located beside that component. And assets that are shared throughout the app can go into directories like `/app/images`, etc. As long as you keep everything under `/app` it will all work as expected. + +### Build errors + +A benefit of this design is that trying to import an asset that does not exist is a build error. You cannot fail to notice if you accidentally delete an asset that is still in use somewhere in your app. + +### Upgrade path + +This proposal can be implemented with relatively small changes to ember-auto-import. Once you upgrade to a version of ember-auto-import with these features, you can begin importing assets and getting valid URLs for them. None of this breaks traditional asset handling including broccoli-asset-rev, so a gradual conversion is possible. + +This RFC does not suggest removing broccoli-asset-rev from the app blueprint, because it would still be responsible for fingerprinting all the classic build output files (app.js, vendor.js, etc). Since these files are not referenced from arbitrary code, the problematic aspects of broccoli-asset-rev don't apply to them. + +### Engines + +Engines have some complicated interactions with asset handling today. Under the current system the URL of each asset is exposed as public API, which means that assets from different packages can potentially fight over namespace. So extra care is needed to keep them apart and give them each a view of their own assets that is namespaced properly into the app-wide namespace of URLs. + +This problem doesn't exist for assets under this new proposal, because assets' precise runtime URLs are not public API. In fact, the build system would be free to notice if identical assets were included by more than one engine and deduplicate them as desired, without ever allowing an accidental collision. + +### Deliberately undefined behavior + +We deliberately do not define how inter-file references will be implemented. All we guarantee is that we will preserve inter-file reference semantics. + +Examples: + - build systems are free to replace any asset URL with a `data:` URI or even a blob at runtime. + - build systems are free to rewrite CSS `@import` to inline the contents (which happens to be today's default behavior) + - build systems can rewrite graphs of ES modules to single ES modules with the same semantics. + - build systems could implement `import "./some.css"` by generating Javascript that inserts an inline stylesheet or a link tag, or by inserting a link tag directly into the HTML. + +The exceptions where you can guarantee control over the URLs of assets are: + + - Files in `/public` are guaranteed to get URLs you can control (and manipulate with the traditional `fingerprint` options). + - The traditional `index.html`, `app.js` and `vendor.js` files (plus their test equivalents) continue to get URLs you can control in the usual way. + +## How we teach this + +ember-auto-import is already part of the default app blueprint, so newly-generated apps would gain these capabilities with no changes to their configuration or dependencies. That means tutorials & guides can show examples of, for example, how to include an image in a component. + +The [Assets and Dependencies docs](https://cli.emberjs.com/release/basic-use/assets-and-dependencies/) would change to show an example of importing a co-located asset directly into your code, in addition to mentioning that `/public` can be used for standalone assets that need their own URL. + +The [Asset Compilation docs](https://cli.emberjs.com/release/advanced-use/asset-compilation/) would change to explain that `/public` is for files that must live at particular URLs in your final app, whereas if you just need to make sure an asset is available to your code, you should keep it within `/app` and import it where it's used. The fingerprinting section can stay as it is for now, though people should be aware that it doesn't apply anymore under embroider, so as we approach enabling embroider by default there will be a future RFC that causes that whole section to go away. + +## Drawbacks + +One footgun is that the module namespace of today's Ember apps doesn't match the on-disk package layout. It would be natural to think that `/app/app.js` could `import "../public/thing.png"`, but this doesn't work because nothing above `/app` is addressable as a module. We should think about ways to provide helpful feedback if people try this. A lint rule against relative imports that reach above "/app" would be one possibility. + +## Alternatives + +We could choose to let apps each configure asset importing in their own way. This is easier to design because we avoid responsibility, but it pushes more complexity onto app authors and it makes life harder for addon authors who want to have some supported thing they can rely on across all apps. + +It would be possible to replace broccoli-asset-rev's unsafe reference rewriting with a runtime API, like a service plus helpers. This requires no build-time features and it would avoid assigning new semantics to ECMA `import`, but it wouldn't have the ability to analyze the asset dependency graph at build time. + +We could address the confusing module namespacing of the `/app` folder by making apps configure the `exports` key in package.json. This would also give them the option of putting importable assets in other locations that are not under `/app`, by extending the `exports` configuration. And while it is relatively simple to make ember-auto-import and Embroider respect `exports`, I don't think it would be easy to make the classic build respect `exports`. So that could introduce new sources of confusion. From 23eb213ac1197313a7f455934cae76ebd09afc3d Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 18 Aug 2021 13:12:39 -0600 Subject: [PATCH 083/292] Update 0763-asset-importing-spec.md --- text/0763-asset-importing-spec.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/0763-asset-importing-spec.md b/text/0763-asset-importing-spec.md index 899fe6fbd0..0edfe7b071 100644 --- a/text/0763-asset-importing-spec.md +++ b/text/0763-asset-importing-spec.md @@ -24,7 +24,7 @@ RFC PR: Fill this in with the URL for the Proposal RFC PR ## Summary -This RFC defines standard semantics for what it means to depend on files that are not Javascript or CSS, like images, fonts, and other media. It proposes that when your code needs to refer to an asset, you should import it, which will give you back a valid URL: +This RFC defines standard semantics for what it means to depend on files that are not JavaScript or CSS, like images, fonts, and other media. It proposes that when your code needs to refer to an asset, you should import it, which will give you back a valid URL: ```js import myImage from './hello.png'; @@ -57,7 +57,7 @@ The regular expressions that broccoli-asset-rev uses to do reference rewriting a Another problem with broccoli-asset-rev is that it's "push based", meaning it handles files because they exist, rather than handling files because somebody is actually consuming them. It can't detect unused assets and it can't detect missing assets at build time. It exposes the underlying implementation of how assets get delivered, making it hard to change later without breaking app code. -And because broccoli-asset-rev exposes assumptions about the exact layout of the final build output, it's not compatible with Embroider. Embroider allows different Javascript packagers to optimize the app delivery in any spec-compliant way. For example, small images might get inlined as `data:` URIs, CSS `@import()` might get inlined or not, etc. All these concerns really need to be integrated into the Javascript packager, because asset handling affects app-wide hashing & fingerprinting. +And because broccoli-asset-rev exposes assumptions about the exact layout of the final build output, it's not compatible with Embroider. Embroider allows different JavaScript packagers to optimize the app delivery in any spec-compliant way. For example, small images might get inlined as `data:` URIs, CSS `@import()` might get inlined or not, etc. All these concerns really need to be integrated into the JavaScript packager, because asset handling affects app-wide hashing & fingerprinting. In contrast, a pull-based design that lets code declare what assets it needs and then not worry about how those assets will get delivered is safer and easier to change in the future. @@ -129,10 +129,10 @@ export default setComponentTemplate( There are many alternative competing ways to assign extra semantics to imports of non-JS files. Examples include: - - importing `.graphql` files, which get preprocessed into a Javascript value, possibly with the side effect of tracking that this particular query is in use. - - doing "CSS in JS" where an imported CSS file comes back as a Javascript value. + - importing `.graphql` files, which get preprocessed into a JavaScript value, possibly with the side effect of tracking that this particular query is in use. + - doing "CSS in JS" where an imported CSS file comes back as a JavaScript value. -This RFC is not in conflict with these patterns, because they should be understood as authoring formats that can be compiled into a spec-compliant format for compatibility with the rest of the build system and ecosystem. In both the above cases, a preprocessor would rewrite these files to Javascript, and then they get completely standard handling from that point forward. +This RFC is not in conflict with these patterns, because they should be understood as authoring formats that can be compiled into a spec-compliant format for compatibility with the rest of the build system and ecosystem. In both the above cases, a preprocessor would rewrite these files to JavaScript, and then they get completely standard handling from that point forward. App authors are still always free to configure their build tool with this kind of preprocessing. They may need to be careful to restrict their customizations to only run on their own code. For example, if you want imports of `.png` files to have a special behavior in your app, that's possible, but you shouldn't rewrite `.png` imports in your addons because they're expecting the standard behavior defined by this RFC. On the other hand, it's fair game to configure your build tool in ways that preserve semantics. For example, configuring your build to run all imported `.png` files through a compression optimizer would be OK even for images imported by addons. @@ -172,7 +172,7 @@ Examples: - build systems are free to replace any asset URL with a `data:` URI or even a blob at runtime. - build systems are free to rewrite CSS `@import` to inline the contents (which happens to be today's default behavior) - build systems can rewrite graphs of ES modules to single ES modules with the same semantics. - - build systems could implement `import "./some.css"` by generating Javascript that inserts an inline stylesheet or a link tag, or by inserting a link tag directly into the HTML. + - build systems could implement `import "./some.css"` by generating JavaScript that inserts an inline stylesheet or a link tag, or by inserting a link tag directly into the HTML. The exceptions where you can guarantee control over the URLs of assets are: From 6ba4272eb18a2a65dc8b99f05167b2fa3cb03c61 Mon Sep 17 00:00:00 2001 From: Katie Gengler Date: Tue, 26 Sep 2023 10:48:00 -0400 Subject: [PATCH 084/292] Update Import Asset RFC to use import.meta.resolve --- text/0763-asset-importing-spec.md | 128 ++++++++++++++++++------------ 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/text/0763-asset-importing-spec.md b/text/0763-asset-importing-spec.md index 0edfe7b071..7fcb72b819 100644 --- a/text/0763-asset-importing-spec.md +++ b/text/0763-asset-importing-spec.md @@ -1,35 +1,43 @@ --- -Stage: Accepted -Start Date: 2021-08-13 -Release Date: Unreleased -Release Versions: - ember-source: vX.Y.Z - ember-data: vX.Y.Z -Relevant Team(s): Ember.js, Ember CLI -RFC PR: https://github.com/emberjs/rfcs/pull/763 +stage: accepted +start-date: 2021-08-13T00:00:00.000Z +release-date: # In format YYYY-MM-DDT00:00:00.000Z +release-versions: +teams: # delete teams that aren't relevant + - cli + - framework + - learning +prs: + accepted: https://github.com/emberjs/rfcs/pull/763 +project-link: +suite: --- - + + # Asset Import Spec ## Summary -This RFC defines standard semantics for what it means to depend on files that are not JavaScript or CSS, like images, fonts, and other media. It proposes that when your code needs to refer to an asset, you should import it, which will give you back a valid URL: +This RFC defines standard semantics for what it means to depend on files that are not JavaScript or CSS, like images, fonts, and other media. It proposes that when your code needs to refer to an asset, you use `import.meta.resolve` which returns a string that can be used to fetch the asset. ```js -import myImage from './hello.png'; class extends Component { - myImage = myImage + myImage = import.meta.resolve('./hello.png'); } ``` ```hbs @@ -38,7 +46,7 @@ class extends Component { ## Motivation -Apps and addons often need to refer to images, fonts, etc from within their JS, HBS,CSS, or HTML files. These references need to remain correct even as both the referring file and the referred-to file go through a build that might include fingerprinting and optimization. +Apps and addons often need to refer to images, fonts, etc from within their JS, HBS, CSS, or HTML files. These references need to remain correct even as both the referring file and the referred-to file go through a build that might include fingerprinting and optimization. Today, the ecosystem mostly relies on [broccoli-asset-rev](https://github.com/ember-cli/broccoli-asset-rev). But broccoli-asset-rev has some major architectural problems and it doesn't take advantage of the newer capabilities we have in ember-auto-import and embroider. @@ -69,7 +77,7 @@ From Type | To Type | Example Syntax | Semantics --------------------|-----------------------|--------|--- JS | JS | `import { stuff } from 'thing';`| ECMA with NodeJS resolving rules JS | CSS | `import 'thing/style.css';` | [Embroider Spec CSS Rule](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md#css) (1) -JS| Other Asset (2) | `import url from 'thing/icon.png';`| **Proposed** URL Rule (3) +JS| Other Asset (2) | `import.meta.resolve('thing/icon.png');`| **Proposed** URL Rule (3) CSS | CSS | `@import("thing/style.css")` | [W3C](https://drafts.csswg.org/css-cascade/#at-import) plus NodeJS resolving rules CSS | Other | `url("thing/icon.png");` | W3C plus NodeJS resolving rules HTML | JS | `` | W3C @@ -77,7 +85,7 @@ HTML | CSS | `` | W3C HTML | Other | `` | W3C -1. Importing a file with an explicit `.css` extension guarantees that the given CSS will be loaded into the DOM before your module executes. We do not define any exported values, this is purely for side-effect. This rule is not part of the present RFC, it was already in RFC 507. +1. Importing a file with an explicit `.css` extension guarantees that the given CSS will be loaded into the DOM before your module executes. We do not define any exported values, this is purely for side-effect. This rule is not part of the present RFC, it was already in [RFC 507](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md). 2. "Other Asset" means this rule applies to any JS import of a path that ends in an explicit file extension that is not `.js` or `.css`, meaning: ```js function isOther(theImportedPath) { @@ -86,20 +94,51 @@ HTML | Other | `` | W3C } ``` -3. Importing any "Other Asset" file gives you back a `default` export containing a valid URL to that file. +3. Calling `import.meta.resolve` with any "Other Asset" file gives you back a string containing a valid URL for that file. + +### `import.meta.resolve(moduleName)` + +`import.meta.resolve(moduleName)`[^1] is a function built-in to browsers that takes a `moduleName` and "returns a string corresponding to the path that would be imported if the argument were passed to import()." [^2] + +The build system will handle uses of `import.meta.resolve` when called with assets other than `.js` or .css` (see above). + +The argument `moduleName` supports a subset of dynamicism as defined [here](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md#supported-subset-of-dynamic-import-syntax). + +The argument `moduleName` must explicitly include the extension. + +For example, the following is valid as the build system can determine the files that possibly match the interpolation: + +```js +class extends Component { + get iconURL() { + return import.meta.resolve(`../icons/${this.args.locale}.png`) + } +} +``` + +Calling `import.meta.resolve` with an asset that does not exist will cause a build error. You cannot fail to notice if you accidentally delete an asset that is still in use somewhere in your app. + +#### Isn't it risky to "take over" a browser API? + +Yes and no. This [original proposal for this feature to WHATWG](https://github.com/whatwg/html/issues/3871#issue-346547968) envisioned build tools rewriting the expressions to provide asset optimizations. + +The built-in function can only resolve modules relative to the active script; by using Ember's build tools developers have no guarantee of where modules build to and the feature effectively cannot be used without those build tools understanding `import.meta.resolve`. + +[^1]: https://html.spec.whatwg.org/#integration-with-the-javascript-module-system +[^2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve ### What about references from HBS? This RFC doesn't treat HBS separately because as far as the module system is concerned, HBS files are just JS files. They're transpiled into JS before any module traversal can happen. This RFC doesn't define any static syntax for use in templates because we should use whatever syntax is designed to go with [Strict Mode](https://github.com/emberjs/rfcs/blob/master/text/0496-handlebars-strict-mode.md). For example, in GJS you could say: ```js -import myImageURL from './my-image.png'; +const myImageURL = import.meta.resolve('./my-image.png'); ``` -Today, the recommendation should be to use the JS part of a component to import assets and pass the resulting URLs to the HBS part of the component. +Today, the recommendation should be to use the JS part of a component to obtain the reference to assets and pass the resulting URLs to the HBS part of the component. Using only Ember public API, it would also be possible to write an optional preprocessor that allows you to experiment with any authoring format you like for accessing assets from HBS. For example, you could rewrite this: @@ -114,7 +153,8 @@ Using only Ember public API, it would also be possible to write an optional prep To this: ```js // this line is the only thing in this file that is newly proposed by this RFC -import url0 from './thing.png'; +const url0 = import.meta.resolve('./thing.png'); + // all the rest of this is existing low-level API from other merged RFCS: import { setComponentTemplate } from '@ember/component'; import { precompileTemplate } from '@ember/template-compilation'; @@ -125,16 +165,9 @@ export default setComponentTemplate( ); ``` -### Extensibility - -There are many alternative competing ways to assign extra semantics to imports of non-JS files. Examples include: - - - importing `.graphql` files, which get preprocessed into a JavaScript value, possibly with the side effect of tracking that this particular query is in use. - - doing "CSS in JS" where an imported CSS file comes back as a JavaScript value. +### Addons -This RFC is not in conflict with these patterns, because they should be understood as authoring formats that can be compiled into a spec-compliant format for compatibility with the rest of the build system and ecosystem. In both the above cases, a preprocessor would rewrite these files to JavaScript, and then they get completely standard handling from that point forward. - -App authors are still always free to configure their build tool with this kind of preprocessing. They may need to be careful to restrict their customizations to only run on their own code. For example, if you want imports of `.png` files to have a special behavior in your app, that's possible, but you shouldn't rewrite `.png` imports in your addons because they're expecting the standard behavior defined by this RFC. On the other hand, it's fair game to configure your build tool in ways that preserve semantics. For example, configuring your build to run all imported `.png` files through a compression optimizer would be OK even for images imported by addons. +This feature provides the capability for addons to reference assets relative to their own modules. Addon authors should ideally run any preprocessing before publishing. If they want apps to also do some preprocessing, they should provide explicit instructions & utilities for app authors to configure preprocessing in their particular build tool. They should not try to automatically rewrite the app's build system configuration, because that way lies madness and ecosystem-wide lock-in. @@ -148,13 +181,9 @@ This is actually fine: anything in `/public` is still "push-based", meaning it w My recommendation is that any asset file that is used by a single component should be co-located beside that component. And assets that are shared throughout the app can go into directories like `/app/images`, etc. As long as you keep everything under `/app` it will all work as expected. -### Build errors - -A benefit of this design is that trying to import an asset that does not exist is a build error. You cannot fail to notice if you accidentally delete an asset that is still in use somewhere in your app. - ### Upgrade path -This proposal can be implemented with relatively small changes to ember-auto-import. Once you upgrade to a version of ember-auto-import with these features, you can begin importing assets and getting valid URLs for them. None of this breaks traditional asset handling including broccoli-asset-rev, so a gradual conversion is possible. +This proposal can be implemented with relatively small changes to ember-auto-import. Once you upgrade to a version of ember-auto-import with these features, you can begin using `import.meta.resolve` and getting valid URLs for them. None of this breaks traditional asset handling including broccoli-asset-rev, so a gradual conversion is possible. This RFC does not suggest removing broccoli-asset-rev from the app blueprint, because it would still be responsible for fingerprinting all the classic build output files (app.js, vendor.js, etc). Since these files are not referenced from arbitrary code, the problematic aspects of broccoli-asset-rev don't apply to them. @@ -169,27 +198,26 @@ This problem doesn't exist for assets under this new proposal, because assets' p We deliberately do not define how inter-file references will be implemented. All we guarantee is that we will preserve inter-file reference semantics. Examples: - - build systems are free to replace any asset URL with a `data:` URI or even a blob at runtime. - - build systems are free to rewrite CSS `@import` to inline the contents (which happens to be today's default behavior) - - build systems can rewrite graphs of ES modules to single ES modules with the same semantics. - - build systems could implement `import "./some.css"` by generating JavaScript that inserts an inline stylesheet or a link tag, or by inserting a link tag directly into the HTML. + - build systems are free to replace any asset URL with a `data:` URI or even a blob at runtime. + - build systems are free to rewrite CSS `@import` to inline the contents (which happens to be today's default behavior) + - build systems can rewrite graphs of ES modules to single ES modules with the same semantics. The exceptions where you can guarantee control over the URLs of assets are: - - Files in `/public` are guaranteed to get URLs you can control (and manipulate with the traditional `fingerprint` options). - - The traditional `index.html`, `app.js` and `vendor.js` files (plus their test equivalents) continue to get URLs you can control in the usual way. + - Files in `/public` are guaranteed to get URLs you can control (and manipulate with the traditional `fingerprint` options). + - The traditional `index.html`, `app.js` and `vendor.js` files (plus their test equivalents) continue to get URLs you can control in the usual way. ## How we teach this ember-auto-import is already part of the default app blueprint, so newly-generated apps would gain these capabilities with no changes to their configuration or dependencies. That means tutorials & guides can show examples of, for example, how to include an image in a component. -The [Assets and Dependencies docs](https://cli.emberjs.com/release/basic-use/assets-and-dependencies/) would change to show an example of importing a co-located asset directly into your code, in addition to mentioning that `/public` can be used for standalone assets that need their own URL. +The [Assets and Dependencies docs](https://cli.emberjs.com/release/basic-use/assets-and-dependencies/) would change to show an example of using `import.meta.resolve` for an asset, in addition to mentioning that `/public` can be used for standalone assets that need their own URL. -The [Asset Compilation docs](https://cli.emberjs.com/release/advanced-use/asset-compilation/) would change to explain that `/public` is for files that must live at particular URLs in your final app, whereas if you just need to make sure an asset is available to your code, you should keep it within `/app` and import it where it's used. The fingerprinting section can stay as it is for now, though people should be aware that it doesn't apply anymore under embroider, so as we approach enabling embroider by default there will be a future RFC that causes that whole section to go away. +The [Asset Compilation docs](https://cli.emberjs.com/release/advanced-use/asset-compilation/) would change to explain that `/public` is for files that must live at particular URLs in your final app, whereas if you just need to make sure an asset is available to your code, you should keep it within `/app` and reference it with `import.meta.resolve` where it's used. The fingerprinting section can stay as it is for now, though people should be aware that it doesn't apply anymore under embroider, so as we approach enabling embroider by default there will be a future RFC that causes that whole section to go away. ## Drawbacks -One footgun is that the module namespace of today's Ember apps doesn't match the on-disk package layout. It would be natural to think that `/app/app.js` could `import "../public/thing.png"`, but this doesn't work because nothing above `/app` is addressable as a module. We should think about ways to provide helpful feedback if people try this. A lint rule against relative imports that reach above "/app" would be one possibility. +One footgun is that the module namespace of today's Ember apps doesn't match the on-disk package layout. It would be natural to think that `/app/app.js` could `import.meta.resolve('../public/thing.png')`, but this doesn't work because nothing above `/app` is addressable as a module. We should think about ways to provide helpful feedback if people try this. A lint rule against relative paths passed to `import.meta.resolve` that reach above "/app" would be one possibility. ## Alternatives From af3b63588cf00fa6b21383119891469fc61b6dea Mon Sep 17 00:00:00 2001 From: achambers Date: Fri, 1 Sep 2023 14:06:43 +0000 Subject: [PATCH 085/292] Advance RFC {{ inputs.rfc-number }} to Stage ready-for-release --- text/0918-deprecate-travis-ci-support.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index 96ab2e5c0a..a7013bc1ed 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -1,13 +1,13 @@ --- -stage: accepted +stage: ready-for-release start-date: 2023-03-25T00:00:00.000Z release-date: release-versions: -teams: # delete teams that aren't relevant +teams: - cli - learning prs: - accepted: https://github.com/emberjs/rfcs/pull/918 + accepted: 'https://github.com/emberjs/rfcs/pull/918' project-link: --- From 161102ad281479bd5ed175f067c3fc9b0a16b40b Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 1 Sep 2023 14:06:48 +0000 Subject: [PATCH 086/292] Update RFC 0918 ready-for-release PR URL --- text/0918-deprecate-travis-ci-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index a7013bc1ed..4770a27fad 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -8,6 +8,7 @@ teams: - learning prs: accepted: 'https://github.com/emberjs/rfcs/pull/918' + ready-for-release: 'https://github.com/emberjs/rfcs/pull/954' project-link: --- From 179769b1fbeeb2168eed1df4359009460a7124dc Mon Sep 17 00:00:00 2001 From: Katie Gengler Date: Fri, 6 Oct 2023 10:57:34 -0400 Subject: [PATCH 087/292] Correct reference to importing to import.meta.resolve, clarify some language --- text/0763-asset-importing-spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0763-asset-importing-spec.md b/text/0763-asset-importing-spec.md index 7fcb72b819..70d4994153 100644 --- a/text/0763-asset-importing-spec.md +++ b/text/0763-asset-importing-spec.md @@ -86,7 +86,7 @@ HTML | Other | `` | W3C 1. Importing a file with an explicit `.css` extension guarantees that the given CSS will be loaded into the DOM before your module executes. We do not define any exported values, this is purely for side-effect. This rule is not part of the present RFC, it was already in [RFC 507](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md). -2. "Other Asset" means this rule applies to any JS import of a path that ends in an explicit file extension that is not `.js` or `.css`, meaning: +2. "Other Asset" means this rule applies to any `import.meta.resolve` with a path that ends in an explicit file extension that is not `.js` or `.css`, meaning: ```js function isOther(theImportedPath) { let extension = /\.([^.\/]+)$/.exec(theImportedPath)?.[1]?.toLowerCase(); @@ -120,7 +120,7 @@ Calling `import.meta.resolve` with an asset that does not exist will cause a bui #### Isn't it risky to "take over" a browser API? -Yes and no. This [original proposal for this feature to WHATWG](https://github.com/whatwg/html/issues/3871#issue-346547968) envisioned build tools rewriting the expressions to provide asset optimizations. +No. This [original proposal for this feature to WHATWG](https://github.com/whatwg/html/issues/3871#issue-346547968) envisioned build tools rewriting the expressions to provide asset optimizations. As describe above, it is only taken over for "Other Assets" (any path that ends in an explicit file extension that is not `.js` or `.css`). The built-in function can only resolve modules relative to the active script; by using Ember's build tools developers have no guarantee of where modules build to and the feature effectively cannot be used without those build tools understanding `import.meta.resolve`. From 98e62fe0629b2530d4ea6b5bd90ac106af235406 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 13 Oct 2023 14:03:00 -0400 Subject: [PATCH 088/292] Clarifying "other assets" is really any asset --- text/0763-asset-importing-spec.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/text/0763-asset-importing-spec.md b/text/0763-asset-importing-spec.md index 70d4994153..a9934f66de 100644 --- a/text/0763-asset-importing-spec.md +++ b/text/0763-asset-importing-spec.md @@ -77,7 +77,7 @@ From Type | To Type | Example Syntax | Semantics --------------------|-----------------------|--------|--- JS | JS | `import { stuff } from 'thing';`| ECMA with NodeJS resolving rules JS | CSS | `import 'thing/style.css';` | [Embroider Spec CSS Rule](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md#css) (1) -JS| Other Asset (2) | `import.meta.resolve('thing/icon.png');`| **Proposed** URL Rule (3) +JS| Any Asset | `import.meta.resolve('thing/icon.png');`| **Proposed** URL Rule (2) CSS | CSS | `@import("thing/style.css")` | [W3C](https://drafts.csswg.org/css-cascade/#at-import) plus NodeJS resolving rules CSS | Other | `url("thing/icon.png");` | W3C plus NodeJS resolving rules HTML | JS | `` | W3C @@ -86,15 +86,8 @@ HTML | Other | `` | W3C 1. Importing a file with an explicit `.css` extension guarantees that the given CSS will be loaded into the DOM before your module executes. We do not define any exported values, this is purely for side-effect. This rule is not part of the present RFC, it was already in [RFC 507](https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md). -2. "Other Asset" means this rule applies to any `import.meta.resolve` with a path that ends in an explicit file extension that is not `.js` or `.css`, meaning: - ```js - function isOther(theImportedPath) { - let extension = /\.([^.\/]+)$/.exec(theImportedPath)?.[1]?.toLowerCase(); - return extension && !['js', 'css'].includes(extension); - } - ``` -3. Calling `import.meta.resolve` with any "Other Asset" file gives you back a string containing a valid URL for that file. +2. Calling `import.meta.resolve` with the path to any file gives you back a string containing a valid URL for that file. ### `import.meta.resolve(moduleName)` @@ -120,7 +113,7 @@ Calling `import.meta.resolve` with an asset that does not exist will cause a bui #### Isn't it risky to "take over" a browser API? -No. This [original proposal for this feature to WHATWG](https://github.com/whatwg/html/issues/3871#issue-346547968) envisioned build tools rewriting the expressions to provide asset optimizations. As describe above, it is only taken over for "Other Assets" (any path that ends in an explicit file extension that is not `.js` or `.css`). +No. This [original proposal for this feature to WHATWG](https://github.com/whatwg/html/issues/3871#issue-346547968) envisioned build tools rewriting the expressions to provide asset optimizations. The built-in function can only resolve modules relative to the active script; by using Ember's build tools developers have no guarantee of where modules build to and the feature effectively cannot be used without those build tools understanding `import.meta.resolve`. From 166023a2859c427a7f74ba2e0f7457c8b1486439 Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 13 Oct 2023 18:05:36 +0000 Subject: [PATCH 089/292] Advance RFC 0918 to Stage released --- text/0918-deprecate-travis-ci-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index 4770a27fad..888f276ce3 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -1,5 +1,5 @@ --- -stage: ready-for-release +stage: released start-date: 2023-03-25T00:00:00.000Z release-date: release-versions: From 6c6d6328411e3d5b1414651f029ed5f79527fda1 Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 13 Oct 2023 18:05:40 +0000 Subject: [PATCH 090/292] Update RFC 0918 released PR URL --- text/0918-deprecate-travis-ci-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index 888f276ce3..9cf0ab20b3 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -9,6 +9,7 @@ teams: prs: accepted: 'https://github.com/emberjs/rfcs/pull/918' ready-for-release: 'https://github.com/emberjs/rfcs/pull/954' + released: 'https://github.com/emberjs/rfcs/pull/978' project-link: --- From ce25b3c07e51247ef95227dc26f68fc5f6088ebe Mon Sep 17 00:00:00 2001 From: runspired Date: Fri, 22 Sep 2023 18:43:17 +0000 Subject: [PATCH 091/292] Advance RFC 0743 to Stage released --- text/0743-ember-data-deprecate-legacy-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0743-ember-data-deprecate-legacy-imports.md b/text/0743-ember-data-deprecate-legacy-imports.md index 4a4fcf291a..82b5efb259 100644 --- a/text/0743-ember-data-deprecate-legacy-imports.md +++ b/text/0743-ember-data-deprecate-legacy-imports.md @@ -1,5 +1,5 @@ --- -stage: ready-for-release +stage: released start-date: 2021-04-23T00:00:00.000Z release-date: release-versions: From 956aa79203a2cf366dead199e75187bb2439ac2c Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 22 Sep 2023 18:43:21 +0000 Subject: [PATCH 092/292] Update RFC 0743 released PR URL --- text/0743-ember-data-deprecate-legacy-imports.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0743-ember-data-deprecate-legacy-imports.md b/text/0743-ember-data-deprecate-legacy-imports.md index 82b5efb259..b2e38fc1ca 100644 --- a/text/0743-ember-data-deprecate-legacy-imports.md +++ b/text/0743-ember-data-deprecate-legacy-imports.md @@ -8,6 +8,7 @@ teams: prs: accepted: 'https://github.com/emberjs/rfcs/pull/743' ready-for-release: 'https://github.com/emberjs/rfcs/pull/947' + released: 'https://github.com/emberjs/rfcs/pull/969' --- # EmberData | Deprecate Legacy Imports From 6cdd6d4e2cb027785d2105733a8bf78ae0a4532e Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 13 Oct 2023 11:06:34 -0700 Subject: [PATCH 093/292] Apply suggestions from code review --- text/0743-ember-data-deprecate-legacy-imports.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0743-ember-data-deprecate-legacy-imports.md b/text/0743-ember-data-deprecate-legacy-imports.md index b2e38fc1ca..74ed18d392 100644 --- a/text/0743-ember-data-deprecate-legacy-imports.md +++ b/text/0743-ember-data-deprecate-legacy-imports.md @@ -1,8 +1,9 @@ --- stage: released start-date: 2021-04-23T00:00:00.000Z -release-date: +release-date: 2023-09-18T00:00:00.000Z release-versions: + ember-data: v5.3.0 teams: - data prs: From 5cce5b2d6080493cf84b704e18db4292d5fda4ce Mon Sep 17 00:00:00 2001 From: Katie Gengler Date: Fri, 20 Oct 2023 13:29:26 -0400 Subject: [PATCH 094/292] Update Release versions and date --- text/0918-deprecate-travis-ci-support.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index 9cf0ab20b3..168c55cda7 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -1,8 +1,9 @@ --- stage: released start-date: 2023-03-25T00:00:00.000Z -release-date: +release-date: 2023-12-11T00:00:00.000Z release-versions: + ember-cli: 5.5.0 teams: - cli - learning From 37e56c40e9e6f9240550a4bf6980abeb9e56405e Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 24 Oct 2023 10:27:30 -0700 Subject: [PATCH 095/292] Update runtime details for #931 This brings back some details about runtime template compilation that got lost from #813 --- text/0931-template-compiler-api.md | 50 +++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/text/0931-template-compiler-api.md b/text/0931-template-compiler-api.md index 8796f9eff8..f33788535f 100644 --- a/text/0931-template-compiler-api.md +++ b/text/0931-template-compiler-api.md @@ -118,26 +118,21 @@ class Example extends Component { ## Detailed design -This RFC introduces two new importable APIs: +This RFC introduces a new importable API: ```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: +The following sections will detail the semantics of this `template()` function. In typical usages, calls to this `template()` will be pre-processed at build time. By default, the template compiler is not included in the build, and if this function is called at runtime without the template compiler, it will throw an runtime error. -| | 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 | +However, there are use cases where runtime template compilation is desirable. For that purpose, we further introduce an importable module as an opt-in to include the template compiler: -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. +```js +import "@ember/template-compiler/runtime"; +``` -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. +When this module is imported into the build, it'll make the template compiler available, which allows the `template()` function to be called at runtime with compatible semantics as the build time pre-processing. Note that this is not an opt-in to disable or otherwise influence build-time compilation, it merely provides the necessary components for the `template()` function to be callable at runtime. See the dedicated section for additional details. ### Scope Access @@ -289,6 +284,31 @@ When the `component` argument is passed, the return value is that backing class, > _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. +### Runtime Compilation + +Ember always had the ability to compile template at runtime. However, because this incur significant costs and most apps do not benefit from it, this feature is disabled by default and requires an explicit opt-in to include the runtime compiler. + +Traditionally, this is done with: + +```js +// ember-cli-build.js +app.import("node_modules/ember-source/dist/ember-template-compiler.js"); +``` + +The new `"@ember/template-compiler/runtime"` module is interned to serve as a replacement for this, which better aligns with the direction we are headed. For example, this module can be imported on only the routes that needs it, and in conjunction with route-based code splitting that would reduce the performance hit on the initial load. + +Note that, even with the template compilation is available at runtime, the result of the compilations may be subtly different – applications may have custom glimmer/handlebars AST plugins in their build, and these plugins will not be available at runtime. + +Other than that, the signature and semantics of the `template()` function is intended to be identical between the build time pre-processing and runtime calls, and the build time pre-processing can be thought of as an optimization. In order to guarantee that the build-time optimization can be performed correctly, the next section details some syntactic restrictions. Sticking to the `"@ember/template-compiler"` import and adhering to the permissible subset of syntax enables authoring/emitting isomorphic code that is agnostic to where the compilation actually happens. + +That said, as a convenience, the `runtime` module will also re-export the `template()` function: + +```js +import { template } from "@ember/template-compiler/runtime"; +``` + +This guarantees that these `template` call will not be touched by any build-time preprocessing, relaxes any static checks for the syntactic restrictions and ensures the runtime compiler is available. + ### Syntactic Restrictions The runtime template compiler has no syntactic restrictions. @@ -318,6 +338,12 @@ If provided, `params.eval` must be: - whose body contains exactly one return statment. - where the return value must be exactly `eval(arguments[0])`. +In summary: + +| | Template Contents | Scope Param | Template Syntax Errors | Payload | +| ---------------------- | ------------------------------ | -------------------------------------------- | ------------------------ | ---------------- | +| Build-time compilation | Restricted to a string literal | Restricted to a few explicitly-allowed forms | Stops your build | Smaller & Faster | +| Runtime compilation | Unrestricted | Unrestricted | Can by caught at runtime | Larger & Slower | ### Older things that are intentionally dropped From 3f7a51f4d84674296a156bc581cc75e63393a154 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 27 Oct 2023 14:04:02 -0400 Subject: [PATCH 096/292] adding eager mode --- text/0939-import-glob.md | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/text/0939-import-glob.md b/text/0939-import-glob.md index ed1d741a1e..e66333bff0 100644 --- a/text/0939-import-glob.md +++ b/text/0939-import-glob.md @@ -56,7 +56,7 @@ const widgets = { This design builds off [Vite's Glob Import Feature](https://vitejs.dev/guide/features.html#glob-import), but since that feature is non-standard and offers a rather wide API surface area, we're picking a well-defined subset that we're committed to supporting, not just under Vite but under all build tooling that we support, including today's classic builds. `import.meta.glob()` is a special function that: - - can only be used with a string-literal argument + - can only be used with a string-literal first argument - can only be invoked directly as `import.meta.glob()`. You cannot pass it as a value, nor can you pass `import.meta` as a value and then try to call `.glob()` on that. The string argument **must** start with `./` or `../`. Only relative imports are supported. @@ -93,16 +93,35 @@ No automatic file extension resolution is performed -- to match `.js`, your patt `{.js,.gjs}`: bash-style brace expansion -### Lazy Loading +### Lazy Mode -`import.meta.glob()` is designed to work nicely in systems that lazily load code. However, it does not promise to *introduce* laziness where laziness does not already exist. - -When building with the classic build pipeline, all your own app code is always included in the bundle regardless of whether anyone imports it or not, and that remains true regardless of whether you use `import.meta.glob()` to access some modules. +By default, `import.meta.glob` gives you asynchronous access to the modules. This is designed to work nicely in systems that lazily load code. However, it does not promise to *introduce* laziness where laziness does not already exist. When building with the classic build pipeline, all your own app code is always included in the bundle regardless of whether anyone imports it or not, and that remains true regardless of whether you use `import.meta.glob()` to access some modules. When building with Embroider, you can achieve lazy loading by using `import.meta.glob()` in combination with other features like `staticAppPaths` or `staticComponents`. The return value from `import.meta.glob()` is the same either way -- you always get functions that return `Promise`. +### Eager Mode + +`import.meta.glob` supports an optional second argument. The only supported value at this time is the literal `{ eager: true }`. + +When eager is true, you get synchronous access to all the modules. These modules cannot be lazily loaded evaluated -- they will load and evaluate eagerly. + +For example: + +```js +// If you type this in your app: +const widgets = import.meta.glob('./widgets/*.js', { eager: true }) + +// It gets automatically converted into something like this: +import _w0 from './widgets/first.js'; +import _w1 from './widgets/second.js'; +const widgets = { + './widgets/first.js': _w0, + './widgets/second.js': _w1, +} +``` + ### Replacing cross-package usages Historically, people have used `requirejs.entries` to have complete global access to everywhere from everywhere. `import.meta.glob` is deliberately more restrictive. For example, an addon cannot use `import.meta.glob` to load code out of the consuming application. Instead, addon authors will need to ask apps to pass them what they need. @@ -134,7 +153,8 @@ This greatly reduces future compatibility concerns, and it doesn't cost us anyth `import.meta.glob` has this signature: ```ts -(pattern: string): Record> +(pattern: string): Record Promise> +(pattern: string, { eager: true }): Record ``` When you know that the things you're importing have a shared interface, it will behoove you to cast to it: @@ -148,7 +168,7 @@ type Button = ComponentLike<{ Blocks: { default: [] } }>; -const buttons: Record> = import.meta.glob('./buttons/*.js'); +const buttons: Record Promise<{ default: Button }>> = import.meta.glob('./buttons/*.js'); ``` @@ -186,7 +206,6 @@ We could attempt to allow more globally-powerful `import.meta.glob`. For example Features from Vite's implementation that I didn't incorporate because I don't want to sign us up to reimplement them in every build system: - absolute imports, starting with `/`. This is not a well-defined concept in today's Ember apps because they do not have a single directory representing the app's web root. - - eager mode, so that you gain synchronous access to the matching modules - `as: 'raw'` which gives you the raw source code of matching files - `as: 'url'` which gives you URLs to the matching files - named imports mode, which allows you to ask for specific names instead of whole modules From 1401660094edf4b1a382bf0e3879ed0fcee47ea9 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:38:57 -0400 Subject: [PATCH 097/292] initial --- text/0000-drop-safari-less-than-14.md | 92 +++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 text/0000-drop-safari-less-than-14.md diff --git a/text/0000-drop-safari-less-than-14.md b/text/0000-drop-safari-less-than-14.md new file mode 100644 index 0000000000..b7844691b0 --- /dev/null +++ b/text/0000-drop-safari-less-than-14.md @@ -0,0 +1,92 @@ +--- +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: +--- + + + + +# Drop support for Safari < v14.1 + +## Summary + +Until v14.1, Safari doesn't support: +- private class fields: https://caniuse.com/mdn-javascript_classes_private_class_fields + +Other features in the ecosystem, + +class static initialization blocks: +- Safari 16.4: https://caniuse.com/mdn-javascript_classes_static_initialization_blocks + +This RFC is not concernd with static initialization blocks, as those can easily by transpiled without adding a a lot of code. + +## Motivation + +Private class field transpilation has a big impact on the kind of code emitted. We want to transpile as little as possible -- ideally nothing, and let app users decide if they need to transpile further. + +## 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. + +## 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? + +## 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 + +> What other designs have been considered? What is the impact of not doing this? + +> This section could also include prior art, that is, how other frameworks in the same domain have solved this problem. + +## Unresolved questions + +> Optional, but suggested for first drafts. What parts of the design are still +TBD? From d51d2d461332bdf8adbba932a44a15c7adc6d0ef Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:40:40 -0400 Subject: [PATCH 098/292] Update frontmatter --- ...afari-less-than-14.md => 0984-drop-safari-less-than-14.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{0000-drop-safari-less-than-14.md => 0984-drop-safari-less-than-14.md} (95%) diff --git a/text/0000-drop-safari-less-than-14.md b/text/0984-drop-safari-less-than-14.md similarity index 95% rename from text/0000-drop-safari-less-than-14.md rename to text/0984-drop-safari-less-than-14.md index b7844691b0..2aa48e9a8c 100644 --- a/text/0000-drop-safari-less-than-14.md +++ b/text/0984-drop-safari-less-than-14.md @@ -1,6 +1,6 @@ --- stage: accepted -start-date: # In format YYYY-MM-DDT00:00:00.000Z +start-date: 2023-11-02T15:40:00.000Z release-date: # In format YYYY-MM-DDT00:00:00.000Z release-versions: teams: # delete teams that aren't relevant @@ -11,7 +11,7 @@ teams: # delete teams that aren't relevant - steering - typescript prs: - accepted: # Fill this in with the URL for the Proposal RFC PR + accepted: https://github.com/emberjs/rfcs/pull/984 project-link: suite: --- From cbfe861e42a63978398afc2fa041b2cbe3ffa712 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:38:00 -0400 Subject: [PATCH 099/292] specify --- text/0984-drop-safari-less-than-14.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0984-drop-safari-less-than-14.md b/text/0984-drop-safari-less-than-14.md index 2aa48e9a8c..ebd1132a73 100644 --- a/text/0984-drop-safari-less-than-14.md +++ b/text/0984-drop-safari-less-than-14.md @@ -51,6 +51,9 @@ Private class field transpilation has a big impact on the kind of code emitted. ## Detailed design +Ember v6 Will not support Safari < v14.1 + + > This is the bulk of the RFC. > Explain the design in enough detail for somebody From 76611b6cba6048748331ac0c43aa48d78cfe244f Mon Sep 17 00:00:00 2001 From: Aaron Chambers Date: Fri, 3 Nov 2023 14:42:11 +0000 Subject: [PATCH 100/292] Apply suggestions from code review Co-authored-by: MrChocolatine <47531779+MrChocolatine@users.noreply.github.com> --- text/0984-drop-safari-less-than-14.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0984-drop-safari-less-than-14.md b/text/0984-drop-safari-less-than-14.md index ebd1132a73..82fbdaa451 100644 --- a/text/0984-drop-safari-less-than-14.md +++ b/text/0984-drop-safari-less-than-14.md @@ -43,15 +43,15 @@ Other features in the ecosystem, class static initialization blocks: - Safari 16.4: https://caniuse.com/mdn-javascript_classes_static_initialization_blocks -This RFC is not concernd with static initialization blocks, as those can easily by transpiled without adding a a lot of code. +This RFC is not concerned with static initialization blocks, as those can easily be transpiled without adding a a lot of code. ## Motivation -Private class field transpilation has a big impact on the kind of code emitted. We want to transpile as little as possible -- ideally nothing, and let app users decide if they need to transpile further. +Private class fields transpilation has a big impact on the kind of code emitted. We want to transpile as little as possible -- ideally nothing, and let app users decide if they need to transpile further. ## Detailed design -Ember v6 Will not support Safari < v14.1 +Ember v6 will not support Safari < v14.1 > This is the bulk of the RFC. From 71cb213651964184f984c8ccb7998819b4b1e1c0 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sat, 13 Mar 2021 17:14:56 -0800 Subject: [PATCH 101/292] copy template --- 0000-dom-query-testing-interface.md | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 0000-dom-query-testing-interface.md diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md new file mode 100644 index 0000000000..66fc429833 --- /dev/null +++ b/0000-dom-query-testing-interface.md @@ -0,0 +1,74 @@ +--- +Stage: Accepted +Start Date: +Release Date: Unreleased +Release Versions: + ember-source: vX.Y.Z + ember-data: vX.Y.Z +Relevant Team(s): +RFC PR: +--- + + + +# + +## Summary + +> One paragraph explanation of the feature. + +## Motivation + +> Why are we doing this? What use cases does it support? What is the expected +outcome? + +## 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. + +## 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? + +## 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 + +> What other designs have been considered? What is the impact of not doing this? + +> This section could also include prior art, that is, how other frameworks in the same domain have solved this problem. + +## Unresolved questions + +> Optional, but suggested for first drafts. What parts of the design are still +TBD? From 61445ceceae48a844d81b3bf37f2a589d6bd94cf Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sat, 13 Mar 2021 18:22:26 -0800 Subject: [PATCH 102/292] Update 0000-template.md --- 0000-dom-query-testing-interface.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index 66fc429833..b8a4154956 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -1,11 +1,11 @@ --- Stage: Accepted -Start Date: +Start Date: 03/13/2021 Release Date: Unreleased Release Versions: ember-source: vX.Y.Z ember-data: vX.Y.Z -Relevant Team(s): +Relevant Team(s): Ember.js RFC PR: --- @@ -20,16 +20,25 @@ Relevant Team(s): Fill this in with the [team(s)](README.md#relevant-teams) to w RFC PR: Fill this in with the URL for the Proposal RFC PR --> -# +# DOM Element descriptor interface for test helpers ## Summary -> One paragraph explanation of the feature. +[@ember/test-helpers](https://github.com/emberjs/ember-test-helpers)' DOM helpers and [qunit-dom](https://github.com/simplabs/qunit-dom) accept either a selector or an HTMLElement as their DOM element descriptor, which is a pretty common pattern. This RFC proposes an interface that generalizes the notion of a DOM element descriptor that `@ember/test-helpers`' DOM helpers, `qunit-dom`, and other similar test support libraries in the Ember ecosystem can support, so page object implementations such as [fractal-page-object](https://github.com/bendemboski/fractal-page-object) and [ember-cli-page-object](http://ember-cli-page-object.js.org/) can implement the interface and integrate cleanly and ergonomically with these test support libraries. ## Motivation -> Why are we doing this? What use cases does it support? What is the expected -outcome? +Ember's testing ecosystem has converged on a single set of recommended DOM APIs. `@ember/test-helpers` provides the core value of implementing DOM interactions, while `qunit-dom` provides the core value of making assertions about DOM query results. They do _not_ (nor should they) provide the core value of advanced DOM querying -- they act on DOM elements, and do the simple baseline of supporting passed selectors and HTMLElements as descriptors of the DOM element(s) to act on. + +[Page Objects](https://martinfowler.com/bliki/PageObject.html) are a powerful and popular tool for making test code well organized, readable, and maintainable. The core value they provide is translating between a particular page's (or fragment of a page's or component's) rendered DOM and a functional/logical description of the page/fragment/component, in other words a page-specific advanced DOM query language. Supporting a clean integration of page objects with libraries like `@ember/test-helpers` and `qunit-dom` that act on DOM element descriptors would keep each focused on its core value, while supporting page objects as "first-class" DOM element descriptors. + +Currently `fractal-page-object` integrates with `@ember/test-helpers` and `qunit-dom` by exposing an `element` property on all page objects, and that works because their APIs accept HTMLElements. But using HTMLElements as descriptors has three major drawbacks compared to using selectors: + +1. It only supports single elements. While this isn't an issue with the `@ember/test-helpers` DOM APIs, in `qunit-dom` that means there's no way to use the multi-element assertions, like `assert.dom(document.querySelectorAll('.list-item')).exists({ count: 3 })`. +2. It does not produce a useful information when encountering an error/failure. For example, `await click('.does-not-exist')` errors with `Error: Element not found when calling click('.does-not-exist').`, while `await click(document.querySelector('.does-not-exist'))` errors with the less helpful `Error: Must pass an element or selector to 'click'` (because it doesn't have any other information to show -- all it knows is it was passed `null` instead of a selector or HTMLElement). Similarly, `assert.dom('.does-not-exist').exists()` produces the assertion message `Element .does-not-exist exists`, while `assert.dom(document.querySelector('.does-not-exist')).exists()` produces the less helpful `Element exists`. +3. It supports a much less ergonomic integration with page objects. In `fractal-page-object`, the integrations currently look like `await click(page.listItems[2].checkbox.element)` and `assert.dom(page.listItems[2].checkbox.element).isChecked()`, rather than `await click(page.listItems[2].checkbox)` and `assert.dom(page.listItems[2].checkbox).isChecked()`. While it may look like a minor difference, in practice it's quite a stumbling block as the mental model of page objects encourages users to think of page object nodes (e.g. `page.listItems[2].checkbox`) as a proxy for the DOM element(s) they describe, so forgetting to add the `.element` is extremely common, even for the author of the library! + +We can solve these by defining an DOM element descriptor interface that allows page object implementations, or even one-off test helpers written by application authors, to implement objects that can be passed to these test helpers and support everything that the selector API supports, specifically multiple elements and an optional description of the result set for messaging/debugging, and all without sacrificing developer ergonomics. ## Detailed design From 86b9b65beb46a90bcaa7744cb9e212b3d13951f9 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sat, 13 Mar 2021 21:47:09 -0800 Subject: [PATCH 103/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 115 ++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 16 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index b8a4154956..d7b9720f0c 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -42,26 +42,109 @@ We can solve these by defining an DOM element descriptor interface that allows p ## 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. +### The interfaces + +This RFC proposes implementing a very lightweight library that exports one `Symbol` and two interfaces: + +```ts +expost const ELEMENT_DESCRIPTOR = Symbol('element descriptor'); + +export interface IElementDescriptor { + element: Element | null; + elements: Element[]; + description?: string; +} + +export interface IElementDescriptorFactory { + [ELEMENT_DESCRIPTOR]: IElementDescriptor; +} +``` + +Then any API method that accepts a selector or element can also accept an `IElementDescriptor` or an `IElementDescriptorFactory`. For example a `click()` method like the one in `@ember/test-helpers` could be implemented as + +```ts +function click(target: string | Element | IElementDescriptor | IElementDescriptorFactory) { + if (!target) { + throw new Error('Must pass an element or selector to `click`.'); + } + + let element; + if (target instanceof Element) { + element = target; + } else if (typeof target === 'string') { + element = document.querySelector(target); + if (!element) { + throw new Error(`element not found when calling \`click(${selector})\`.`); + } + } else { + // IElementDescriptor or IElementDescriptorFactory + let descriptor = target[ELEMENT_DESCRIPTOR]; + if (!descriptor) { + descriptor = target; + } + + let element = descriptor.element; + if (!element) { + let description = descriptor.description; + if (description) { + throw new Error(`element not found when calling \`click()\` with descriptor: ${description}`); + } else { + throw new Error(`element not found when calling \`click()\` with descriptor`); + } + } + } + + element.click(); +} +``` + +To further illustrate, this is an (unnecessary) implementation of a descriptor and descriptor factory that just wrap a selector: + +```ts +class SelectorDescriptor implements IElementDescriptor { + constructor(private selector: string) {} + + get element(): Element | null { + return document.querySelector(this.selector); + } + + get elements(): Element[] { + return document.querySelectorAll(this.selector); + } + + get description(): string { + return this.selector; + } +} + +class SelectorDOMQuery implements IElementDescriptorFactory { + public elementDescriptor: IElementDescriptor; + + constructor(selector: string) { + this.elementDescriptor = new SelectorDescriptor(selector); + } +} +``` + +This RFC proposes to extend `@ember/test-helpers`'s DOM helpers and `qunit-dom`'s DOM assertions to accept arguments of type `IElementDescriptor` and `IElementDescriptorFactory` anywhere they accept a selector or an `Element`. + +### Why two interfaces? + +It would be possible to only have the `IElementDescriptor` interface and not the `IElementDescriptorFactory` interface. The short answer is that one of the use cases this RFC is aiming to address involves page objects implementing these interfaces, which means that the interface properties/methods would be in the same namespace as user-defined properties on the page objects. So the `IElementDescriptorFactory` interface exists to allow such page objects to only have to reserve one property name (`elementDescriptor`), rather than three (`element`, `elements`, and `description`). + +This is further discussed in the alternatives section of this RFC. + +### Where does this live? + +This would live in a new library, since it defines interfaces for integration between existing libraries, and is not actually dependent on/tied to Ember in any way. The library export the `ELEMENT_DESCRIPTOR` symbol and types of the interfaces. + +It could also potentially provide other types and helpers, such a `string | Element | IElementDescriptor | IElementDescriptorFactory` type or a `findElement()` method similar to the one in `@ember/test-helpers` that implements most of the element-finding logic in the `click()` example in the [the interfaces](#the-interfaces) section of this RFC. ## 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? +This is primarily taught through the API documentation of the various libraries that accept the interfaces, such as `@ember/test-helpers` and `qunit-dom`, and that implement the interfaces, such as `fractal-page-object`. In addition the new library proposed in this RFC would have documentation explaining the interfaces and how to author objects that implement them. -> How should this feature be introduced and taught to existing Ember -users? +The Ember guides would not need to be updated, as the default Ember testing methodology would be unaffected -- this would be added functionality for users using page object libraries, or implementing ad-hoc element descriptors in their tests. ## Drawbacks From 76586826bf885c78c60e7b9047b8be23c7d3d93c Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sat, 13 Mar 2021 22:04:06 -0800 Subject: [PATCH 104/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 53 +++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index d7b9720f0c..3db574e557 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -51,7 +51,7 @@ expost const ELEMENT_DESCRIPTOR = Symbol('element descriptor'); export interface IElementDescriptor { element: Element | null; - elements: Element[]; + elements?: Element[]; description?: string; } @@ -128,12 +128,29 @@ class SelectorDOMQuery implements IElementDescriptorFactory { This RFC proposes to extend `@ember/test-helpers`'s DOM helpers and `qunit-dom`'s DOM assertions to accept arguments of type `IElementDescriptor` and `IElementDescriptorFactory` anywhere they accept a selector or an `Element`. -### Why two interfaces? +### Why a symbol and two interfaces? -It would be possible to only have the `IElementDescriptor` interface and not the `IElementDescriptorFactory` interface. The short answer is that one of the use cases this RFC is aiming to address involves page objects implementing these interfaces, which means that the interface properties/methods would be in the same namespace as user-defined properties on the page objects. So the `IElementDescriptorFactory` interface exists to allow such page objects to only have to reserve one property name (`elementDescriptor`), rather than three (`element`, `elements`, and `description`). +It would be possible to only have the `IElementDescriptor` interface and not the `IElementDescriptorFactory` interface, and do away with the `ELEMENT_DESCRIPTOR` symbol. The short answer for why we have them is that one of the use cases this RFC is aiming to address involves page objects implementing these interfaces, which means that the interface properties/methods would be in the same namespace as user-defined properties on the page objects. So the `IElementDescriptorFactory` interface and `ELEMENT_DESCRIPTOR` symbol exist to allow such page objects to avoid namespace conflicts. This is further discussed in the alternatives section of this RFC. +### New use cases + +Page objects: + +```js +await click(pageObject.listItems[2].checkbox); +assert.dom(pageObject.listItems[2].checkbox).isChecked(); +``` + +Ad-hoc descriptors: + +```js +let element = someOtherLibrary.getGraphElement(); +await click({ element, description: 'graph element' }); +assert.dom({ element, description: 'graph element' }).hasClass('selected'); +``` + ### Where does this live? This would live in a new library, since it defines interfaces for integration between existing libraries, and is not actually dependent on/tied to Ember in any way. The library export the `ELEMENT_DESCRIPTOR` symbol and types of the interfaces. @@ -148,19 +165,35 @@ The Ember guides would not need to be updated, as the default Ember testing meth ## 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. +* This would increase the complexity of the DOM helper and assertion APIs +* This would add a small amount of extra maintenance cost to those libraries as all new code does ## Alternatives +### Do nothing + +This mainly improves developer ergonomics by allowing for better error/failure messaging and a simpler/more natural semantics when passing page objects to DOM helper/assertion methods. The only new functionality it enables is the ability for DOM helper/assertion methods to accept multi-element descriptors of types other than selectors. So we could do nothing and say what we have now is good enough. + +### One interface, three symbols + +We could get rid of the `IElementDescriptorProvider` interface and modify the `IElementDescriptor` interface to have symbol property keys instead of string property keys. This would simplify the overall picture, but would make implementing ad-hoc descriptors less ergonomic: + +```js +let element = someOtherLibrary.getGraphElement(); +await click({ element, description: 'graph element' }); +``` + +vs. + +```js +let element = someOtherLibrary.getGraphElement(); +await click({ [ELEMENT]: element, [DESCRIPTION]: 'graph element' }); +``` + > What other designs have been considered? What is the impact of not doing this? > This section could also include prior art, that is, how other frameworks in the same domain have solved this problem. ## Unresolved questions -> Optional, but suggested for first drafts. What parts of the design are still -TBD? +* What do we call the new library? From e7aa61ce67bffc53404af0c84f684250e4af1dce Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Sun, 14 Mar 2021 20:47:26 -0700 Subject: [PATCH 105/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index 3db574e557..02cdbd4c2a 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -24,21 +24,27 @@ RFC PR: Fill this in with the URL for the Proposal RFC PR ## Summary -[@ember/test-helpers](https://github.com/emberjs/ember-test-helpers)' DOM helpers and [qunit-dom](https://github.com/simplabs/qunit-dom) accept either a selector or an HTMLElement as their DOM element descriptor, which is a pretty common pattern. This RFC proposes an interface that generalizes the notion of a DOM element descriptor that `@ember/test-helpers`' DOM helpers, `qunit-dom`, and other similar test support libraries in the Ember ecosystem can support, so page object implementations such as [fractal-page-object](https://github.com/bendemboski/fractal-page-object) and [ember-cli-page-object](http://ember-cli-page-object.js.org/) can implement the interface and integrate cleanly and ergonomically with these test support libraries. +[@ember/test-helpers](https://github.com/emberjs/ember-test-helpers)' DOM helpers and [qunit-dom](https://github.com/simplabs/qunit-dom) accept either a selector or an `Element` as their DOM element descriptor, which is a pretty common pattern. This RFC proposes an interface that generalizes the notion of a DOM element descriptor that `@ember/test-helpers`' DOM helpers, `qunit-dom`, and other similar test support libraries in the Ember ecosystem can support, so page object implementations such as [fractal-page-object](https://github.com/bendemboski/fractal-page-object) and [ember-cli-page-object](http://ember-cli-page-object.js.org/) can implement the interface and integrate cleanly and ergonomically with these test support libraries. ## Motivation -Ember's testing ecosystem has converged on a single set of recommended DOM APIs. `@ember/test-helpers` provides the core value of implementing DOM interactions, while `qunit-dom` provides the core value of making assertions about DOM query results. They do _not_ (nor should they) provide the core value of advanced DOM querying -- they act on DOM elements, and do the simple baseline of supporting passed selectors and HTMLElements as descriptors of the DOM element(s) to act on. +In this RFC we'll use **DOM element descriptor** to mean a Javascript value that can be used to retrieve one or more `Element`s from a rendered DOM. Examples include a string containing a CSS selector, a direct reference to an `Element`, a function that returns an `Element` or `null`, a function that returns an array of `Element`s, etc. -[Page Objects](https://martinfowler.com/bliki/PageObject.html) are a powerful and popular tool for making test code well organized, readable, and maintainable. The core value they provide is translating between a particular page's (or fragment of a page's or component's) rendered DOM and a functional/logical description of the page/fragment/component, in other words a page-specific advanced DOM query language. Supporting a clean integration of page objects with libraries like `@ember/test-helpers` and `qunit-dom` that act on DOM element descriptors would keep each focused on its core value, while supporting page objects as "first-class" DOM element descriptors. +In this RFC we'll use **DOM helper** to mean an API that is passed a DOM element descriptor, and performs some actions based on the element or elements the descriptor describes. Examples include `@ember/test-helpers`' DOM helper methods such as `click()` and `triggerEvent`, and `qunit-dom`'s assertion factory api, i.e. `assert.dom()`. -Currently `fractal-page-object` integrates with `@ember/test-helpers` and `qunit-dom` by exposing an `element` property on all page objects, and that works because their APIs accept HTMLElements. But using HTMLElements as descriptors has three major drawbacks compared to using selectors: +Ember's testing ecosystem has converged on a single set of recommended DOM helpers. `@ember/test-helpers` provides the core value of implementing DOM interactions, while `qunit-dom` provides the core value of making assertions about DOM query results. They do _not_ (nor should they) provide the core value of advanced DOM querying -- they act on DOM elements, and do the simple baseline of supporting two kinds of DOM element descriptors, CSS selector strings and `Element` references. -1. It only supports single elements. While this isn't an issue with the `@ember/test-helpers` DOM APIs, in `qunit-dom` that means there's no way to use the multi-element assertions, like `assert.dom(document.querySelectorAll('.list-item')).exists({ count: 3 })`. -2. It does not produce a useful information when encountering an error/failure. For example, `await click('.does-not-exist')` errors with `Error: Element not found when calling click('.does-not-exist').`, while `await click(document.querySelector('.does-not-exist'))` errors with the less helpful `Error: Must pass an element or selector to 'click'` (because it doesn't have any other information to show -- all it knows is it was passed `null` instead of a selector or HTMLElement). Similarly, `assert.dom('.does-not-exist').exists()` produces the assertion message `Element .does-not-exist exists`, while `assert.dom(document.querySelector('.does-not-exist')).exists()` produces the less helpful `Element exists`. +[Page Objects](https://martinfowler.com/bliki/PageObject.html) are a powerful and popular tool for making test code well organized, readable, and maintainable. The core value they provide is supporting the implementation of a domain-specific languange (DSL) for interacting with a rendered DOM. Such DSLs can be thought of as, among other things, providing powerful and resuable DOM element descriptors. + +Supporting a clean integration of page objects (or, indeed, anything that produces DOM element descriptors that aren't CSS selectors or direct `Element` references) with DOM helpers like the ones in `@ember/test-helpers` and `qunit-dom` would keep each focused on its core value, while providing "first-class" support for page objects and other DOM element descriptors. + +As a case study (and most proximate motivation for this RFC), let's consider `fractal-page-object`. Currently `fractal-page-object` integrates with `@ember/test-helpers` and `qunit-dom` by exposing an `element` property on all page objects, and that works because their APIs accept direct `Element` references. But this has three major drawbacks: + +1. It only supports single elements. While this isn't an issue with the `@ember/test-helpers` DOM APIs, in `qunit-dom` that means there's no way to use the multi-element assertions, analogous to `assert.dom(document.querySelectorAll('.list-item')).exists({ count: 3 })`. +2. It does not produce useful information when encountering an error/failure. For example, `await click('.does-not-exist')` errors with `Error: Element not found when calling click('.does-not-exist').`, while `await click(document.querySelector('.does-not-exist'))` errors with the less helpful `Error: Must pass an element or selector to 'click'` (because it doesn't have any other information to show -- all it knows is it was passed `null` instead of a selector or `Element`). Similarly, `assert.dom('.does-not-exist').exists()` produces the assertion message `Element .does-not-exist exists`, while `assert.dom(document.querySelector('.does-not-exist')).exists()` produces the less helpful `Element exists`. 3. It supports a much less ergonomic integration with page objects. In `fractal-page-object`, the integrations currently look like `await click(page.listItems[2].checkbox.element)` and `assert.dom(page.listItems[2].checkbox.element).isChecked()`, rather than `await click(page.listItems[2].checkbox)` and `assert.dom(page.listItems[2].checkbox).isChecked()`. While it may look like a minor difference, in practice it's quite a stumbling block as the mental model of page objects encourages users to think of page object nodes (e.g. `page.listItems[2].checkbox`) as a proxy for the DOM element(s) they describe, so forgetting to add the `.element` is extremely common, even for the author of the library! -We can solve these by defining an DOM element descriptor interface that allows page object implementations, or even one-off test helpers written by application authors, to implement objects that can be passed to these test helpers and support everything that the selector API supports, specifically multiple elements and an optional description of the result set for messaging/debugging, and all without sacrificing developer ergonomics. +We can solve these by formalizing the notion of DOM element descriptors in an interface, so page object implementations and any other mechanisms for DOM access can produce objects implementing this interface and they can be passed to these test helpers without incurring any of the shortcoming described above. ## Detailed design From 3051df708e8e3c43e6fce9062e8b861a1b5c535a Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Mon, 15 Mar 2021 11:18:28 -0700 Subject: [PATCH 106/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 71 ++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index 02cdbd4c2a..52db8b39ad 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -53,23 +53,23 @@ We can solve these by formalizing the notion of DOM element descriptors in an in This RFC proposes implementing a very lightweight library that exports one `Symbol` and two interfaces: ```ts -expost const ELEMENT_DESCRIPTOR = Symbol('element descriptor'); +export const ELEMENT_DESCRIPTOR = Symbol('element descriptor'); export interface IElementDescriptor { element: Element | null; - elements?: Element[]; + elements: Element[]; description?: string; } -export interface IElementDescriptorFactory { +export interface IElementDescriptorProvider { [ELEMENT_DESCRIPTOR]: IElementDescriptor; } ``` -Then any API method that accepts a selector or element can also accept an `IElementDescriptor` or an `IElementDescriptorFactory`. For example a `click()` method like the one in `@ember/test-helpers` could be implemented as +Then any API method that accepts a selector or element can also accept an `IElementDescriptor` or an `IElementDescriptorProvider`. For example a `click()` method like the one in `@ember/test-helpers` could be implemented as ```ts -function click(target: string | Element | IElementDescriptor | IElementDescriptorFactory) { +function click(target: string | Element | IElementDescriptor | IElementDescriptorProvider) { if (!target) { throw new Error('Must pass an element or selector to `click`.'); } @@ -83,7 +83,7 @@ function click(target: string | Element | IElementDescriptor | IElementDescripto throw new Error(`element not found when calling \`click(${selector})\`.`); } } else { - // IElementDescriptor or IElementDescriptorFactory + // IElementDescriptor or IElementDescriptorProvider let descriptor = target[ELEMENT_DESCRIPTOR]; if (!descriptor) { descriptor = target; @@ -123,7 +123,7 @@ class SelectorDescriptor implements IElementDescriptor { } } -class SelectorDOMQuery implements IElementDescriptorFactory { +class SelectorDOMQuery implements IElementDescriptorProvider { public elementDescriptor: IElementDescriptor; constructor(selector: string) { @@ -132,11 +132,11 @@ class SelectorDOMQuery implements IElementDescriptorFactory { } ``` -This RFC proposes to extend `@ember/test-helpers`'s DOM helpers and `qunit-dom`'s DOM assertions to accept arguments of type `IElementDescriptor` and `IElementDescriptorFactory` anywhere they accept a selector or an `Element`. +This RFC proposes to extend `@ember/test-helpers`'s DOM helpers and `qunit-dom`'s DOM assertions to accept arguments of type `IElementDescriptor` and `IElementDescriptorProvider` anywhere they accept a selector or an `Element`. -### Why a symbol and two interfaces? +### Why a symbol? Why two interfaces? -It would be possible to only have the `IElementDescriptor` interface and not the `IElementDescriptorFactory` interface, and do away with the `ELEMENT_DESCRIPTOR` symbol. The short answer for why we have them is that one of the use cases this RFC is aiming to address involves page objects implementing these interfaces, which means that the interface properties/methods would be in the same namespace as user-defined properties on the page objects. So the `IElementDescriptorFactory` interface and `ELEMENT_DESCRIPTOR` symbol exist to allow such page objects to avoid namespace conflicts. +It would be possible to only have the `IElementDescriptor` interface and not the `IElementDescriptorProvider` interface, and do away with the `ELEMENT_DESCRIPTOR` symbol. The short answer for why we have them is that one of this RFC's target use cases is page objects providing element descriptors, and if they _were_ element descriptors then the element descriptor interface properties/methods would be in the same namespace as user-defined properties on the page objects (e.g. a user might want to implement a `description` property on an album page object containing the text of the album's description, and this would conflict with the `description` property on the `IElementDescriptor` interface). So the `IElementDescriptorProvider` interface and `ELEMENT_DESCRIPTOR` symbol exist to allow such page objects to avoid namespace conflicts. This is further discussed in the alternatives section of this RFC. @@ -153,15 +153,24 @@ Ad-hoc descriptors: ```js let element = someOtherLibrary.getGraphElement(); -await click({ element, description: 'graph element' }); -assert.dom({ element, description: 'graph element' }).hasClass('selected'); +await click({ element, elements: element ? [element] : [], description: 'graph element' }); +assert.dom({ element, elements: element ? [element] : [], description: 'graph element' }).hasClass('selected'); ``` +It would probably make sense to implement some factory functions for ad-hoc descriptors, e.g. + +```ts +function descriptorFromElement(element: Element | null, description?: string): IElementDescriptor; +function descriptorFromElements(elements: Element[], description?: string): IElementDescriptor; +``` + +but that's an implementation decision that's outside the scope of this RFC. + ### Where does this live? -This would live in a new library, since it defines interfaces for integration between existing libraries, and is not actually dependent on/tied to Ember in any way. The library export the `ELEMENT_DESCRIPTOR` symbol and types of the interfaces. +This would live in a new library, since it defines interfaces for integration between existing libraries, and is not actually dependent on/tied to Ember in any way. The library would export the `ELEMENT_DESCRIPTOR` symbol and types for the `IElementDescriptor` and `IElementDescriptorProvider` interface. -It could also potentially provide other types and helpers, such a `string | Element | IElementDescriptor | IElementDescriptorFactory` type or a `findElement()` method similar to the one in `@ember/test-helpers` that implements most of the element-finding logic in the `click()` example in the [the interfaces](#the-interfaces) section of this RFC. +It could also potentially provide other types and helpers, such a `string | Element | IElementDescriptor | IElementDescriptorProvider` type, a `findElement()` method similar to the one in `@ember/test-helpers` that implements most of the element-finding logic in the `click()` example in the [the interfaces](#the-interfaces) section of this RFC, and/or the factory functions described in the [new use cases](#new-use-cases) section, but these are implementation details outside the scope of this RFC. ## How we teach this @@ -178,27 +187,47 @@ The Ember guides would not need to be updated, as the default Ember testing meth ### Do nothing -This mainly improves developer ergonomics by allowing for better error/failure messaging and a simpler/more natural semantics when passing page objects to DOM helper/assertion methods. The only new functionality it enables is the ability for DOM helper/assertion methods to accept multi-element descriptors of types other than selectors. So we could do nothing and say what we have now is good enough. +This mainly improves developer ergonomics by allowing for better error/failure messaging and a simpler/more natural semantics when passing page objects to DOM helper/assertion methods. We could decide that the status quo is good enough, and the improved ergonomics are not worth the cost. ### One interface, three symbols We could get rid of the `IElementDescriptorProvider` interface and modify the `IElementDescriptor` interface to have symbol property keys instead of string property keys. This would simplify the overall picture, but would make implementing ad-hoc descriptors less ergonomic: ```js -let element = someOtherLibrary.getGraphElement(); -await click({ element, description: 'graph element' }); +let elements = someOtherLibrary.getGraphElements(); +let element = elements.length > 0 ? elements[0] : null; +await click({ element, elements, description: 'graph element' }); ``` vs. ```js -let element = someOtherLibrary.getGraphElement(); -await click({ [ELEMENT]: element, [DESCRIPTION]: 'graph element' }); +let elements = someOtherLibrary.getGraphElements(); +let element = elements.length > 0 ? elements[0] : null; +await click({ [ELEMENT]: element, [ELEMENTS]: elements, [DESCRIPTION]: 'graph element' }); +``` + +although this would be largely mitigated by the factory functions described in the [new use cases](#new-use-cases) section. + +### WeakMap + +To address the namespace conflicts in page objects, we could use a WeakMap instead of a symbol and two interfaces. The new library could provide + +```ts +const descriptorMap = new WeakMap(); + +export function registerDescriptorProvider(provider: object, descriptor: IElementDescriptor): void { + descriptorMap.set(provider, descriptor); +} + +export function getDescriptor(provider: object): IElementDescriptor? { + return descriptorMap.get(provider); +} ``` -> What other designs have been considered? What is the impact of not doing this? +and page objects (and the like) could register their element descriptors, allowing DOM helpers to retrieve the descriptors when needed. -> This section could also include prior art, that is, how other frameworks in the same domain have solved this problem. +This would also solve the namespace conflict, but seems to have limited benefits compared to the symbol solution and introduces extra complexity to the solution. ## Unresolved questions From 2ee9c7b30f0265ce8297f9cd3b61cbf581146083 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Mon, 15 Mar 2021 11:22:22 -0700 Subject: [PATCH 107/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index 52db8b39ad..b87f0b875a 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -30,7 +30,7 @@ RFC PR: Fill this in with the URL for the Proposal RFC PR In this RFC we'll use **DOM element descriptor** to mean a Javascript value that can be used to retrieve one or more `Element`s from a rendered DOM. Examples include a string containing a CSS selector, a direct reference to an `Element`, a function that returns an `Element` or `null`, a function that returns an array of `Element`s, etc. -In this RFC we'll use **DOM helper** to mean an API that is passed a DOM element descriptor, and performs some actions based on the element or elements the descriptor describes. Examples include `@ember/test-helpers`' DOM helper methods such as `click()` and `triggerEvent`, and `qunit-dom`'s assertion factory api, i.e. `assert.dom()`. +In this RFC we'll use **DOM helper** to mean an API that is passed a DOM element descriptor, and performs some actions based on the element or elements the descriptor describes. Examples include `@ember/test-helpers`' DOM helper methods such as `click()` and `triggerEvent`, and `qunit-dom`'s assertion factory API, i.e. `assert.dom()`. Ember's testing ecosystem has converged on a single set of recommended DOM helpers. `@ember/test-helpers` provides the core value of implementing DOM interactions, while `qunit-dom` provides the core value of making assertions about DOM query results. They do _not_ (nor should they) provide the core value of advanced DOM querying -- they act on DOM elements, and do the simple baseline of supporting two kinds of DOM element descriptors, CSS selector strings and `Element` references. From 2ae6dba7bfb5929b16cd476b062a5160d8098d78 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Mon, 15 Mar 2021 11:25:19 -0700 Subject: [PATCH 108/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index b87f0b875a..43128bf518 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -42,7 +42,7 @@ As a case study (and most proximate motivation for this RFC), let's consider `fr 1. It only supports single elements. While this isn't an issue with the `@ember/test-helpers` DOM APIs, in `qunit-dom` that means there's no way to use the multi-element assertions, analogous to `assert.dom(document.querySelectorAll('.list-item')).exists({ count: 3 })`. 2. It does not produce useful information when encountering an error/failure. For example, `await click('.does-not-exist')` errors with `Error: Element not found when calling click('.does-not-exist').`, while `await click(document.querySelector('.does-not-exist'))` errors with the less helpful `Error: Must pass an element or selector to 'click'` (because it doesn't have any other information to show -- all it knows is it was passed `null` instead of a selector or `Element`). Similarly, `assert.dom('.does-not-exist').exists()` produces the assertion message `Element .does-not-exist exists`, while `assert.dom(document.querySelector('.does-not-exist')).exists()` produces the less helpful `Element exists`. -3. It supports a much less ergonomic integration with page objects. In `fractal-page-object`, the integrations currently look like `await click(page.listItems[2].checkbox.element)` and `assert.dom(page.listItems[2].checkbox.element).isChecked()`, rather than `await click(page.listItems[2].checkbox)` and `assert.dom(page.listItems[2].checkbox).isChecked()`. While it may look like a minor difference, in practice it's quite a stumbling block as the mental model of page objects encourages users to think of page object nodes (e.g. `page.listItems[2].checkbox`) as a proxy for the DOM element(s) they describe, so forgetting to add the `.element` is extremely common, even for the author of the library! +3. It supports a noticeably less ergonomic integration with page objects. In `fractal-page-object`, the integrations currently look like `await click(page.listItems[2].checkbox.element)` and `assert.dom(page.listItems[2].checkbox.element).isChecked()`, rather than `await click(page.listItems[2].checkbox)` and `assert.dom(page.listItems[2].checkbox).isChecked()`. While it may look like a minor difference, in practice it's quite a stumbling block as the mental model of page objects encourages users to think of page object nodes (e.g. `page.listItems[2].checkbox`) as a proxy for the DOM element(s) they describe, so forgetting to add the `.element` is extremely common, even for the author of the library! We can solve these by formalizing the notion of DOM element descriptors in an interface, so page object implementations and any other mechanisms for DOM access can produce objects implementing this interface and they can be passed to these test helpers without incurring any of the shortcoming described above. From 29feb94f66865ee8953295878bab9f2eaaeb86d1 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Mon, 15 Mar 2021 11:46:40 -0700 Subject: [PATCH 109/292] Update 0000-dom-query-testing-interface.md --- 0000-dom-query-testing-interface.md | 89 +++++++++++++++++++---------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/0000-dom-query-testing-interface.md b/0000-dom-query-testing-interface.md index 43128bf518..17f0750b44 100644 --- a/0000-dom-query-testing-interface.md +++ b/0000-dom-query-testing-interface.md @@ -57,7 +57,7 @@ export const ELEMENT_DESCRIPTOR = Symbol('element descriptor'); export interface IElementDescriptor { element: Element | null; - elements: Element[]; + elements: NodeListOf | Iterable; description?: string; } @@ -69,38 +69,45 @@ export interface IElementDescriptorProvider { Then any API method that accepts a selector or element can also accept an `IElementDescriptor` or an `IElementDescriptorProvider`. For example a `click()` method like the one in `@ember/test-helpers` could be implemented as ```ts -function click(target: string | Element | IElementDescriptor | IElementDescriptorProvider) { +function click( + target: string | Element | IElementDescriptor | IElementDescriptorProvider +) { if (!target) { throw new Error('Must pass an element or selector to `click`.'); } - - let element; + + let element: Element | null; if (target instanceof Element) { element = target; } else if (typeof target === 'string') { - element = document.querySelector(target); + let selector = target as string; + element = document.querySelector(selector); if (!element) { throw new Error(`element not found when calling \`click(${selector})\`.`); } } else { // IElementDescriptor or IElementDescriptorProvider - let descriptor = target[ELEMENT_DESCRIPTOR]; + let descriptor = (target as IElementDescriptorProvider)[ELEMENT_DESCRIPTOR]; if (!descriptor) { - descriptor = target; + descriptor = target as IElementDescriptor; } - + let element = descriptor.element; if (!element) { let description = descriptor.description; if (description) { - throw new Error(`element not found when calling \`click()\` with descriptor: ${description}`); + throw new Error( + `element not found when calling \`click()\` with descriptor: ${description}` + ); } else { - throw new Error(`element not found when calling \`click()\` with descriptor`); + throw new Error( + `element not found when calling \`click()\` with descriptor` + ); } } } - element.click(); + element!.click(); } ``` @@ -109,25 +116,25 @@ To further illustrate, this is an (unnecessary) implementation of a descriptor a ```ts class SelectorDescriptor implements IElementDescriptor { constructor(private selector: string) {} - - get element(): Element | null { + + get element() { return document.querySelector(this.selector); } - - get elements(): Element[] { + + get elements() { return document.querySelectorAll(this.selector); } - + get description(): string { return this.selector; } } -class SelectorDOMQuery implements IElementDescriptorProvider { - public elementDescriptor: IElementDescriptor; +class SelectorDescriptorProvider implements IElementDescriptorProvider { + public [ELEMENT_DESCRIPTOR]: IElementDescriptor; constructor(selector: string) { - this.elementDescriptor = new SelectorDescriptor(selector); + this[ELEMENT_DESCRIPTOR] = new SelectorDescriptor(selector); } } ``` @@ -153,15 +160,32 @@ Ad-hoc descriptors: ```js let element = someOtherLibrary.getGraphElement(); -await click({ element, elements: element ? [element] : [], description: 'graph element' }); -assert.dom({ element, elements: element ? [element] : [], description: 'graph element' }).hasClass('selected'); +await click({ + element, + elements: element ? [element] : [], + description: 'graph element', +}); +assert + .dom({ + element, + elements: element ? [element] : [], + description: 'graph element', + }) + .hasClass('selected'); ``` It would probably make sense to implement some factory functions for ad-hoc descriptors, e.g. ```ts -function descriptorFromElement(element: Element | null, description?: string): IElementDescriptor; -function descriptorFromElements(elements: Element[], description?: string): IElementDescriptor; +function descriptorFromElement( + element: Element | null, + description?: string +): IElementDescriptor; + +function descriptorFromElements( + elements: NodeListOf | Iterable, + description?: string +): IElementDescriptor; ``` but that's an implementation decision that's outside the scope of this RFC. @@ -193,7 +217,7 @@ This mainly improves developer ergonomics by allowing for better error/failure m We could get rid of the `IElementDescriptorProvider` interface and modify the `IElementDescriptor` interface to have symbol property keys instead of string property keys. This would simplify the overall picture, but would make implementing ad-hoc descriptors less ergonomic: -```js +```ts let elements = someOtherLibrary.getGraphElements(); let element = elements.length > 0 ? elements[0] : null; await click({ element, elements, description: 'graph element' }); @@ -201,10 +225,14 @@ await click({ element, elements, description: 'graph element' }); vs. -```js +```ts let elements = someOtherLibrary.getGraphElements(); let element = elements.length > 0 ? elements[0] : null; -await click({ [ELEMENT]: element, [ELEMENTS]: elements, [DESCRIPTION]: 'graph element' }); +await click({ + [ELEMENT]: element, + [ELEMENTS]: elements, + [DESCRIPTION]: 'graph element', +}); ``` although this would be largely mitigated by the factory functions described in the [new use cases](#new-use-cases) section. @@ -216,12 +244,15 @@ To address the namespace conflicts in page objects, we could use a WeakMap inste ```ts const descriptorMap = new WeakMap(); -export function registerDescriptorProvider(provider: object, descriptor: IElementDescriptor): void { +export function registerDescriptorProvider( + provider: object, + descriptor: IElementDescriptor +): void { descriptorMap.set(provider, descriptor); } -export function getDescriptor(provider: object): IElementDescriptor? { - return descriptorMap.get(provider); +export function getDescriptor(provider: object): IElementDescriptor | null { + return descriptorMap.get(provider) || null; } ``` From 057196f5e16a1cd8f8a2fd1a9984f56bf3081311 Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Mon, 15 Mar 2021 18:16:03 -0700 Subject: [PATCH 110/292] Fill in PR number --- ...ing-interface.md => 0726-dom-element-descriptor-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename 0000-dom-query-testing-interface.md => 0726-dom-element-descriptor-interface.md (99%) diff --git a/0000-dom-query-testing-interface.md b/0726-dom-element-descriptor-interface.md similarity index 99% rename from 0000-dom-query-testing-interface.md rename to 0726-dom-element-descriptor-interface.md index 17f0750b44..1542d1b359 100644 --- a/0000-dom-query-testing-interface.md +++ b/0726-dom-element-descriptor-interface.md @@ -6,7 +6,7 @@ Release Versions: ember-source: vX.Y.Z ember-data: vX.Y.Z Relevant Team(s): Ember.js -RFC PR: +RFC PR: #726 --- + +# Propose {{RFC_NAME}} + + + +## [Rendered](https://github.com/{{username}}/rfcs/blob/{{branch}}/text/{{rfc_number}}-{{rfc_slug}}.md) + +## Summary + +This pull request is proposing a new RFC. + +To succeed, it will need to pass into the [Exploring Stage](https://github.com/emberjs/rfcs#exploring)), followed by the [Accepted Stage](https://github.com/emberjs/rfcs#accepted). + +A Proposed or Exploring RFC may also move to the [Closed Stage](https://github.com/emberjs/rfcs#closed) if it is withdrawn by the author or if it is rejected by the Ember team. This requires an "FCP to Close" period. + +**An FCP is required before merging this PR to advance to Accepted.** + +Upon merging this PR, automation will open a draft PR for this RFC to move to the [Ready for Released Stage](https://github.com/emberjs/rfcs#ready-for-release). + +
+ Exploring Stage Description + +This stage is entered when the Ember team believes the concept described in the RFC should be pursued, but the RFC may still need some more work, discussion, answers to open questions, and/or a champion before it can move to the next stage. + +An RFC is moved into Exploring with consensus of the relevant teams. The relevant team expects to spend time helping to refine the proposal. The RFC remains a PR and will have an `Exploring` label applied. + +An Exploring RFC that is successfully completed can move to [Accepted](https://github.com/emberjs/rfcs#accepted) with an FCP is required as in the existing process. It may also be moved to [Closed](https://github.com/emberjs/rfcs#closed) with an FCP. +
+ +
+ Accepted Stage Description + +To move into the "accepted stage" the RFC must have complete prose and have successfully passed through an "FCP to Accept" period in which the community has weighed in and consensus has been achieved on the direction. The relevant teams believe that the proposal is well-specified and ready for implementation. The RFC has a champion within one of the relevant teams. + +If there are unanswered questions, we have outlined them and expect that they will be answered before [Ready for Release](https://github.com/emberjs/rfcs#ready-for-release). + +When the RFC is accepted, the PR will be merged, and automation will open a new PR to move the RFC to the [Ready for Release](https://github.com/emberjs/rfcs#ready-for-release) stage. That PR should be used to track implementation progress and gain consensus to move to the next stage. + +
+ +## Checklist to move to Exploring + +- [ ] The team believes the concepts described in the RFC should be pursued. +- [ ] The label `S-Proposed` is removed from the PR and the label `S-Exploring` is added. +- [ ] The Ember team is willing to work on the proposal to get it to Accepted + +## Checklist to move to Accepted + +- [ ] This PR has had the `Final Comment Period` label has been added to start the FCP +- [ ] The RFC is announced in #news-and-announcements in the Ember Discord. +- [ ] The RFC has complete prose, is well-specified and ready for implementation. + - [ ] All sections of the RFC are filled out. + - [ ] Any unanswered questions are outlined and expected to be answered before Ready for Release. + - [ ] "How we teach this?" is sufficiently filled out. +- [ ] The RFC has a champion within one of the relevant teams. +- [ ] The RFC has consensus after the FCP period. From 6b827ea9daab5b5c3a366563223c0ee7f8fe652d Mon Sep 17 00:00:00 2001 From: Ben Demboski Date: Fri, 17 Nov 2023 11:51:22 -0800 Subject: [PATCH 119/292] Extend "how we teach this" a bit --- text/0726-dom-element-descriptor-interface.md | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/text/0726-dom-element-descriptor-interface.md b/text/0726-dom-element-descriptor-interface.md index a08bc81e3e..70a336c555 100644 --- a/text/0726-dom-element-descriptor-interface.md +++ b/text/0726-dom-element-descriptor-interface.md @@ -1,3 +1,19 @@ +--- +stage: accepted +start-date: 2021-03-13T00:42:02.085Z +release-date: # In format YYYY-MM-DDT00:00:00.000Z +release-versions: +teams: # delete teams that aren't relevant + - cli + - framework + - learning + - typescript +prs: + accepted: https://github.com/emberjs/rfcs/pull/939 +project-link: +suite: +--- + --- Stage: Accepted Start Date: 2021-03-13 @@ -12,12 +28,15 @@ RFC PR: https://github.com/emberjs/rfcs/pull/726 # DOM Element descriptor interface for test helpers @@ -186,7 +205,9 @@ function for returning the descriptor's `description` or deriving some kind of r This is primarily taught through the API documentation of the various libraries that implement compliant DOM helpers, such as `@ember/test-helpers` and `qunit-dom`, and libraries that produce DOM element descriptors, such as `fractal-page-object`. In addition the new library proposed in this RFC would have documentation explaining the infrastructure and how to use it. -The Ember guides would not need to be updated, as the default Ember testing methodology would be unaffected -- this would be added functionality for users using page object libraries, or implementing ad-hoc element descriptors in their tests. +The Ember guides would not need to be updated, as the default Ember testing methodology would be unaffected -- this would be added functionality for users using page object libraries, or implementing ad-hoc element descriptors in their tests. However, if Ember's guides were ever extended to include page object testing methodologies, we would need to include a discussion of DOM element descriptors. + +Also, if we were to discover any new and valuable testing methods/patterns that are unlocked by DOM element descriptors, we might want to discuss them, along with DOM element descriptors themselves, in Ember's educational materials. ## Drawbacks From 038a322e66810a29b1c0170089ed87b487d3565a Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Fri, 1 Dec 2023 14:19:44 -0500 Subject: [PATCH 120/292] Updating metadata --- text/0726-dom-element-descriptor-interface.md | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/text/0726-dom-element-descriptor-interface.md b/text/0726-dom-element-descriptor-interface.md index 70a336c555..805dfbe7af 100644 --- a/text/0726-dom-element-descriptor-interface.md +++ b/text/0726-dom-element-descriptor-interface.md @@ -9,36 +9,11 @@ teams: # delete teams that aren't relevant - learning - typescript prs: - accepted: https://github.com/emberjs/rfcs/pull/939 + accepted: https://github.com/emberjs/rfcs/pull/726 project-link: suite: --- ---- -Stage: Accepted -Start Date: 2021-03-13 -Release Date: Unreleased -Release Versions: - ember-source: vX.Y.Z - ember-data: vX.Y.Z -Relevant Team(s): Ember.js -RFC PR: https://github.com/emberjs/rfcs/pull/726 ---- - - - # DOM Element descriptor interface for test helpers ## Summary From 95020b0e7358457890479108d2b6cf8ec3819a9f Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 1 Dec 2023 19:29:53 +0000 Subject: [PATCH 121/292] Advance RFC 0726 to Stage ready-for-release --- text/0726-dom-element-descriptor-interface.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/text/0726-dom-element-descriptor-interface.md b/text/0726-dom-element-descriptor-interface.md index 805dfbe7af..df41eb8aa7 100644 --- a/text/0726-dom-element-descriptor-interface.md +++ b/text/0726-dom-element-descriptor-interface.md @@ -1,17 +1,17 @@ --- -stage: accepted +stage: ready-for-release start-date: 2021-03-13T00:42:02.085Z -release-date: # In format YYYY-MM-DDT00:00:00.000Z +release-date: release-versions: -teams: # delete teams that aren't relevant +teams: - cli - framework - learning - typescript prs: - accepted: https://github.com/emberjs/rfcs/pull/726 + accepted: 'https://github.com/emberjs/rfcs/pull/726' project-link: -suite: +suite: --- # DOM Element descriptor interface for test helpers From 4a2e47927d932a33f067e63a222277b8bbb546bb Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 1 Dec 2023 19:29:57 +0000 Subject: [PATCH 122/292] Update RFC 0726 ready-for-release PR URL --- text/0726-dom-element-descriptor-interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0726-dom-element-descriptor-interface.md b/text/0726-dom-element-descriptor-interface.md index df41eb8aa7..b0b467515f 100644 --- a/text/0726-dom-element-descriptor-interface.md +++ b/text/0726-dom-element-descriptor-interface.md @@ -10,6 +10,7 @@ teams: - typescript prs: accepted: 'https://github.com/emberjs/rfcs/pull/726' + ready-for-release: 'https://github.com/emberjs/rfcs/pull/992' project-link: suite: --- From 281b7adcfbdb5ebd0e96e2b4e14bda3e8d38b381 Mon Sep 17 00:00:00 2001 From: Katie Gengler Date: Fri, 8 Dec 2023 15:37:30 -0500 Subject: [PATCH 123/292] Update 0831-standardize-use-npm-yarn.md Correct title --- text/0831-standardize-use-npm-yarn.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/text/0831-standardize-use-npm-yarn.md b/text/0831-standardize-use-npm-yarn.md index 7f1e07bc74..05e56df108 100644 --- a/text/0831-standardize-use-npm-yarn.md +++ b/text/0831-standardize-use-npm-yarn.md @@ -24,8 +24,7 @@ Relevant Team(s): Fill this in with the [team(s)](README.md#relevant-teams) to w RFC PR: Fill this in with the URL for the Proposal RFC PR --> -# -Standardize the use of yarn and npm scripts in the Ember experience +# Standardize the use of yarn and npm scripts in the Ember experience ## Summary From cbe53de65265bcf02f2ee5e56b7a81be359eedcb Mon Sep 17 00:00:00 2001 From: ef4 Date: Fri, 15 Dec 2023 19:21:12 +0000 Subject: [PATCH 124/292] Advance RFC 0918 to Stage recommended --- text/0918-deprecate-travis-ci-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index 168c55cda7..fdfb43d610 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -1,5 +1,5 @@ --- -stage: released +stage: recommended start-date: 2023-03-25T00:00:00.000Z release-date: 2023-12-11T00:00:00.000Z release-versions: From c66656224982100533070db95470f3952df06089 Mon Sep 17 00:00:00 2001 From: "Ember.js RFCS CI" Date: Fri, 15 Dec 2023 19:21:15 +0000 Subject: [PATCH 125/292] Update RFC 0918 recommended PR URL --- text/0918-deprecate-travis-ci-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0918-deprecate-travis-ci-support.md b/text/0918-deprecate-travis-ci-support.md index fdfb43d610..0e1b69f241 100644 --- a/text/0918-deprecate-travis-ci-support.md +++ b/text/0918-deprecate-travis-ci-support.md @@ -11,6 +11,7 @@ prs: accepted: 'https://github.com/emberjs/rfcs/pull/918' ready-for-release: 'https://github.com/emberjs/rfcs/pull/954' released: 'https://github.com/emberjs/rfcs/pull/978' + recommended: 'https://github.com/emberjs/rfcs/pull/994' project-link: --- From aace14e077fcb01baab22a73667d3b8044e7ff38 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 15 Dec 2023 14:38:31 -0500 Subject: [PATCH 126/292] Create 0000-deprecate-non-colocated-components.md --- ...0000-deprecate-non-colocated-components.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 text/0000-deprecate-non-colocated-components.md diff --git a/text/0000-deprecate-non-colocated-components.md b/text/0000-deprecate-non-colocated-components.md new file mode 100644 index 0000000000..cefef1b3aa --- /dev/null +++ b/text/0000-deprecate-non-colocated-components.md @@ -0,0 +1,77 @@ +--- +stage: accepted +start-date: +release-date: +release-versions: +teams: # delete teams that aren't relevant + - cli + - data + - framework + - learning + - steering + - typescript +prs: + accepted: # update this to the PR that you propose your RFC in +project-link: +--- + + + +# Deprecate non-co-located components. + +## Summary + +Deprecates +- classic component layout +- pods component layout + +## Motivation + +> Why are we doing this? What are the problems with the deprecated feature? +What is the replacement functionality? + +## Transition Path + +> This is the bulk of the RFC. Explain the use-cases that deprecated functionality +covers, and for each use-case, describe the transition path. +Describe it in enough detail for someone who uses the deprecated functionality +to understand, for someone to write the deprecation guide, and for someone +familiar with the implementation to implement. + +## How We Teach This + +> 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? +Does it mean we need to put effort into highlighting the replacement +functionality more? What should we do about documentation, in the guides +related to this feature? +How should this deprecation be introduced and explained to existing Ember +users? + +## 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 + +> What other designs have been considered? What is the impact of not doing this? + +## Unresolved questions + +> Optional, but suggested for first drafts. What parts of the design are still +TBD? From f1757801330b86da7854072b411707f6b1a88d6d Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 15 Dec 2023 15:16:24 -0500 Subject: [PATCH 127/292] Actually write the thing --- ...0000-deprecate-non-colocated-components.md | 77 ---------- ...0995-deprecate-non-colocated-components.md | 132 ++++++++++++++++++ 2 files changed, 132 insertions(+), 77 deletions(-) delete mode 100644 text/0000-deprecate-non-colocated-components.md create mode 100644 text/0995-deprecate-non-colocated-components.md diff --git a/text/0000-deprecate-non-colocated-components.md b/text/0000-deprecate-non-colocated-components.md deleted file mode 100644 index cefef1b3aa..0000000000 --- a/text/0000-deprecate-non-colocated-components.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -stage: accepted -start-date: -release-date: -release-versions: -teams: # delete teams that aren't relevant - - cli - - data - - framework - - learning - - steering - - typescript -prs: - accepted: # update this to the PR that you propose your RFC in -project-link: ---- - - - -# Deprecate non-co-located components. - -## Summary - -Deprecates -- classic component layout -- pods component layout - -## Motivation - -> Why are we doing this? What are the problems with the deprecated feature? -What is the replacement functionality? - -## Transition Path - -> This is the bulk of the RFC. Explain the use-cases that deprecated functionality -covers, and for each use-case, describe the transition path. -Describe it in enough detail for someone who uses the deprecated functionality -to understand, for someone to write the deprecation guide, and for someone -familiar with the implementation to implement. - -## How We Teach This - -> 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? -Does it mean we need to put effort into highlighting the replacement -functionality more? What should we do about documentation, in the guides -related to this feature? -How should this deprecation be introduced and explained to existing Ember -users? - -## 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 - -> What other designs have been considered? What is the impact of not doing this? - -## Unresolved questions - -> Optional, but suggested for first drafts. What parts of the design are still -TBD? diff --git a/text/0995-deprecate-non-colocated-components.md b/text/0995-deprecate-non-colocated-components.md new file mode 100644 index 0000000000..142d0f71e2 --- /dev/null +++ b/text/0995-deprecate-non-colocated-components.md @@ -0,0 +1,132 @@ +--- +stage: accepted +start-date: 2023-12-15 +release-date: +release-versions: +teams: # delete teams that aren't relevant + - cli + - framework + - learning + - typescript +prs: + accepted: https://github.com/emberjs/rfcs/pull/995 +project-link: +--- + + + +# Deprecate non-co-located components. + +## Summary + +Deprecates +- classic component layout +- pods component layout + + +After "ember@6", only the following will be allowed: +- co-located components +- gjs / gts components + +## Motivation + +These older component layouts force build tooling to keep a lot of resolution rules around, and makes it hard for codemods and other community tooling to effectively work across folks' projects. + + +## Transition Path + +There are two types of paths to migrate off the old layouts +- use a currently supported multi-file layout (keeping separate `js`, `ts`, and hbs files) +- migrate the component entirely to the latest component format, `gjs`, `gts`, (aka `