Skip to content

Commit

Permalink
Allow unknown/any in TS catch clause param
Browse files Browse the repository at this point in the history
  • Loading branch information
existentialism committed Jun 27, 2020
1 parent cfaa70d commit d284528
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile
@@ -1,6 +1,6 @@
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
TEST262_COMMIT = 058adfed86b1d4129996faaf50a85ea55379a66a
TYPESCRIPT_COMMIT = 5fc917be2e4dd64c8e9504d36615cd7fbfdd4cd3
TYPESCRIPT_COMMIT = ffa35d3272647fe48ddf173e1f0928f772c18630

FORCE_PUBLISH = "@babel/runtime,@babel/runtime-corejs2,@babel/runtime-corejs3,@babel/standalone"

Expand Down
15 changes: 11 additions & 4 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -636,6 +636,16 @@ export default class StatementParser extends ExpressionParser {
return this.finishNode(node, "ThrowStatement");
}

parseCatchClauseParam(): N.Identifier {
const param = this.parseBindingAtom();

const simple = param.type === "Identifier";
this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0);
this.checkLVal(param, BIND_LEXICAL, null, "catch clause");

return param;
}

parseTryStatement(node: N.TryStatement): N.TryStatement {
this.next();

Expand All @@ -647,10 +657,7 @@ export default class StatementParser extends ExpressionParser {
this.next();
if (this.match(tt.parenL)) {
this.expect(tt.parenL);
clause.param = this.parseBindingAtom();
const simple = clause.param.type === "Identifier";
this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0);
this.checkLVal(clause.param, BIND_LEXICAL, null, "catch clause");
clause.param = this.parseCatchClauseParam();
this.expect(tt.parenR);
} else {
clause.param = null;
Expand Down
24 changes: 24 additions & 0 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -86,6 +86,8 @@ const TSErrors = Object.freeze({
"Template literal types cannot have any substitution",
TypeAnnotationAfterAssign:
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",
UnexpectedCatchClauseParamType:
"Catch clause variable type annotation must be 'any' or 'unknown' if specified.",
UnexpectedReadonly:
"'readonly' type modifier is only permitted on array and tuple literal types.",
UnexpectedTypeAnnotation: "Did not expect a type annotation here.",
Expand Down Expand Up @@ -2667,4 +2669,26 @@ export default (superClass: Class<Parser>): Class<Parser> =>

return hasContextParam ? baseCount + 1 : baseCount;
}

parseCatchClauseParam(): N.Identifier {
const param = super.parseCatchClauseParam();
const type = this.tsTryParseTypeAnnotation();

if (type) {
switch (type.typeAnnotation.type) {
case "TSAnyKeyword":
case "TSUnknownKeyword":
param.type = type;
break;

default:
this.raise(
type.typeAnnotation.start,
TSErrors.UnexpectedCatchClauseParamType,
);
}
}

return param;
}
};
@@ -0,0 +1 @@
try {} catch (ex: string) {}
@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}},
"errors": [
"SyntaxError: Catch clause variable type annotation must be 'any' or 'unknown' if specified. (1:18)"
],
"program": {
"type": "Program",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}},
"block": {
"type": "BlockStatement",
"start":4,"end":6,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":6}},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start":7,"end":28,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":28}},
"param": {
"type": "Identifier",
"start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"ex"},
"name": "ex"
},
"body": {
"type": "BlockStatement",
"start":26,"end":28,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":28}},
"body": [],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
try {} catch (ex) {}
try {} catch (ex: unknown) {}
try {} catch (ex: any) {}
@@ -0,0 +1,105 @@
{
"type": "File",
"start":0,"end":76,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":25}},
"program": {
"type": "Program",
"start":0,"end":76,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":25}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"block": {
"type": "BlockStatement",
"start":4,"end":6,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":6}},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start":7,"end":20,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":20}},
"param": {
"type": "Identifier",
"start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"ex"},
"name": "ex"
},
"body": {
"type": "BlockStatement",
"start":18,"end":20,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":20}},
"body": [],
"directives": []
}
},
"finalizer": null
},
{
"type": "TryStatement",
"start":21,"end":50,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":29}},
"block": {
"type": "BlockStatement",
"start":25,"end":27,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":6}},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start":28,"end":50,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":29}},
"param": {
"type": {
"type": "TSTypeAnnotation",
"start":37,"end":46,"loc":{"start":{"line":2,"column":16},"end":{"line":2,"column":25}},
"typeAnnotation": {
"type": "TSUnknownKeyword",
"start":39,"end":46,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":25}}
}
},
"start":35,"end":37,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16},"identifierName":"ex"},
"name": "ex"
},
"body": {
"type": "BlockStatement",
"start":48,"end":50,"loc":{"start":{"line":2,"column":27},"end":{"line":2,"column":29}},
"body": [],
"directives": []
}
},
"finalizer": null
},
{
"type": "TryStatement",
"start":51,"end":76,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":25}},
"block": {
"type": "BlockStatement",
"start":55,"end":57,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":6}},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start":58,"end":76,"loc":{"start":{"line":3,"column":7},"end":{"line":3,"column":25}},
"param": {
"type": {
"type": "TSTypeAnnotation",
"start":67,"end":72,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":21}},
"typeAnnotation": {
"type": "TSAnyKeyword",
"start":69,"end":72,"loc":{"start":{"line":3,"column":18},"end":{"line":3,"column":21}}
}
},
"start":65,"end":67,"loc":{"start":{"line":3,"column":14},"end":{"line":3,"column":16},"identifierName":"ex"},
"name": "ex"
},
"body": {
"type": "BlockStatement",
"start":74,"end":76,"loc":{"start":{"line":3,"column":23},"end":{"line":3,"column":25}},
"body": [],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}
26 changes: 26 additions & 0 deletions scripts/parser-tests/typescript/allowlist.txt
Expand Up @@ -48,6 +48,8 @@ augmentedTypesFunction.ts
augmentedTypesInterface.ts
augmentedTypesVar.ts
bigintIndex.ts
binderBinaryExpressionStress.ts
binderBinaryExpressionStressJs.ts
cacheResolutions.ts
cachedModuleResolution1.ts
cachedModuleResolution2.ts
Expand All @@ -64,6 +66,7 @@ classCannotExtendVar.ts
classExpressionWithDecorator1.ts
classExtendsAcrossFiles.ts
classExtendsMultipleBaseClasses.ts
classIndexer5.ts
classOverloadForFunction.ts
collisionExportsRequireAndClass.ts
commonSourceDir5.ts
Expand All @@ -87,8 +90,10 @@ declarationEmitDestructuringOptionalBindingParametersInOverloads.ts
declarationEmitDestructuringParameterProperties.ts
declarationEmitDestructuringWithOptionalBindingParameters.ts
declarationEmitExpandoPropertyPrivateName.ts
declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts
declarationEmitExportAssignment.ts
declarationEmitExportDeclaration.ts
declarationEmitForModuleImportingModuleAugmentationRetainsImport.ts
declarationEmitForTypesWhichNeedImportTypes.ts
declarationEmitInterfaceWithNonEntityNameExpressionHeritage.ts
declarationEmitPrefersPathKindBasedOnBundling.ts
Expand All @@ -98,6 +103,7 @@ declarationImportTypeAliasInferredAndEmittable.ts
declarationMapsMultifile.ts
declarationMapsOutFile.ts
declarationsForInferredTypeFromOtherFile.ts
declarationsIndirectGeneratedAliasReference.ts
declareModifierOnImport1.ts
decoratorMetadataRestParameterWithImportedType.ts
decoratorMetadataWithImportDeclarationNameCollision.ts
Expand Down Expand Up @@ -195,6 +201,7 @@ exportSameNameFuncVar.ts
exportSpecifierAndExportedMemberDeclaration.ts
exportSpecifierAndLocalMemberDeclaration.ts
exportStarFromEmptyModule.ts
exportStarNotElided.ts
expressionsForbiddenInParameterInitializers.ts
extendingClassFromAliasAndUsageInIndexer.ts
extendsClauseAlreadySeen.ts
Expand All @@ -209,6 +216,8 @@ functionExpressionInWithBlock.ts
functionExpressionWithResolutionOfTypeNamedArguments01.ts
gettersAndSettersErrors.ts
giant.ts
globalThisDeclarationEmit.ts
globalThisDeclarationEmit2.ts
implementClausePrecedingExtends.ts
implementsClauseAlreadySeen.ts
importAndVariableDeclarationConflict1.ts
Expand All @@ -227,13 +236,24 @@ importHelpersNoHelpers.ts
importHelpersNoModule.ts
importHelpersOutFile.ts
importHelpersSystem.ts
importNonExportedMember10.ts
importNonExportedMember11.ts
importNonExportedMember4.ts
importNonExportedMember5.ts
importNonExportedMember6.ts
importNonExportedMember7.ts
importNonExportedMember8.ts
importNonExportedMember9.ts
importWithTrailingSlash.ts
importedEnumMemberMergedWithExportedAliasIsError.ts
importedModuleClassNameClash.ts
indexSignatureWithAccessibilityModifier.ts
indexSignatureWithInitializer1.ts
indexSignatureWithTrailingComma.ts
indexTypeCheck.ts
indexWithoutParamType.ts
indexerSignatureWithRestParam.ts
inferrenceInfiniteLoopWithSubtyping.ts
initializedParameterBeforeNonoptionalNotOptional.ts
interfaceMayNotBeExtendedWitACall.ts
interfaceWithImplements1.ts
Expand All @@ -242,12 +262,15 @@ isLiteral1.ts
isLiteral2.ts
isolatedModulesReExportType.ts
jsEnumTagOnObjectFrozen.ts
jsExportMemberMergedWithModuleAugmentation.ts
jsFileCompilationBindDuplicateIdentifier.ts
jsFileCompilationDuplicateFunctionImplementation.ts
jsFileCompilationDuplicateFunctionImplementationFileOrderReversed.ts
jsFileCompilationExternalPackageError.ts
jsFileImportPreservedWhenUsed.ts
jsNoImplicitAnyNoCascadingReferenceErrors.ts
jsdocAccessEnumType.ts
jsdocPropertyTagInvalid.ts
jsxAttributeWithoutExpressionReact.tsx
jsxIntrinsicElementsExtendsRecord.tsx
letAndVarRedeclaration.ts
Expand Down Expand Up @@ -335,6 +358,8 @@ preserveUnusedImports.ts
privacyCheckExternalModuleExportAssignmentOfGenericClass.ts
privacyTopLevelAmbientExternalModuleImportWithExport.ts
privacyTopLevelAmbientExternalModuleImportWithoutExport.ts
privateFieldAssignabilityFromUnknown.ts
privateNameWeakMapCollision.ts
reExportGlobalDeclaration1.ts
reExportUndefined1.ts
reExportUndefined2.ts
Expand Down Expand Up @@ -388,6 +413,7 @@ unusedImports3.ts
unusedImports4.ts
unusedImports5.ts
unusedInvalidTypeArguments.ts
usedImportNotElidedInJs.ts
varAndFunctionShareName.ts
varArgConstructorMemberParameter.ts
withStatement.ts
Expand Down
2 changes: 1 addition & 1 deletion scripts/parser-tests/typescript/error-codes.js
Expand Up @@ -40,7 +40,7 @@ module.exports = [
"TS1163", // A 'yield' expression is only allowed in a generator body.
"TS1184", // Modifiers cannot appear here.
"TS1191", // An import declaration cannot have modifiers.
"TS1196", // Catch clause variable cannot have a type annotation.
"TS1196", // Catch clause variable type annotation must be 'any' or 'unknown' if specified.
"TS1197", // Catch clause variable cannot have an initializer.
"TS1200", // Line terminator not permitted before arrow.
"TS1312", // '=' can only be used in an object literal property inside a destructuring assignment.
Expand Down

0 comments on commit d284528

Please sign in to comment.