From 0c5db90776350ea626c1aa3300a8c5811b6517f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 8 Jun 2020 00:51:10 +0200 Subject: [PATCH 01/30] Create 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 320 +++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 rfcs/0000-top-level-assumptions.md diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md new file mode 100644 index 0000000..435c485 --- /dev/null +++ b/rfcs/0000-top-level-assumptions.md @@ -0,0 +1,320 @@ +# RFC: Loose + +- Repo: [`babel/babel`](https://github.com/babel/babel) +- Start Date: 2020-06-08 +- RFC PR: +- Related Issues: +- Authors: Nicolò Ribaudo +- Champion: Nicolò Ribaudo +- Implementors: + +# Summary + +Many of our plugins have a `loose` option, which enables the compiler to make some assumptions about the code you are writing. It uses these to ignore certain edge cases and generate a smaller or faster output. + +The `loose` option has been around since `6to5`: at first as a top level option, and then it was split into each plugin as a catch all for anything that we wanted to be less spec compliant. + +However, `loose` has some problems: namely that the term itself is not clear what it means, and _should_ be more related to a part of the language rather than to the plugin that it's compiling it (see the "Motivation" section for more details). A lot of this behavior is documented with a single example, so in the future we’ll want to be specific with the assumptions themselves and maybe provide a set of tests/codesandboxes explaining differences. + +This RFC proposes introducing a new *top-level* option, `"assumptions"`, which is an object containing different flags which can simplify the output code. +These flags have two characteristics: +- They specify _something_ about a specific language feature, and not about a specific Babel plugin. +- Different flags can toggle different unrelated optimizations in the same plugin, instead of toggling both of them with a single generic `"loose"` option. + +# Basic example + +```jsonc +// babel.config.json +{ + "assumptions": { + "noDocumentAll": true, + "noGetterSideEffects": true, + "iterableIsArray": true + }, + "presets": ["@babel/preset-env"] +} +``` + +
+Input / Output + +```javascript +// input code + +for (const el of arr) { + el.logger?.log("Ok!"); +} +``` + +```javascript +// output code + +for (let i = 0; i < arr.length; i++) { + const el = arr[i]; + el.logger == null ? void 0 : el.logger.log("Ok!"); +} +``` +
+
+ +```jsonc +// babel.config.json +{ + "assumptions": { + "noDocumentAll": false, + "noGetterSideEffects": true, + "iterableIsArray": true + }, + "presets": ["@babel/preset-env"] +} +``` + + +
+Input / Output + +```javascript +// input code + +for (const el of arr) { + el.logger?.log("Ok!"); +} +``` + +```javascript +// output code + +for (let i = 0; i < arr.length; i++) { + const el = arr[i]; + el.logger === null || el.logger === void 0 ? void 0 : el.logger.log("Ok!"); +} +``` +
+ +# Motivation + +The `loose` options have different problems: +- _"What is loose?"_ It's not always clear what assumptions `loose` makes. You always have to check in the docs, end even the docs often only partially mention what `loose` means in that specific context. +- _"How loose is loose?"_ Is making `loose` "looser" a breaking change? We have been considering it as such: for this reason, we have been introducing different `loose`-like options in some plugins. For example, `transform-for-of` supports `loose`, `assumeArray` and `allowArrayLike`. +- There are cross-dependencies between the `loose` option of different plugins: for example, `proposal-class-properties`'s loose mode must always match `proposal-private-methods`'s (otherwise we throw an error). This has already caused problems: [babel/babel#11622](https://github.com/babel/babel/issues/11622). +- Some plugins should be aware of other plugins' `loose` option value. For example, we sometimes need to partially transpile optional chaining in the class properties plugin ([babel/babel#11248](https://github.com/babel/babel/pull/11248)). Should we add a new `optionalChainingLoose` option to `proposal-private-methods` and `proposal-class-properties`? Or should we use a cross-plugin communication channel to share it? What about when someone has the private methods plugin enabled, but not the optional chaining one? + +This RFC also solves another problem, which is not directly related to the points above: +- `@babel/preset-env` has a `loose` option, which is forwarded to all the plugins it enables. When a user wants to set `loose` only for a specific feature, they have to manually install the plugin and explicitly add it to their configuration ([babel/babel#6978](https://github.com/babel/babel/issues/6978)). + + +# Detailed design + +## New configuration option + +This RFC introduces a new top-level option: `assumptions`. This is an object containing different flags to mark different assumptions about the input code as safe and thus allow optimizing them. + +```typescript +type Assumptions = { + [assumption: string]: boolean +}; +``` + +This new options should be allowed in the following locations: +- In programmatic options passed, for example, to `babel.transform()` or to `babel-loader`. +- In `babel.config.json` and `.babelrc.json` top-level options. +- In `overrides` blocks. This is useful, for example, to enable a possible `noDocumentAll` assumption on a folder containing server-side code and not inside one containing client-side code. +- In `env` blocks. This is mostly included for completeness, but I can't think about an use case for it: assumptions are about the _input code_, which isn't affected by env variables. + +Additionally, `"assumptions"` should also be allowed inside presets. +There are two main kinds of presets: framework-specific presets, like `babel-preset-react-app`, and company-wide presets, used to share the same plugins accross different projects. Since assumptions describe the input code and not the used plugins, this new option fits better in company-wide presets where the person writing the preset and the person writing the input code have less "degrees of separation", but there are also use cases in framework-specific presets: for example, `babel-preset-react-app` [enables](https://github.com/facebook/create-react-app/blob/c87ab79559e98a5dae2cd0b02477c38ff6113e6a/packages/babel-preset-react-app/create.js#L151-L154) `loose: true` for `@babel/plugin-proposal-class-properties`. + +## Configuration merging + +Multiple `"assumptions"` object should be merged using `Object.assign`, instead of by overwriting the object as it happens for other options. +This makes it easy, for example, to enable one additional assumption for a specific folder. Also, it still keeps the ability of disabling an assumption simply by setting it to `false`. + +They should be merged considering the following precedence, which is the same as what is already used for other options: +- preset < `babel.config.json` < `.babelrc.json` (far from the compiled file)< `.babelrc.json` (near to the compiled file) < programmatic options +- top-level < `env` section < `overrides` + +Assumptions set inside a preset are not boxed inside the preset but are applied to all the plugins, for two reasons: +1. conceptually, the assumptions describe the input file and not a specific plugin enabled inside the preset; +2. practically, this makes it possible to have a single "personal" or "company" preset containing assumptions which apply to a user's coding practices, and re-use it in different projects without duplicating the list of assumptions. + +In order to "leak" assumptions defined inside presets, we need to first resolve and instantiate all the presets, and then all the plugins with the resolved assumptions ([babel/babel#11689](https://github.com/babel/babel/pull/11689)). Currently, presets and plugins are instantiated in mixed order. +This also means that we cannot provide the defined assumptions list to the presets, because it hasn't been finalized yet when they are instantiated. + +## Plugin API + +The first parameter passed to the plugins (often known as `api`) should have a new property: `assumptions`, which is a frozen copy of the resolved assumptions object. + +## Assumptions list + +The different `loose` or `loose`-like options we currently have in our plugins map to these assumptions: + +> ℹ️ I'm not particularly attatched to these option names: I tried to choose something descriptive for their behavior, but they can all change. + +| Assumption | Behavior | Current option | Repl | Notes | +|:-----------|:---------|:---------------|:----:|:-----:| +| `usePlusForTemplates` | Transform `` `a${x}b` `` to `"a" + x + "b"` instead of `"a".concat(x, "b")` | `loose` in `transform-template-literals` | +| `noFrozenTemplateObject` | Don't use `Object.freeze` for the template object created for tagged template literals. This effectively means using the `taggedTemplateLiteralLoose` helper instead of `taggedTemplateLiteral` | `loose` in `transform-template-literals` | +| `ignoreFunctionLength` | The `.length` of a function should be cropped at the first default argument. When this option is enabled, ignore this spec requirement and don't rely on the `arguments` object | `loose` in `transform-parameters` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABMMAKAhgGkQI0QXkQCZsJsATAxAZgEpEBvAKAF8g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `iterableIsArray` | When using an iterable (in array destructuring, for-of or with spreads), assume that the iterable object is an `Array` | `loose` in `transform-destructuring` and `transform-spread`, `assumeArray` in `transform-for-of` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ2gOmQIwLoG4BQpLwB4A0EyiAnmrFNkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) (it doesn't support `assumeArray`) | 1 | +| `arrayLikeIsIterable` | Allow array-like objects to be used where an iterable is expected. This can be useful, for example, to iterate DOM collections in older browsers | `allowArrayLike` in `transform-destructuring`, `transform-spread` and `transform-for-of` | | 1 | +| `skipForOfIterationClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | 2 | +| `arrayIndexedIteration` | When using `for-of` with an array, ignore the iterator protocol and use direct accss to its element like a `for` loop would do | `loose` in `transform-for-of` | | 2 | +| `objectRestNoSymbols` | When using rest in object destructuring, don't copy symbol keys. This effectively means using the `objectWithoutPropertiesLoose` helper instead of `objectWithoutProperties` | `loose` in `transform-destructuring` and `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBA3hIDQQHTIEYQL4QLwQMYG4g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `setObjectSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | +| `setObjectComputedProperties` | When using computed object properties, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `computed-properties` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ3gKAhA2gDwLoC4ICYAaRAXyA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `setClassMethods` | When declaring classes, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]`. This doesn't preserve the correct enumerability. | `loose` in `transform-classes` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=true&code_lz=MYGwhgzhAECC0G8BQ1oDMD2GAUBKRAvkgUA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `definePrivateAsOwnProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | +| `useCallForSuper` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | +| `inheritsLoose` (TODO: Better name) | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | +| `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 4 | +| `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | +| `immutableReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | +| `noNewArrowAttempt` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 5 | + +1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. +2. With the current implementation, `skipForOfIterationClosing` and `arrayIndexedIteration` should be merged in a single option. +3. Currently, the `loose` option must be the same for these plugins or it will throw an error. We have a workaround in `@babel/preset-env` to allow setting `loose` there differently from these plugins ([babel/babel#11634](https://github.com/babel/babel/pull/11634)) +4. `?.` also needs to be compiled by the private fields and methods plugins ([babel/babel#11248](https://github.com/babel/babel/pull/11248), but currently there is no way to set it to `loose` +5. The current default behavior is to consider this assumption as valid, and only produce 100% spec-compliant code when the `spec` option is enabled. + +# Drawbacks + +- This RFC introduces a very big number of new top-level options (19), and makes it relatively cheap to add new ones. Having a big number of options can add more "tooling fatigue" on the shoulders of our users, and it can make it hard for us to properly document them. However, these new options replace 22 existing plugin options, many of which have the same name (`loose`) but different behaviors. + +- ([@JLHwung](https://github.com/JLHwung)) Some `assumptions` are only effective in one plugin, but users will have to go through their presets/plugins to see if they have opt-in to this plugins. Let's say there is an assumption in a stage-1 proposal and the users does not know it is no-op for their config, it may inadvertently turn into a long list of `assumptions` and the no-op assumptions can kick in once users upgrades `preset-env` which may includes it once its stage advances. + +# Alternatives + +- We could decide to add these new descriptive options names directly in plugins options, instead of in `@babel/core`. This solves the problem of "what does loose mean?", but it doesn't solve the problem of having the same assumption in different plugins. + +- We could decide to add a simple top-level `loose` option, like we did in Babel 5: this solves the problem of multiple plugins sharing the same assumption. However, it would be even more obscure than the current `loose` options inside the plugins (which at least give some context). Also, having an all-or-nothing toggle means that often you would have to disable _every_ optimization just because you rely on a single edge case. + +# Adoption strategy + +We can introduce these options without introducing breaking changes, because it's opt-in. There are three possible compatibility strategies between the existing `loose` options and `assumptions` that we can choose: + +1. Allow both, `assumptions` has higher precedence because it's the new recommended option: + ```javascript + export default function transformClassProperties(api, options) { + const { setPublicClassFields = options.loose } = api.assumptions; + ``` + +1. Allow both, `loose` has higher precedence because it "nearer" to the plugin: + ```javascript + export default function transformClassProperties(api, options) { + const setPublicClassFields = options.loose ?? api.assumptions.setPublicClassFields; + ``` + +1. Disallow using both at the same time. This will make the migration faster but a little harder: + ```javascript + export default function transformClassProperties(api, options) { + let { setPublicClassFields } = options.loose; + if (options.loose != null) { + if (setPublicClassFields != null) throw new Error(); + setPublicClassFields = options.loose; + } + ``` + +I prefer the first alternative, since it makes it possible for our users to gradually migrate to the new options and gradually makes the `loose` options noops in users' configs while migrating. + +# How we teach this + +This RFC proposed the addition of a new set of options in a way that every option can affect multiple plugins, and a plugin can be affected by multiple options. + +Documenting the different `loose` and `loose`-like options wasn't too hard: every plugin had a bunch of those options, and we could document them in the plugin's page. + +A possible structure for the documentation could be a two-entry table, with all the plugins in the rows and the assumptions in the columns, marking which assumption affects which plugins. However, this would lead to an enormous highly sparse table, impossible to fit in a normal web page. + +I think that the best way of documenting these options is to put all of them in a single long list, divided in two sections: assumptions that affect standard features, and assumptions that only affect proposals. For each assumption we should write: +- The option name +- It's description +- An example (which could be interactive, using CodeSandbox) +- The affected plugins + +In the docs of each affected plugin, we should write the assumptions that affect it and link to the corresponding entry in the assumptions list. We shouldn't duplicate the description of what each assumption does, because duplicating it would likely lead to the two copies become out of sync. + +We can also provide a tool to check that the all the assumptions hold. This can't be done with an ESLint plugin because almost all the assumptions are about runtime semantics hard to statically analyze, but we can do it using a Babel plugin which should run while testing, and which injects assertions in the transpiled code: + +```javascript +// input code + +foo?.bar; +``` + +```javascript +// output code + +(() => { + const _tmp = foo; + if (_tmp == null && _tmp !== null && _tmp !== undefined) { + throw new Error(` + Invalid assumption - noDocumentAll. + + "noDocumentAll: true" implies that ?. and ?? are never + used with the special document.all object. + This assumption has been violated, so you should + disable it in your config. + `); + } + reutrn _tmp +})?.bar +``` + +
+Config + +```jsonc +// babel.config.json +{ + "assumptions": { + "noDocumentAll": true + }, + "env": { + "test": { + "plugins": ["@babel/validate-assumptions"] + } + } +} +``` + +
+ +# Open questions + +- Should we try to pass to the presets at least a _partial_ `assumptions` object? Currently `@babel/preset-env` relies on `loose` to enable/disable the `typeof-symbol` plugin. +- Should we validate the list of `assumptions` in `@babel/core`, and disallow unknown ones? This would make it impossible for third-party plugins to introduce their own assumptions, but it also means that it's easier for us to introduce new assumptions without risking ecosystem incompatibilities. +- Should assumptions always default to `false`? Currently everything defaults to being spec-compliant, except for the `arrow-functions` plugin which has a `spec: true` option as an opt-in. +- ([@JLHwung](https://github.com/JLHwung)) Should we further infer `assumptions` from `targets`? i.e. `{ targets: "node 8" }` can imply `{ assumptions: { noDocumentAll: true } }`. + + + +## Frequently Asked Questions + + + + From 7e28875e31d51209b5693a116fd2b02c98663fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 8 Jun 2020 01:03:46 +0200 Subject: [PATCH 02/30] Add "Related Discussions" section --- rfcs/0000-top-level-assumptions.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 435c485..c93331b 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -310,11 +310,6 @@ foo?.bar; in this section. --> - +## Related Discussions +- [2020-04-02 notes](https://github.com/babel/notes/blob/e4699d49a119877c622255bde259d4dfb84c0d0e/2020/04-02.md) From 0f60d740aacc3b25635b3761cbcfd78b5435d6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 13 Jun 2020 21:37:22 +0200 Subject: [PATCH 03/30] Apply suggestions from code review Co-authored-by: Brian Ng --- rfcs/0000-top-level-assumptions.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index c93331b..993c3a1 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -14,9 +14,9 @@ Many of our plugins have a `loose` option, which enables the compiler to make so The `loose` option has been around since `6to5`: at first as a top level option, and then it was split into each plugin as a catch all for anything that we wanted to be less spec compliant. -However, `loose` has some problems: namely that the term itself is not clear what it means, and _should_ be more related to a part of the language rather than to the plugin that it's compiling it (see the "Motivation" section for more details). A lot of this behavior is documented with a single example, so in the future we’ll want to be specific with the assumptions themselves and maybe provide a set of tests/codesandboxes explaining differences. +However, `loose` has some problems: namely the term itself is not really descriptive at all and _should_ be named after the part of the language it affects rather than the plugin that's compiling it (see the "Motivation" section for more details). A lot of this behavior is documented with a single example, so in the future we’ll want to be specific with the assumptions themselves and maybe provide a set of tests/codesandboxes explaining the differences. -This RFC proposes introducing a new *top-level* option, `"assumptions"`, which is an object containing different flags which can simplify the output code. +This RFC proposes introducing a new *top-level* option, `"assumptions"`, which is an object containing different flags that can simplify the code that Babel generates. These flags have two characteristics: - They specify _something_ about a specific language feature, and not about a specific Babel plugin. - Different flags can toggle different unrelated optimizations in the same plugin, instead of toggling both of them with a single generic `"loose"` option. @@ -94,7 +94,7 @@ for (let i = 0; i < arr.length; i++) { # Motivation The `loose` options have different problems: -- _"What is loose?"_ It's not always clear what assumptions `loose` makes. You always have to check in the docs, end even the docs often only partially mention what `loose` means in that specific context. +- _"What is loose?"_ Since `loose` is not descriptive, it requires users to check a plugin's docs to see what assumptions it makes (and the docs often only partially mention what `loose` means in a specific context). - _"How loose is loose?"_ Is making `loose` "looser" a breaking change? We have been considering it as such: for this reason, we have been introducing different `loose`-like options in some plugins. For example, `transform-for-of` supports `loose`, `assumeArray` and `allowArrayLike`. - There are cross-dependencies between the `loose` option of different plugins: for example, `proposal-class-properties`'s loose mode must always match `proposal-private-methods`'s (otherwise we throw an error). This has already caused problems: [babel/babel#11622](https://github.com/babel/babel/issues/11622). - Some plugins should be aware of other plugins' `loose` option value. For example, we sometimes need to partially transpile optional chaining in the class properties plugin ([babel/babel#11248](https://github.com/babel/babel/pull/11248)). Should we add a new `optionalChainingLoose` option to `proposal-private-methods` and `proposal-class-properties`? Or should we use a cross-plugin communication channel to share it? What about when someone has the private methods plugin enabled, but not the optional chaining one? @@ -115,7 +115,7 @@ type Assumptions = { }; ``` -This new options should be allowed in the following locations: +This new option should be allowed in the following locations: - In programmatic options passed, for example, to `babel.transform()` or to `babel-loader`. - In `babel.config.json` and `.babelrc.json` top-level options. - In `overrides` blocks. This is useful, for example, to enable a possible `noDocumentAll` assumption on a folder containing server-side code and not inside one containing client-side code. @@ -126,7 +126,7 @@ There are two main kinds of presets: framework-specific presets, like `babel-pre ## Configuration merging -Multiple `"assumptions"` object should be merged using `Object.assign`, instead of by overwriting the object as it happens for other options. +Multiple `"assumptions"` objects should be merged using `Object.assign`, and not overwritten like other options. This makes it easy, for example, to enable one additional assumption for a specific folder. Also, it still keeps the ability of disabling an assumption simply by setting it to `false`. They should be merged considering the following precedence, which is the same as what is already used for other options: From 0b71d95f2180c7837d20c5cac64ec7d9d8cffda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 19 Oct 2020 17:12:47 +0200 Subject: [PATCH 04/30] Update names --- rfcs/0000-top-level-assumptions.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 993c3a1..f46c3c6 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -152,25 +152,25 @@ The different `loose` or `loose`-like options we currently have in our plugins m | Assumption | Behavior | Current option | Repl | Notes | |:-----------|:---------|:---------------|:----:|:-----:| -| `usePlusForTemplates` | Transform `` `a${x}b` `` to `"a" + x + "b"` instead of `"a".concat(x, "b")` | `loose` in `transform-template-literals` | -| `noFrozenTemplateObject` | Don't use `Object.freeze` for the template object created for tagged template literals. This effectively means using the `taggedTemplateLiteralLoose` helper instead of `taggedTemplateLiteral` | `loose` in `transform-template-literals` | +| `ignoreToPrimitiveHint` | Transform `` `a${x}b` `` to `"a" + x + "b"` instead of `"a".concat(x, "b")` | `loose` in `transform-template-literals` | +| `mutableTemplateObject` | Don't use `Object.freeze` for the template object created for tagged template literals. This effectively means using the `taggedTemplateLiteralLoose` helper instead of `taggedTemplateLiteral` | `loose` in `transform-template-literals` | | `ignoreFunctionLength` | The `.length` of a function should be cropped at the first default argument. When this option is enabled, ignore this spec requirement and don't rely on the `arguments` object | `loose` in `transform-parameters` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABMMAKAhgGkQI0QXkQCZsJsATAxAZgEpEBvAKAF8g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `iterableIsArray` | When using an iterable (in array destructuring, for-of or with spreads), assume that the iterable object is an `Array` | `loose` in `transform-destructuring` and `transform-spread`, `assumeArray` in `transform-for-of` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ2gOmQIwLoG4BQpLwB4A0EyiAnmrFNkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) (it doesn't support `assumeArray`) | 1 | | `arrayLikeIsIterable` | Allow array-like objects to be used where an iterable is expected. This can be useful, for example, to iterate DOM collections in older browsers | `allowArrayLike` in `transform-destructuring`, `transform-spread` and `transform-for-of` | | 1 | | `skipForOfIterationClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | 2 | | `arrayIndexedIteration` | When using `for-of` with an array, ignore the iterator protocol and use direct accss to its element like a `for` loop would do | `loose` in `transform-for-of` | | 2 | | `objectRestNoSymbols` | When using rest in object destructuring, don't copy symbol keys. This effectively means using the `objectWithoutPropertiesLoose` helper instead of `objectWithoutProperties` | `loose` in `transform-destructuring` and `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBA3hIDQQHTIEYQL4QLwQMYG4g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `setObjectSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | +| `setSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | | `setObjectComputedProperties` | When using computed object properties, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `computed-properties` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ3gKAhA2gDwLoC4ICYAaRAXyA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setClassMethods` | When declaring classes, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]`. This doesn't preserve the correct enumerability. | `loose` in `transform-classes` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=true&code_lz=MYGwhgzhAECC0G8BQ1oDMD2GAUBKRAvkgUA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `definePrivateAsOwnProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | -| `useCallForSuper` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | -| `inheritsLoose` (TODO: Better name) | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | +| `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | +| `superAsFunctionCall` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | +| `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 4 | | `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | -| `immutableReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | -| `noNewArrowAttempt` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 5 | +| `copyReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | +| `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 5 | 1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. 2. With the current implementation, `skipForOfIterationClosing` and `arrayIndexedIteration` should be merged in a single option. From 369abf8d28fe355f7df82bb925de1f369f9185ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 19 Oct 2020 17:15:05 +0200 Subject: [PATCH 05/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index f46c3c6..8f11a57 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -161,7 +161,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `arrayIndexedIteration` | When using `for-of` with an array, ignore the iterator protocol and use direct accss to its element like a `for` loop would do | `loose` in `transform-for-of` | | 2 | | `objectRestNoSymbols` | When using rest in object destructuring, don't copy symbol keys. This effectively means using the `objectWithoutPropertiesLoose` helper instead of `objectWithoutProperties` | `loose` in `transform-destructuring` and `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBA3hIDQQHTIEYQL4QLwQMYG4g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | -| `setObjectComputedProperties` | When using computed object properties, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `computed-properties` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ3gKAhA2gDwLoC4ICYAaRAXyA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `setComputedProperties` | When using computed object properties, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `computed-properties` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ3gKAhA2gDwLoC4ICYAaRAXyA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setClassMethods` | When declaring classes, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]`. This doesn't preserve the correct enumerability. | `loose` in `transform-classes` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=true&code_lz=MYGwhgzhAECC0G8BQ1oDMD2GAUBKRAvkgUA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | From ef71bce2df062c5a12ac85debbeebab7347c85d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 19 Oct 2020 21:46:24 +0200 Subject: [PATCH 06/30] Update rfcs/0000-top-level-assumptions.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Huáng Jùnliàng --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 8f11a57..d39d3ed 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -131,7 +131,7 @@ This makes it easy, for example, to enable one additional assumption for a speci They should be merged considering the following precedence, which is the same as what is already used for other options: - preset < `babel.config.json` < `.babelrc.json` (far from the compiled file)< `.babelrc.json` (near to the compiled file) < programmatic options -- top-level < `env` section < `overrides` +- top-level < `env` section < `overrides` < `overrides.env` Assumptions set inside a preset are not boxed inside the preset but are applied to all the plugins, for two reasons: 1. conceptually, the assumptions describe the input file and not a specific plugin enabled inside the preset; From 4b27414296fde282334be5966fc71c9c5a1ac870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 11 Nov 2020 21:06:40 +0100 Subject: [PATCH 07/30] Update rfcs/0000-top-level-assumptions.md Co-authored-by: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index d39d3ed..fcd85f0 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -257,7 +257,7 @@ foo?.bar; disable it in your config. `); } - reutrn _tmp + return _tmp; })?.bar ``` From 8ea1cbfefb8883241bac4fe3916f2ff3ee5828b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 13 Nov 2020 16:55:12 +0100 Subject: [PATCH 08/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index fcd85f0..5b58b82 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -2,11 +2,11 @@ - Repo: [`babel/babel`](https://github.com/babel/babel) - Start Date: 2020-06-08 -- RFC PR: +- RFC PR: [babel/babel#12219](https://github.com/babel/babel/pull/12219) - Related Issues: - Authors: Nicolò Ribaudo - Champion: Nicolò Ribaudo -- Implementors: +- Implementors: Nicolò Ribaudo # Summary @@ -124,6 +124,8 @@ This new option should be allowed in the following locations: Additionally, `"assumptions"` should also be allowed inside presets. There are two main kinds of presets: framework-specific presets, like `babel-preset-react-app`, and company-wide presets, used to share the same plugins accross different projects. Since assumptions describe the input code and not the used plugins, this new option fits better in company-wide presets where the person writing the preset and the person writing the input code have less "degrees of separation", but there are also use cases in framework-specific presets: for example, `babel-preset-react-app` [enables](https://github.com/facebook/create-react-app/blob/c87ab79559e98a5dae2cd0b02477c38ff6113e6a/packages/babel-preset-react-app/create.js#L151-L154) `loose: true` for `@babel/plugin-proposal-class-properties`. +To avoid conflicts between assumptions set in presets, they will only be able to _enable_ them (i.e. set them to `true`). The only way to disable an already enabled assumption is to explicitly do it in a configuration file or in programmatic options. ([discussion](https://github.com/babel/rfcs/pull/5#discussion_r507979771)) + ## Configuration merging Multiple `"assumptions"` objects should be merged using `Object.assign`, and not overwritten like other options. @@ -137,12 +139,14 @@ Assumptions set inside a preset are not boxed inside the preset but are applied 1. conceptually, the assumptions describe the input file and not a specific plugin enabled inside the preset; 2. practically, this makes it possible to have a single "personal" or "company" preset containing assumptions which apply to a user's coding practices, and re-use it in different projects without duplicating the list of assumptions. -In order to "leak" assumptions defined inside presets, we need to first resolve and instantiate all the presets, and then all the plugins with the resolved assumptions ([babel/babel#11689](https://github.com/babel/babel/pull/11689)). Currently, presets and plugins are instantiated in mixed order. -This also means that we cannot provide the defined assumptions list to the presets, because it hasn't been finalized yet when they are instantiated. +In order to expose assumptions defined inside presets to every plugin, we need to first resolve and instantiate all the presets, and then all the plugins with the resolved assumptions. This also means that we cannot provide the defined assumptions list to the presets, because it hasn't been finalized yet when they are instantiated. +This is implemented by [babel/babel#11689](https://github.com/babel/babel/pull/11689)). ## Plugin API -The first parameter passed to the plugins (often known as `api`) should have a new property: `assumptions`, which is a frozen copy of the resolved assumptions object. +The first parameter passed to the plugins (often known as `api`) should have a new method: `assumptions(name: string): boolean | undefined`, which returns `true` if the assumption has been enabled, `false` if it has been explicitly disabled, or `undefined` if it hasn't been set. We need to differentiate between `false` and `undefined` so that the arrow-function transform can default to `true` for `newableArrowFunctions`, but we may revisit this in Babel 8. + +This is implemented as a function and not as an object whose properties reflect the assumptions because it configures the plugins' caching (they are reinstantiated when an assumption they use changes). ## Assumptions list From 8bb7481591e8e9078730afad50554b2c9b3a905c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 13 Nov 2020 16:57:14 +0100 Subject: [PATCH 09/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 5b58b82..0876539 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -54,6 +54,7 @@ for (let i = 0; i < arr.length; i++) { el.logger == null ? void 0 : el.logger.log("Ok!"); } ``` +
@@ -89,6 +90,7 @@ for (let i = 0; i < arr.length; i++) { el.logger === null || el.logger === void 0 ? void 0 : el.logger.log("Ok!"); } ``` + # Motivation From 86b54a39c9b2a56506bcbce5f7859a009c02c043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 13 Nov 2020 17:04:02 +0100 Subject: [PATCH 10/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 0876539..bae11ed 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -184,11 +184,17 @@ The different `loose` or `loose`-like options we currently have in our plugins m 4. `?.` also needs to be compiled by the private fields and methods plugins ([babel/babel#11248](https://github.com/babel/babel/pull/11248), but currently there is no way to set it to `loose` 5. The current default behavior is to consider this assumption as valid, and only produce 100% spec-compliant code when the `spec` option is enabled. +### New assumptions policy + +We will only define new assumptions for standard ECMAScript features or for very stable stage 3 proposals (following the same convention we use for `@babel/preset-env`'s `shippedProposals` option). + +However, existing assumptions can be used by plugins for proposals in earlier stages of the TC39 process: for example, the `#priv in obj` plugin is likely affected by the same assumptions that affect the class private fields plugin. + # Drawbacks - This RFC introduces a very big number of new top-level options (19), and makes it relatively cheap to add new ones. Having a big number of options can add more "tooling fatigue" on the shoulders of our users, and it can make it hard for us to properly document them. However, these new options replace 22 existing plugin options, many of which have the same name (`loose`) but different behaviors. -- ([@JLHwung](https://github.com/JLHwung)) Some `assumptions` are only effective in one plugin, but users will have to go through their presets/plugins to see if they have opt-in to this plugins. Let's say there is an assumption in a stage-1 proposal and the users does not know it is no-op for their config, it may inadvertently turn into a long list of `assumptions` and the no-op assumptions can kick in once users upgrades `preset-env` which may includes it once its stage advances. +- ([@JLHwung](https://github.com/JLHwung)) Some `assumptions` are only effective in one plugin, but users will have to go through their presets/plugins to see if they have opt-in to this plugins. # Alternatives From f3854995f550755cab16c8d5570dc3d7dd87c8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 13 Nov 2020 17:32:00 +0100 Subject: [PATCH 11/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index bae11ed..40a3030 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -146,7 +146,7 @@ This is implemented by [babel/babel#11689](https://github.com/babel/babel/pull/1 ## Plugin API -The first parameter passed to the plugins (often known as `api`) should have a new method: `assumptions(name: string): boolean | undefined`, which returns `true` if the assumption has been enabled, `false` if it has been explicitly disabled, or `undefined` if it hasn't been set. We need to differentiate between `false` and `undefined` so that the arrow-function transform can default to `true` for `newableArrowFunctions`, but we may revisit this in Babel 8. +The first parameter passed to the plugins (often known as `api`) should have a new method: `assumptions(name: string): boolean`, which returns whether or not the assumption has been enabled. If a plugin is asking about an assumption not supported by the used `@babel/core` version, it will return `false`. This is implemented as a function and not as an object whose properties reflect the assumptions because it configures the plugins' caching (they are reinstantiated when an assumption they use changes). From b697eb5f177b90b281c156fc1c6c3bf9e16cc5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 13 Nov 2020 23:36:52 +0100 Subject: [PATCH 12/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 40a3030..de5e476 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -1,4 +1,4 @@ -# RFC: Loose +# RFC: Replace "loose" options with a top-level "assumptions" object - Repo: [`babel/babel`](https://github.com/babel/babel) - Start Date: 2020-06-08 From b7b0d5988586f443e301a523b22db72e3a765aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 10 Dec 2020 14:07:41 +0100 Subject: [PATCH 13/30] Update rfcs/0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index de5e476..558f1fc 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -146,7 +146,7 @@ This is implemented by [babel/babel#11689](https://github.com/babel/babel/pull/1 ## Plugin API -The first parameter passed to the plugins (often known as `api`) should have a new method: `assumptions(name: string): boolean`, which returns whether or not the assumption has been enabled. If a plugin is asking about an assumption not supported by the used `@babel/core` version, it will return `false`. +The first parameter passed to the plugins (often known as `api`) should have a new method: `assumptions(name: string): boolean | undefined`, which returns whether or not the assumption has been enabled. If a plugin is asking about an assumption not enabled or not supported by the used `@babel/core` version, it will return `undefined`. This is implemented as a function and not as an object whose properties reflect the assumptions because it configures the plugins' caching (they are reinstantiated when an assumption they use changes). From b8bc056469510bb1f328c5885940ed974a71cb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 10 Dec 2020 23:10:39 +0100 Subject: [PATCH 14/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 558f1fc..d03e492 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -174,6 +174,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `superAsFunctionCall` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 4 | +| `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `copyReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | | `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 5 | From 0fca25c5b558f317da672797a04901699b2787d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 10 Dec 2020 23:41:34 +0100 Subject: [PATCH 15/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index d03e492..15d3c16 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -28,7 +28,7 @@ These flags have two characteristics: { "assumptions": { "noDocumentAll": true, - "noGetterSideEffects": true, + "pureGetters": true, "iterableIsArray": true }, "presets": ["@babel/preset-env"] @@ -63,7 +63,7 @@ for (let i = 0; i < arr.length; i++) { { "assumptions": { "noDocumentAll": false, - "noGetterSideEffects": true, + "pureGetters": true, "iterableIsArray": true }, "presets": ["@babel/preset-env"] From 37b329d5af687a9fc8db273804c02cee55e27329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 12 Dec 2020 16:32:14 +0100 Subject: [PATCH 16/30] Typo --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 15d3c16..d8e3353 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -163,7 +163,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `ignoreFunctionLength` | The `.length` of a function should be cropped at the first default argument. When this option is enabled, ignore this spec requirement and don't rely on the `arguments` object | `loose` in `transform-parameters` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABMMAKAhgGkQI0QXkQCZsJsATAxAZgEpEBvAKAF8g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `iterableIsArray` | When using an iterable (in array destructuring, for-of or with spreads), assume that the iterable object is an `Array` | `loose` in `transform-destructuring` and `transform-spread`, `assumeArray` in `transform-for-of` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ2gOmQIwLoG4BQpLwB4A0EyiAnmrFNkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) (it doesn't support `assumeArray`) | 1 | | `arrayLikeIsIterable` | Allow array-like objects to be used where an iterable is expected. This can be useful, for example, to iterate DOM collections in older browsers | `allowArrayLike` in `transform-destructuring`, `transform-spread` and `transform-for-of` | | 1 | -| `skipForOfIterationClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | 2 | +| `skipForOfIteratorClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | 2 | | `arrayIndexedIteration` | When using `for-of` with an array, ignore the iterator protocol and use direct accss to its element like a `for` loop would do | `loose` in `transform-for-of` | | 2 | | `objectRestNoSymbols` | When using rest in object destructuring, don't copy symbol keys. This effectively means using the `objectWithoutPropertiesLoose` helper instead of `objectWithoutProperties` | `loose` in `transform-destructuring` and `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBA3hIDQQHTIEYQL4QLwQMYG4g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | From e59b6dc9f8644d284a799002bfe21d4abc5687af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 12 Dec 2020 21:42:51 +0100 Subject: [PATCH 17/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index d8e3353..2321795 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -163,27 +163,25 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `ignoreFunctionLength` | The `.length` of a function should be cropped at the first default argument. When this option is enabled, ignore this spec requirement and don't rely on the `arguments` object | `loose` in `transform-parameters` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABMMAKAhgGkQI0QXkQCZsJsATAxAZgEpEBvAKAF8g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `iterableIsArray` | When using an iterable (in array destructuring, for-of or with spreads), assume that the iterable object is an `Array` | `loose` in `transform-destructuring` and `transform-spread`, `assumeArray` in `transform-for-of` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ2gOmQIwLoG4BQpLwB4A0EyiAnmrFNkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) (it doesn't support `assumeArray`) | 1 | | `arrayLikeIsIterable` | Allow array-like objects to be used where an iterable is expected. This can be useful, for example, to iterate DOM collections in older browsers | `allowArrayLike` in `transform-destructuring`, `transform-spread` and `transform-for-of` | | 1 | -| `skipForOfIteratorClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | 2 | -| `arrayIndexedIteration` | When using `for-of` with an array, ignore the iterator protocol and use direct accss to its element like a `for` loop would do | `loose` in `transform-for-of` | | 2 | +| `skipForOfIteratorClosing` | When using `for-of` with an iterator, it should always be closed with `.return()` and with `.throw()` in case of an error. This option allows skipping those methods | `loose` in `transform-for-of` | | | | `objectRestNoSymbols` | When using rest in object destructuring, don't copy symbol keys. This effectively means using the `objectWithoutPropertiesLoose` helper instead of `objectWithoutProperties` | `loose` in `transform-destructuring` and `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBA3hIDQQHTIEYQL4QLwQMYG4g&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setSpreadProperties` | When using object spread, use `Object.assign` to copy the properties instead of cloning their property descriptors with `Object.defineProperty` | `loose`&`useBuiltIns` in `proposal-object-rest-spread` | | | `setComputedProperties` | When using computed object properties, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `computed-properties` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=false&code_lz=G4QwTgBCELwQ3gKAhA2gDwLoC4ICYAaRAXyA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setClassMethods` | When declaring classes, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]`. This doesn't preserve the correct enumerability. | `loose` in `transform-classes` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=true&code_lz=MYGwhgzhAECC0G8BQ1oDMD2GAUBKRAvkgUA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | +| `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superAsFunctionCall` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | -| `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 4 | +| `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `copyReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | -| `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 5 | +| `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | 1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. -2. With the current implementation, `skipForOfIterationClosing` and `arrayIndexedIteration` should be merged in a single option. -3. Currently, the `loose` option must be the same for these plugins or it will throw an error. We have a workaround in `@babel/preset-env` to allow setting `loose` there differently from these plugins ([babel/babel#11634](https://github.com/babel/babel/pull/11634)) -4. `?.` also needs to be compiled by the private fields and methods plugins ([babel/babel#11248](https://github.com/babel/babel/pull/11248), but currently there is no way to set it to `loose` -5. The current default behavior is to consider this assumption as valid, and only produce 100% spec-compliant code when the `spec` option is enabled. +2. Currently, the `loose` option must be the same for these plugins or it will throw an error. We have a workaround in `@babel/preset-env` to allow setting `loose` there differently from these plugins ([babel/babel#11634](https://github.com/babel/babel/pull/11634)) +3. `?.` also needs to be compiled by the private fields and methods plugins ([babel/babel#11248](https://github.com/babel/babel/pull/11248), but currently there is no way to set it to `loose` +4. The current default behavior is to consider this assumption as valid, and only produce 100% spec-compliant code when the `spec` option is enabled. ### New assumptions policy From ae33e7bad2c186803261c9a2f5ff91b1536bca5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 14 Dec 2020 19:57:57 +0100 Subject: [PATCH 18/30] Add `constantSuper` assumption --- rfcs/0000-top-level-assumptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 2321795..0242b22 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -171,6 +171,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superAsFunctionCall` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | +| `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | From 5be64a9be88a644144bd4fdeaa11ae62bbfc7cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 14 Dec 2020 21:48:37 +0100 Subject: [PATCH 19/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 0242b22..541ee61 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -174,7 +174,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | -| `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `copyReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | | `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | From 37a2c529829b267d03817b4c08723df804620ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 15 Dec 2020 11:50:40 +0100 Subject: [PATCH 20/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 541ee61..40a665d 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -170,13 +170,13 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `setClassMethods` | When declaring classes, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]`. This doesn't preserve the correct enumerability. | `loose` in `transform-classes` | [🔗](https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&spec=false&loose=true&code_lz=MYGwhgzhAECC0G8BQ1oDMD2GAUBKRAvkgUA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setPublicClassFields` | When using computed public class fields, use `[[Set]]` semantics (i.e. use an assignment) instead of `[[Define]]` | `loose` in `proposal-class-properties` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oDMCWBTEATaAvNAIwDcSAvkA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | -| `superAsFunctionCall` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | +| `superIsCallableConstructor` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | -| `copyReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | +| `constantReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | | `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | 1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. From 9bf92185714b8b08c8d53de693bbc4bb6895e64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 15 Dec 2020 18:24:04 +0100 Subject: [PATCH 21/30] Update rfcs/0000-top-level-assumptions.md Co-authored-by: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 40a665d..d754218 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -175,7 +175,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `setModuleMeta` | When compiling ESM to CJS, Babel defined a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | +| `setModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `constantReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | | `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | From d17679729507e288d095bbaebcab714057a807c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 12 Jan 2021 16:39:46 +0100 Subject: [PATCH 22/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index d754218..c075b95 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -172,7 +172,6 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superIsCallableConstructor` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `inheritAsObjectCreate` | Use the `inheritsLoose` helper instead of `inherits` for derived classes | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `setModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | @@ -184,6 +183,10 @@ The different `loose` or `loose`-like options we currently have in our plugins m 3. `?.` also needs to be compiled by the private fields and methods plugins ([babel/babel#11248](https://github.com/babel/babel/pull/11248), but currently there is no way to set it to `loose` 4. The current default behavior is to consider this assumption as valid, and only produce 100% spec-compliant code when the `spec` option is enabled. +### `loose` features not ported to `assumptions` + +- It's not clear if we still need `inheritsLoose` helper injected by the `transform-classes` plugin ([#5 (comment by @jridgewell)](https://github.com/babel/rfcs/pull/5#discussion_r543925453)). + ### New assumptions policy We will only define new assumptions for standard ECMAScript features or for very stable stage 3 proposals (following the same convention we use for `@babel/preset-env`'s `shippedProposals` option). From c59701f8df41b934d7084698c70c152b5aad9810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 30 Jan 2021 23:56:56 +0100 Subject: [PATCH 23/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index c075b95..ba6eb4c 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -174,7 +174,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `setModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | +| `enumerableModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `constantReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | | `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | From 4793d98db18adb189b1f24b7ab66165ca43b4aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sun, 31 Jan 2021 02:27:10 +0100 Subject: [PATCH 24/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index ba6eb4c..1964f1a 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -172,6 +172,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superIsCallableConstructor` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | +| `noCallClass` | Assume that classes are always instantiated with `new` and that the code never tries to call them as function. This lets Babel skipping the `this instanceof ThisClass` check (`_classCallCheck`). | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `enumerableModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | From decb846df3450acdabd3e824001144166504081c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 12 Feb 2021 00:48:17 +0100 Subject: [PATCH 25/30] Update 0000-top-level-assumptions.md --- rfcs/0000-top-level-assumptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index 1964f1a..c6fdee0 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -172,12 +172,12 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superIsCallableConstructor` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `noCallClass` | Assume that classes are always instantiated with `new` and that the code never tries to call them as function. This lets Babel skipping the `this instanceof ThisClass` check (`_classCallCheck`). | `loose` in `transform-classes` | | +| `noClassCalls` | Assume that classes are always instantiated with `new` and that the code never tries to call them as function. This lets Babel skipping the `this instanceof ThisClass` check (`_classCallCheck`). | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `enumerableModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `constantReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | -| `newableArrowFunctions` | Do not check that arrow functions are never instantiated using `new` | `spec` in `transform-arrow-functions` | | 4 | +| `noNewArrows` | Assume that the code never tries to instantiatearrow function using `new`, so Babel can avoid injecting checks to prevent it | `spec` in `transform-arrow-functions` | | 4 | 1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. 2. Currently, the `loose` option must be the same for these plugins or it will throw an error. We have a workaround in `@babel/preset-env` to allow setting `loose` there differently from these plugins ([babel/babel#11634](https://github.com/babel/babel/pull/11634)) From 03978f10daed33905fb9ddaeb1fc052a81a7b74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 12 Feb 2021 01:13:42 +0100 Subject: [PATCH 26/30] Update rfcs/0000-top-level-assumptions.md Co-authored-by: Jordan Harband --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index c6fdee0..bb02fc7 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -177,7 +177,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `enumerableModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | | `constantReexports` | When re-exporting an imported value, assume that it's value doesn't change and set it with a simple assignment | `loose` in `transform-modules-commonjs`, `transform-modules-umd`, `transform-modules-amd` _(not documented)_ | | | -| `noNewArrows` | Assume that the code never tries to instantiatearrow function using `new`, so Babel can avoid injecting checks to prevent it | `spec` in `transform-arrow-functions` | | 4 | +| `noNewArrows` | Assume that the code never tries to instantiate arrow function using `new`, so Babel can avoid injecting checks to prevent it | `spec` in `transform-arrow-functions` | | 4 | 1. `iterableIsArray` is not compatible with `arrayLikeIsIterable`, even if array-like objects could work with `iterableIsArray` in cases where we only rely on indexed access and not on array methods. 2. Currently, the `loose` option must be the same for these plugins or it will throw an error. We have a workaround in `@babel/preset-env` to allow setting `loose` there differently from these plugins ([babel/babel#11634](https://github.com/babel/babel/pull/11634)) From fc5b7f1719f4918b55205fda3896a0f7729565b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 12 Feb 2021 10:01:37 +0100 Subject: [PATCH 27/30] Update rfcs/0000-top-level-assumptions.md Co-authored-by: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> --- rfcs/0000-top-level-assumptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index bb02fc7..f072c7b 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -172,7 +172,7 @@ The different `loose` or `loose`-like options we currently have in our plugins m | `privateFieldsAsProperties` | Instead of storing private fields and methods using a `WeakMap` or a `WeakSet`, define them as own non-enumerable properties of the class instance | `loose` in `proposal-class-properties` _(not documented)_, in `proposal-private-methods` and `proposal-private-property-in-object` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1oGIBmBLApiAJtALzQCMA3CtFWgLY4AuAFgPb4AUAlIlQJABOjAK78AdtGZYIAOky4ClVAF8kSoA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 2 | | `superIsCallableConstructor` | When this option is enabled, `super(arg1)` will be transpiled to `BaseClass.call(this, arg1)`. This means that it won't work with native classes or with built-ins, but only with compiled classes or ES5 constructors | `loose` in `transform-classes` | | | `constantSuper` | The `super` binding in classes can be changed using `setPrototypeOf`, so it's not possible to statically know it. With this option Babel can assume that the superclass is never changed at runtime. | `loose` in `transform-classes`, `proposal-class-properties`, `proposal-private-methods` and `proposal-decorators`. It should also be added to `transform-object-super`. | [🔗](https://babeljs.io/repl#?browsers=chrome%2040&build=&builtIns=false&spec=false&loose=false&code_lz=MYGwhgzhAEBC0G8BQ1oFsCmAXAFgewBMAKASkWjBAwCcsiAiWAQnpIG5oBfJbpUSGAGFEKdNnzEyCClVoNBLdlx5I-4KNACC0DAA8sGAHYEY8ZKmoBXQ6RGpUAegfQAKgAkAkgGVoAGQ8AcgCiTKKoEJYADjQAdJi4hKRsoty8APIARgBWGMBYMRDYAArUeFhlAJ7RaQBmRJoxkaXlWFUYADTQgo3NldHsqoYYAO5apDFWNuxAA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | -| `noClassCalls` | Assume that classes are always instantiated with `new` and that the code never tries to call them as function. This lets Babel skipping the `this instanceof ThisClass` check (`_classCallCheck`). | `loose` in `transform-classes` | | +| `noClassCalls` | Assume that classes are always instantiated with `new` and that the code never tries to call them as a function. This lets Babel skip the `this instanceof ThisClass` check (`_classCallCheck`). | `loose` in `transform-classes` | | | `noDocumentAll` | When compiling the `??` and `?.` operators, assume that they are never used with `document.all` and thus `== null` is safe | `loose` in `proposal-optional-chaining` and `proposal-nullish-coalescing-operator` | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=false&code_lz=IYfgdARg3AUMAEIT2kA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cenv&prettier=false&targets=&version=7.10.1&externalPlugins=) | 3 | | `pureGetters` | When an expression that might invoke getters needs to be evaluated multiple times, Babel caches its value. When this option is enabled, the expression can be safely re-evaluated. For example, `a.b?.()` can be compiled to `a.b != null && a.b()` without caching `a.b` | `loose` in `proposal-optional-chaining` and in `proposal-object-rest-spread` _(not documented)_ | [🔗](https://babeljs.io/repl#?browsers=chrome%2070&build=&builtIns=false&spec=false&loose=true&code_lz=IYOgRg_CAUCUQ&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env&prettier=false&targets=&version=7.10.1&externalPlugins=) | | `enumerableModuleMeta` | When compiling ESM to CJS, Babel defines a non-enumerable, non-witable, non-configurable `__esModule` property on the `exports` object. When this option is enabled, that property is set using a simple assignment | `loose` in `transform-modules-commonjs` | From 3fd8385d4b36728570b4005386b2a56def10f96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 19 Feb 2021 13:55:32 +0100 Subject: [PATCH 28/30] Update FAQ section --- rfcs/0000-top-level-assumptions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rfcs/0000-top-level-assumptions.md b/rfcs/0000-top-level-assumptions.md index f072c7b..4804192 100644 --- a/rfcs/0000-top-level-assumptions.md +++ b/rfcs/0000-top-level-assumptions.md @@ -196,7 +196,7 @@ However, existing assumptions can be used by plugins for proposals in earlier st # Drawbacks -- This RFC introduces a very big number of new top-level options (19), and makes it relatively cheap to add new ones. Having a big number of options can add more "tooling fatigue" on the shoulders of our users, and it can make it hard for us to properly document them. However, these new options replace 22 existing plugin options, many of which have the same name (`loose`) but different behaviors. +- This RFC introduces a very big number of new top-level options (20), and makes it relatively cheap to add new ones. Having a big number of options can add more "tooling fatigue" on the shoulders of our users, and it can make it hard for us to properly document them. However, these new options replace 22 existing plugin options, many of which have the same name (`loose`) but different behaviors. - ([@JLHwung](https://github.com/JLHwung)) Some `assumptions` are only effective in one plugin, but users will have to go through their presets/plugins to see if they have opt-in to this plugins. @@ -298,9 +298,9 @@ foo?.bar; # Open questions -- Should we try to pass to the presets at least a _partial_ `assumptions` object? Currently `@babel/preset-env` relies on `loose` to enable/disable the `typeof-symbol` plugin. -- Should we validate the list of `assumptions` in `@babel/core`, and disallow unknown ones? This would make it impossible for third-party plugins to introduce their own assumptions, but it also means that it's easier for us to introduce new assumptions without risking ecosystem incompatibilities. -- Should assumptions always default to `false`? Currently everything defaults to being spec-compliant, except for the `arrow-functions` plugin which has a `spec: true` option as an opt-in. +- Should we try to pass to the presets at least a _partial_ `assumptions` object? Currently `@babel/preset-env` relies on `loose` to enable/disable the `typeof-symbol` plugin. **ANSWER:** No, presets can only _produce_ assumptions and not _consume_ them. +- Should we validate the list of `assumptions` in `@babel/core`, and disallow unknown ones? This would make it impossible for third-party plugins to introduce their own assumptions, but it also means that it's easier for us to introduce new assumptions without risking ecosystem incompatibilities. **ANSWER:** Yes, the compatibility problems are easily solved checking Babel's version. +- Should assumptions always default to `false`? Currently everything defaults to being spec-compliant, except for the `arrow-functions` plugin which has a `spec: true` option as an opt-in. **ANSWER:** Yes, we will make `noNewArrows` default to `false` in Babel 8. - ([@JLHwung](https://github.com/JLHwung)) Should we further infer `assumptions` from `targets`? i.e. `{ targets: "node 8" }` can imply `{ assumptions: { noDocumentAll: true } }`.