-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: Declaration EmitThe issue relates to the emission of d.ts filesThe issue relates to the emission of d.ts filesFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
π Search Terms
declaration syntax invalid comment docstring
π Version & Regression Information
- Bisected this to 2b4e7e3 cc @dragomirtitian @weswigham
β― Playground Link
π» Code
// @composite: true
// @strict: true
// @declaration: true
// @showEmit
// @showEmittedFile: a.d.ts
// @filename: a.ts
import { boxedBox } from "./boxedBox";
export const _ = boxedBox;
// At index 83
/**
* wat
*/
// @filename: boxedBox.d.ts
export declare const boxedBox: import("./box").Box<{
boxed: import("./box").Box<number>;
}>; // ^This is index 83 in this file
// @filename: box.d.ts
export declare class Box<T> {
value: T;
constructor(value: T);
}
export declare function box<T>(value: T): Box<T>;
π Actual behavior
a.d.ts
is emitted as
export declare const _: import("./box").Box<{
boxed: import("./box").Box /**
* wat
*/<number>;
}>;
/**
* wat
*/
π Expected behavior
a.d.ts
is emitted as
export declare const _: import("./box").Box<{
boxed: import("./box").Box<number>;
}>;
/**
* wat
*/
Additional information about the issue
Given the extremely specific conditions under which this bug arises, somehow we hit the lottery by encountering it. Basically what I observed is that there is a point where this code is reached:
TypeScript/src/compiler/emitter.ts
Lines 5715 to 5728 in d8086f1
function emitCommentsAfterNode(node: Node, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { | |
const emitFlags = getEmitFlags(node); | |
const commentRange = getCommentRange(node); | |
// Emit trailing comments | |
if (emitFlags & EmitFlags.NoNestedComments) { | |
commentsDisabled = false; | |
} | |
emitTrailingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); | |
const typeNode = getTypeNode(node); | |
if (typeNode) { | |
emitTrailingCommentsOfNode(node, emitFlags, typeNode.pos, typeNode.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); | |
} | |
} |
in the following state:
node
refers toBox
, the one that's part ofimport("./box").Box
that comes just before the syntax error.getSourceFileOfNode(node)
evaluates to theb.d.ts
which is different fromcurrentSourceFile
, which isa.ts
- We use
node.pos
andnode.end
to figure out which comment range to get the comment from. But these indexes are relative tob.d.ts
, nota.ts
! So we attempt to look for a comment ina.ts
. Most of the time no comment would be found at these positions ina.ts
, but by sheer luck, there happens to be a comment ina.ts
starting right atnode.end
!
Imagine our surprise when my teammate's compilation started failing after touching a completely different part of a different file. They were just unlucky enough to have shifted a token into the exact right spot to surface the bug.
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: Declaration EmitThe issue relates to the emission of d.ts filesThe issue relates to the emission of d.ts filesFix AvailableA PR has been opened for this issueA PR has been opened for this issue