No stronger opinion on both implementations, I just think the scope-based is clearer, and iterating over scope is always faster than node. The only bad point in this implementation we don't have specific ScopeFlags for class methods, thus we need to check if the parent of the function is a `MethodDefinition`
Missing error that super property inside plain function.
```js
class C {
constructor() {
function g() {
// * It is a Syntax Error if PropName of MethodDefinition is not "constructor" and HasDirectSuper of MethodDefinition is true.
super();
}
}
method() {
function func() {
// It is a Syntax Error if FunctionBody Contains SuperProperty is true.
super.good();
}
}
}
```
I am not sure why test262 doesn't cover tests like that
The simplified version of the evaluation of `a = a || b` is:
> AssignmentExpression : LeftHandSideExpression = LogicalORExpression || LogicalANDExpression
> 1. Let lRef be ? Evaluation of LeftHandSideExpression.
> 2. Let llRef be ? Evaluation of LogicalORExpression.
> 3. Let llVal be ? GetValue(llRef).
> 4. If ToBoolean(llVal) is true
> a. Perform ? PutValue(lRef, llVal).
> b. return llVal.
> 5. Let lrRef be ? Evaluation of LogicalANDExpression.
> 6. Let rRef be ? GetValue(lrRef).
> 7. Let rVal be ? GetValue(rRef). [Note GetValue(rRef) returns rRef itself]
> 8. Perform ? PutValue(lRef, rVal).
> 9. Return rVal.
The simplified version of the evaluation of `a ||= b` is:
> AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
> 1. Let lRef be ? Evaluation of LeftHandSideExpression.
> 2. Let lVal be ? GetValue(lRef).
> 3. If ToBoolean(lVal) is true, return lVal.
> 4. Let rRef be ? Evaluation of AssignmentExpression.
> 5. Let rVal be ? GetValue(rRef).
> 6. Perform ? PutValue(lRef, rVal).
> 7. Return rVal.
The difference of these is that
- the evaluation of `a` is done twice for `a = a || b`, one with `1. Let lRef be ? Evaluation of LeftHandSideExpression` and one with `2. Let llRef be ? Evaluation of LogicalORExpression.`. This is same with #8366, #8367.
- `PutValue(lRef, llVal)` is performed when `ToBoolean(lVal)` is `true`.
So `x = x || 1` can be compressed to `x ||= 1` when the conditions written in #8366 are met and `PutValue(lRef, llVal)` does not have a side effect. When `a` is a non-global identifier (and not a reference created by a `with` statement), these conditions are met.
**References**
- [Spec of `||`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-binary-logical-operators-runtime-semantics-evaluation)
- [Spec of `=` / `||=`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-binary-logical-operators-runtime-semantics-evaluation)
The simplified version of the evaluation of `a += b` is:
> AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
> 1. Let lRef be ? Evaluation of LeftHandSideExpression.
> 2. Let lVal be ? GetValue(lRef).
> 3. Let rRef be ? Evaluation of AssignmentExpression.
> 4. Let rVal be ? GetValue(rRef).
> 5. Let r be ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal).
> 6. Perform ? PutValue(lRef, r).
> 7. Return r.
The simplified version of the evaluation of `a = a + b` is:
> AssignmentExpression : LeftHandSideExpression = AssignmentExpressionLeft + AssignmentExpressionRight
> 1. Let lRef be ? Evaluation of LeftHandSideExpression.
> 2. Let alRef be ? Evaluation of AssignmentExpressionLeft.
> 3. Let alVal be ? GetValue(alRef).
> 4. Let arRef be ? Evaluation of AssignmentExpressionRight.
> 5. Let arVal be ? GetValue(arRef).
> 6. Let rRef be ? ApplyStringOrNumericBinaryOperator(alVal, opText, arVal).
> 7. Let rVal be ? GetValue(rRef). [Note GetValue(rRef) returns rRef itself]
> 8. Perform ? PutValue(lRef, rVal).
> 9. Return rVal.
The difference of these is that the evaluation of `a` is done twice for `a = a + b`, one with `1. Let lRef be ? Evaluation of LeftHandSideExpression` and one with `2. Let alRef be ? Evaluation of AssignmentExpressionLeft.`
So this is same with #8366 and can be compressed similarly when the conditions are met (`a.b = a.b + c` -> `a.b += c`).
**References**
- [Spec of `=`, `+=`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators-runtime-semantics-evaluation)
- [Spec of `+`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-addition-operator-plus-runtime-semantics-evaluation)
Fix panic if a private accessor is present in class which also has property. e.g.:
```js
let C = class C {
prop = 1;
accessor #private = 2;
};
```
Panic occurred due to trying to unwrap `brand` property, but it's `None` because no private instance methods in the class.
No temp var is required for class if it contains static private method which is not referenced within class. e.g.:
```js
let C = class {
static #method() {}
};
```
->
```js
let C = class {};
function _method() {}
```
Small improvement. Use `Class::type` field to determine if class is declaration/expression. Not sure why it did it in such a complicated way previously!
In the following case, async methods can be nested in another async method. The implementation is changing to store `super_methods` on a stack, and then we can store super method information in the correct `super_methods` map.
```js
const outer = {
value: 0,
async method() {
() => super.value;
const inner = {
value: 0,
async method() {
() => super.value;
}
};
() => super.value;
}
};
```
I refactored the code in `tasks/prettier_conformance` primarily to make
the output more readable when using `--filter`.
But I also discovered that our previous implementation did not correctly
handle Prettier's behavior of adding a blank line at the EOF.
In addition, I resolved a problem where test specs that used patterns
like `runFormatTest(_, parsers)` were unable to locate the correct
snapshot output.
As a result, compatibility has also improved slightly. 😉
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Follow-on after #8024.
Move code out of `visit_expression`.
`visit_expression` is marked `#[inline]`, which is a good idea because it's a hot path and most of the time the `Expression` is not `super()` and the function does nothing.
But this means we want `visit_expression` to be as small as possible to reduce the cost of inlining it. So only retain the fast path for "Is it `super()`? No it's not, so just continue traversal." and move everything else out into a separate function.
Follow-on after #8024. Don't inline `visit_statements` visitor method. This visitor is not so small, and always executes unconditionally. The compiler can decide whether to inline it or not. Where `#[inline]` is really valuable is:
1. Where the function is tiny so the cost of moving it into the caller is small. and
2. The function gets called a lot e.g. `visit_expression`, `visit_statement`, `visit_identifier_reference`.
3. Most commonly the function checks something and exits "nothing to do here". e.g. `visit_expression` where you only need to transform a particular type of `Expression`.
Follow-on after #8024. Pure refactor.
Re-order the methods of the `ConstructorBodyThisAfterSuperInserter` visitor. Intent is that the call path flows from top to bottom, so the "story" makes sense when you read the code starting from the top.
Follow-on after #8024.
Use `NonEmptyStack` instead of `Stack`.
`NonEmptyStack` is cheaper as `last` / `last_mut` always returns `T`, rather than `Option<T>`, so there's no need to branch on whether it's `Some` or not.
The only downside of `NonEmptyStack` is that it always contains 1 dummy entry at the start (so that it's never empty). This means that it always allocates, unlike `Stack` which doesn't allocate unless you push something into it.
So `NonEmptyStack` is always the better choice unless either:
1. The stack will likely never have anything pushed to it. or
2. The type the stack holds is large or expensive to construct, so there's a high cost in having to create an initial dummy value.
In this case:
* The type is `bool` - very small and cheap to construct.
* The stack will be pushed to when entering a function. Very few JS files contain no functions at all, so the stack will always need to allocate, even if we used `Stack`.
So this case doesn't satisfy either of the circumstances in which `Stack` is the better choice.