mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 11:24:29 -05:00
Fix crash when this is typed as a generic T with no type constraints (#47991)
* fix this type validations for protected fields * update previous baselines * add new tests and baselines * ClassOrInterface can be returned as enclosingClass * inline function code and remove unnecessary blank lines * refactor enclosingClass checks
This commit is contained in:
@@ -20644,7 +20644,7 @@ namespace ts {
|
||||
|
||||
// Return true if the given class derives from each of the declaring classes of the protected
|
||||
// constituents of the given property.
|
||||
function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symbol, writing: boolean) {
|
||||
function isClassDerivedFromDeclaringClasses<T extends Type>(checkClass: T, prop: Symbol, writing: boolean) {
|
||||
return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ?
|
||||
!hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
|
||||
}
|
||||
@@ -28396,14 +28396,15 @@ namespace ts {
|
||||
// of the property as base classes
|
||||
let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => {
|
||||
const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as InterfaceType;
|
||||
return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing) ? enclosingClass : undefined;
|
||||
return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
|
||||
});
|
||||
// A protected property is accessible if the property is within the declaring class or classes derived from it
|
||||
if (!enclosingClass) {
|
||||
// allow PropertyAccessibility if context is in function with this parameter
|
||||
// static member access is disallow
|
||||
let thisParameter: ParameterDeclaration | undefined;
|
||||
if (flags & ModifierFlags.Static || !(thisParameter = getThisParameterFromNodeContext(location)) || !thisParameter.type) {
|
||||
// static member access is disallowed
|
||||
enclosingClass = getEnclosingClassFromThisParameter(location);
|
||||
enclosingClass = enclosingClass && isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
|
||||
if (flags & ModifierFlags.Static || !enclosingClass) {
|
||||
if (errorNode) {
|
||||
error(errorNode,
|
||||
Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses,
|
||||
@@ -28412,9 +28413,6 @@ namespace ts {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const thisType = getTypeFromTypeNode(thisParameter.type);
|
||||
enclosingClass = (((thisType.flags & TypeFlags.TypeParameter) ? getConstraintOfTypeParameter(thisType as TypeParameter) : thisType) as TypeReference).target;
|
||||
}
|
||||
// No further restrictions for static properties
|
||||
if (flags & ModifierFlags.Static) {
|
||||
@@ -28435,6 +28433,18 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined {
|
||||
const thisParameter = getThisParameterFromNodeContext(node);
|
||||
let thisType = thisParameter?.type && getTypeFromTypeNode(thisParameter.type);
|
||||
if (thisType && thisType.flags & TypeFlags.TypeParameter) {
|
||||
thisType = getConstraintOfTypeParameter(thisType as TypeParameter);
|
||||
}
|
||||
if (thisType && getObjectFlags(thisType) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
|
||||
return getTargetType(thisType) as InterfaceType;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getThisParameterFromNodeContext(node: Node) {
|
||||
const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false);
|
||||
return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined;
|
||||
|
||||
Reference in New Issue
Block a user