Repository navigation
Regression: 3.6 crashes if constructor parameters transformed #33295
Description
TypeScript Version: 3.6.2, and typescript@3.7.0-dev.20190906
Search Terms:
isParameterPropertyDeclaration
Code
Briefly, if a transformer touches the parameters of a constructor via e.g. ts.updateParameter, then the new node loses its parent pointer, which produces the following backtrace once TS runs after the transformer. (The below is 3.6.2 to make the line numbers easier for you to match up, but it also repros on the head version.)
TypeError: Cannot read property 'kind' of undefined
at isParameterPropertyDeclaration (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:13411:88)
at Object.filter (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:469:31)
at transformClassMembers (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70629:20)
at createClassDeclarationHeadWithDecorators (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70591:27)
at visitClassDeclaration (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70399:19)
at visitTypeScript (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70247:28)
at visitorWorker (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70041:24)
at sourceElementVisitorWorker (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70066:28)
at saveStateAndInvoke (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:69979:27)
at sourceElementVisitor (/home/evanm/projects/ts/36/node_modules/typescript/lib/typescript.js:70051:20)
Here's an example transformer that provokes this crash. Note that it doesn't actually change anything in the AST, it just runs ts.updateParameter with a copy of the input array (using the ... spread) to force ts.updateParameter to not early exit.
function transformer(context: ts.TransformationContext): ts.Transformer<ts.SourceFile> {
return (sf: ts.SourceFile) => {
return ts.visitEachChild(sf, visit, context);
};
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
console.log(ts.SyntaxKind[node.kind]);
switch (node.kind) {
case ts.SyntaxKind.Constructor:
const ctor = node as ts.ConstructorDeclaration;
const params = ctor.parameters.map(param => ts.updateParameter(
param,
[...param.decorators!], param.modifiers,
param.dotDotDotToken, param.name, param.questionToken,
param.type, param.initializer));
return ts.updateConstructor(ctor, ctor.decorators, ctor.modifiers,
params, ctor.body);
default:
return ts.visitEachChild(node, visit, context);
}
}
}
Expected behavior:
This code succeeds under TS3.5.
Actual behavior:
This crashes in 3.6.
Playground Link:
Related Issues:
Activity
evmar commentedon Sep 7, 2019
CC Ron Buckton (@rbuckton)
Handle parentless nodes in isParameterPropertyDeclaration
Handle parentless nodes in isParameterPropertyDeclaration
Handle parentless nodes in isParameterPropertyDeclaration
Move to a patched TypeScript version.
Upgrade to TypeScript 3.6.2
Upgrade to TypeScript 3.6.2
Handle parentless nodes in isParameterPropertyDeclaration
Handle parentless nodes in isParameterPropertyDeclaration
Upgrade to TypeScript 3.6.2
Upgrade to TypeScript 3.6.2