Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix compiler crash with object rest in catch binding
- Loading branch information
Showing
18 changed files
with
267 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/* @internal */ | ||
namespace ts { | ||
export namespace Debug { | ||
export function formatSymbol(symbol: Symbol): string { | ||
return `{ name: ${unescapeLeadingUnderscores(symbol.escapedName)}; flags: ${formatSymbolFlags(symbol.flags)}; declarations: ${map(symbol.declarations, node => formatSyntaxKind(node.kind))} }`; | ||
} | ||
|
||
/** | ||
* Formats an enum value as a string for debugging and debug assertions. | ||
*/ | ||
export function formatEnum(value = 0, enumObject: any, isFlags?: boolean) { | ||
const members = getEnumMembers(enumObject); | ||
if (value === 0) { | ||
return members.length > 0 && members[0][0] === 0 ? members[0][1] : "0"; | ||
} | ||
if (isFlags) { | ||
let result = ""; | ||
let remainingFlags = value; | ||
for (let i = members.length - 1; i >= 0 && remainingFlags !== 0; i--) { | ||
const [enumValue, enumName] = members[i]; | ||
if (enumValue !== 0 && (remainingFlags & enumValue) === enumValue) { | ||
remainingFlags &= ~enumValue; | ||
result = `${enumName}${result ? "|" : ""}${result}`; | ||
} | ||
} | ||
if (remainingFlags === 0) { | ||
return result; | ||
} | ||
} | ||
else { | ||
for (const [enumValue, enumName] of members) { | ||
if (enumValue === value) { | ||
return enumName; | ||
} | ||
} | ||
} | ||
return value.toString(); | ||
} | ||
|
||
function getEnumMembers(enumObject: any) { | ||
const result: [number, string][] = []; | ||
for (const name in enumObject) { | ||
const value = enumObject[name]; | ||
if (typeof value === "number") { | ||
result.push([value, name]); | ||
} | ||
} | ||
|
||
return stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); | ||
} | ||
|
||
export function formatSyntaxKind(kind: SyntaxKind | undefined): string { | ||
return formatEnum(kind, (<any>ts).SyntaxKind, /*isFlags*/ false); | ||
} | ||
|
||
export function formatNodeFlags(flags: NodeFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).NodeFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatModifierFlags(flags: ModifierFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).ModifierFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatTransformFlags(flags: TransformFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).TransformFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatEmitFlags(flags: EmitFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).EmitFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatSymbolFlags(flags: SymbolFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).SymbolFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatTypeFlags(flags: TypeFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).TypeFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function formatObjectFlags(flags: ObjectFlags | undefined): string { | ||
return formatEnum(flags, (<any>ts).ObjectFlags, /*isFlags*/ true); | ||
} | ||
|
||
export function failBadSyntaxKind(node: Node, message?: string): never { | ||
return fail( | ||
`${message || "Unexpected node."}\r\nNode ${formatSyntaxKind(node.kind)} was unexpected.`, | ||
failBadSyntaxKind); | ||
} | ||
|
||
export const assertEachNode = shouldAssert(AssertionLevel.Normal) | ||
? (nodes: Node[], test: (node: Node) => boolean, message?: string): void => assert( | ||
test === undefined || every(nodes, test), | ||
message || "Unexpected node.", | ||
() => `Node array did not pass test '${getFunctionName(test)}'.`, | ||
assertEachNode) | ||
: noop; | ||
|
||
export const assertNode = shouldAssert(AssertionLevel.Normal) | ||
? (node: Node | undefined, test: ((node: Node | undefined) => boolean) | undefined, message?: string): void => assert( | ||
test === undefined || test(node), | ||
message || "Unexpected node.", | ||
() => `Node ${formatSyntaxKind(node!.kind)} did not pass test '${getFunctionName(test!)}'.`, | ||
assertNode) | ||
: noop; | ||
|
||
export const assertOptionalNode = shouldAssert(AssertionLevel.Normal) | ||
? (node: Node, test: (node: Node) => boolean, message?: string): void => assert( | ||
test === undefined || node === undefined || test(node), | ||
message || "Unexpected node.", | ||
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`, | ||
assertOptionalNode) | ||
: noop; | ||
|
||
export const assertOptionalToken = shouldAssert(AssertionLevel.Normal) | ||
? (node: Node, kind: SyntaxKind, message?: string): void => assert( | ||
kind === undefined || node === undefined || node.kind === kind, | ||
message || "Unexpected node.", | ||
() => `Node ${formatSyntaxKind(node.kind)} was not a '${formatSyntaxKind(kind)}' token.`, | ||
assertOptionalToken) | ||
: noop; | ||
|
||
export const assertMissingNode = shouldAssert(AssertionLevel.Normal) | ||
? (node: Node, message?: string): void => assert( | ||
node === undefined, | ||
message || "Unexpected node.", | ||
() => `Node ${formatSyntaxKind(node.kind)} was unexpected'.`, | ||
assertMissingNode) | ||
: noop; | ||
|
||
let isDebugInfoEnabled = false; | ||
|
||
/** | ||
* Injects debug information into frequently used types. | ||
*/ | ||
export function enableDebugInfo() { | ||
if (isDebugInfoEnabled) return; | ||
|
||
// Add additional properties in debug mode to assist with debugging. | ||
Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, { | ||
__debugFlags: { get(this: Symbol) { return formatSymbolFlags(this.flags); } } | ||
}); | ||
|
||
Object.defineProperties(objectAllocator.getTypeConstructor().prototype, { | ||
__debugFlags: { get(this: Type) { return formatTypeFlags(this.flags); } }, | ||
__debugObjectFlags: { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((<ObjectType>this).objectFlags) : ""; } }, | ||
__debugTypeToString: { value(this: Type) { return this.checker.typeToString(this); } }, | ||
}); | ||
|
||
const nodeConstructors = [ | ||
objectAllocator.getNodeConstructor(), | ||
objectAllocator.getIdentifierConstructor(), | ||
objectAllocator.getTokenConstructor(), | ||
objectAllocator.getSourceFileConstructor() | ||
]; | ||
|
||
for (const ctor of nodeConstructors) { | ||
if (!ctor.prototype.hasOwnProperty("__debugKind")) { | ||
Object.defineProperties(ctor.prototype, { | ||
__debugKind: { get(this: Node) { return formatSyntaxKind(this.kind); } }, | ||
__debugNodeFlags: { get(this: Node) { return formatNodeFlags(this.flags); } }, | ||
__debugModifierFlags: { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } }, | ||
__debugTransformFlags: { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, | ||
__debugIsParseTreeNode: { get(this: Node) { return isParseTreeNode(this); } }, | ||
__debugEmitFlags: { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, | ||
__debugGetText: { | ||
value(this: Node, includeTrivia?: boolean) { | ||
if (nodeIsSynthesized(this)) return ""; | ||
const parseNode = getParseTreeNode(this); | ||
const sourceFile = parseNode && getSourceFileOfNode(parseNode); | ||
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
isDebugInfoEnabled = true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
"files": [ | ||
"core.ts", | ||
"performance.ts", | ||
"debug.ts", | ||
"semver.ts", | ||
|
||
"types.ts", | ||
|
Oops, something went wrong.