fix(54465): Broken emit with private field in class decorator (#54679)

This commit is contained in:
Oleksandr T
2023-06-24 00:09:48 +03:00
committed by GitHub
parent 39da6b1c63
commit de6e6abbac
14 changed files with 361 additions and 8 deletions

View File

@@ -248,6 +248,7 @@ import {
getCombinedModifierFlags,
getCombinedNodeFlags,
getContainingClass,
getContainingClassExcludingClassDecorators,
getContainingClassStaticBlock,
getContainingFunction,
getContainingFunctionOrClassStaticBlock,
@@ -31407,7 +31408,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// Lookup the private identifier lexically.
function lookupSymbolForPrivateIdentifierDeclaration(propName: __String, location: Node): Symbol | undefined {
for (let containingClass = getContainingClass(location); !!containingClass; containingClass = getContainingClass(containingClass)) {
for (let containingClass = getContainingClassExcludingClassDecorators(location); !!containingClass; containingClass = getContainingClass(containingClass)) {
const { symbol } = containingClass;
const name = getSymbolNameForPrivateIdentifier(symbol, propName);
const prop = (symbol.members && symbol.members.get(name)) || (symbol.exports && symbol.exports.get(name));
@@ -31547,23 +31548,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) {
grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right));
}
if (isAnyLike) {
if (lexicallyScopedSymbol) {
return isErrorType(apparentType) ? errorType : apparentType;
}
if (!getContainingClass(right)) {
if (getContainingClassExcludingClassDecorators(right) === undefined) {
grammarErrorOnNode(right, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
return anyType;
}
}
prop = lexicallyScopedSymbol ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedSymbol) : undefined;
// Check for private-identifier-specific shadowing and lexical-scoping errors.
if (!prop && checkPrivateIdentifierPropertyAccess(leftType, right, lexicallyScopedSymbol)) {
return errorType;
prop = lexicallyScopedSymbol && getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedSymbol);
if (prop === undefined) {
// Check for private-identifier-specific shadowing and lexical-scoping errors.
if (checkPrivateIdentifierPropertyAccess(leftType, right, lexicallyScopedSymbol)) {
return errorType;
}
const containingClass = getContainingClassExcludingClassDecorators(right);
if (containingClass && isPlainJsFile(getSourceFileOfNode(containingClass), compilerOptions.checkJs)) {
grammarErrorOnNode(right, Diagnostics.Private_field_0_must_be_declared_in_an_enclosing_class, idText(right));
}
}
else {
const isSetonlyAccessor = prop && prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) {
error(node, Diagnostics.Private_accessor_was_defined_without_a_getter);
}

View File

@@ -315,6 +315,10 @@
"category": "Error",
"code": 1110
},
"Private field '{0}' must be declared in an enclosing class.": {
"category": "Error",
"code": 1111
},
"A 'default' clause cannot appear more than once in a 'switch' statement.": {
"category": "Error",
"code": 1113

View File

@@ -1430,6 +1430,7 @@ export const plainJSErrors: Set<number> = new Set([
Diagnostics.Class_constructor_may_not_be_an_accessor.code,
Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code,
Diagnostics.await_using_statements_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code,
Diagnostics.Private_field_0_must_be_declared_in_an_enclosing_class.code,
// Type errors
Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value.code,
]);

View File

@@ -2838,6 +2838,12 @@ export function getContainingFunctionOrClassStaticBlock(node: Node): SignatureDe
return findAncestor(node.parent, isFunctionLikeOrClassStaticBlockDeclaration);
}
/** @internal */
export function getContainingClassExcludingClassDecorators(node: Node): ClassLikeDeclaration | undefined {
const decorator = findAncestor(node.parent, n => isClassLike(n) ? "quit" : isDecorator(n));
return decorator && isClassLike(decorator.parent) ? getContainingClass(decorator.parent) : getContainingClass(decorator ?? node);
}
/** @internal */
export type ThisContainer =
| FunctionDeclaration