Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,17 @@ namespace ts {
return keys;
}

export function getAllKeys(obj: object): string[] {
const result: string[] = [];
do {
const names = Object.getOwnPropertyNames(obj);
for (const name of names) {
pushIfUnique(result, name);
}
} while (obj = Object.getPrototypeOf(obj));
return result;
}

export function getOwnValues<T>(sparseArray: T[]): T[] {
const values: T[] = [];
for (const key in sparseArray) {
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,10 @@ namespace ts {
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;

const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
// We set `structuralIsReused` to `undefined` because `tryReuseStructureFromOldProgram` calls `tryReuseStructureFromOldProgram` which checks
// `structuralIsReused`, which would be a TDZ violation if it was not set in advance to `undefined`.
let structuralIsReused: StructureIsReused | undefined;
structuralIsReused = tryReuseStructureFromOldProgram();
if (structuralIsReused !== StructureIsReused.Completely) {
processingDefaultLibFiles = [];
processingOtherFiles = [];
Expand Down
18 changes: 11 additions & 7 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ namespace ts {
let currentSourceFile: SourceFile;
let refs: Map<SourceFile>;
let libs: Map<boolean>;
let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
const resolver = context.getEmitResolver();
const options = context.getCompilerOptions();
const newLine = getNewLineCharacter(options);
Expand Down Expand Up @@ -279,7 +280,7 @@ namespace ts {
const statements = visitNodes(node.statements, visitDeclarationStatements);
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
refs.forEach(referenceVisitor);
const emittedImports = filter(combinedStatements, isAnyImportSyntax);
emittedImports = filter(combinedStatements, isAnyImportSyntax);
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
}
Expand Down Expand Up @@ -736,6 +737,12 @@ namespace ts {
}
const oldDiag = getSymbolAccessibilityDiagnostic;

// Setup diagnostic-related flags before first potential `cleanup` call, otherwise
// We'd see a TDZ violation at runtime
const canProduceDiagnostic = canProduceDiagnostics(input);
const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);

// Emit methods which are private as properties with no type information
if (isMethodDeclaration(input) || isMethodSignature(input)) {
if (hasModifier(input, ModifierFlags.Private)) {
Expand All @@ -744,17 +751,14 @@ namespace ts {
}
}

const canProdiceDiagnostic = canProduceDiagnostics(input);
if (canProdiceDiagnostic && !suppressNewDiagnosticContexts) {
if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
}

if (isTypeQueryNode(input)) {
checkEntityNameVisibility(input.exprName, enclosingDeclaration);
}

const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);
if (shouldEnterSuppressNewDiagnosticsContextContext) {
// We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do.
suppressNewDiagnosticContexts = true;
Expand Down Expand Up @@ -909,13 +913,13 @@ namespace ts {
return cleanup(visitEachChild(input, visitDeclarationSubtree, context));

function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
if (returnValue && canProdiceDiagnostic && hasDynamicName(input as Declaration)) {
if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) {
checkName(input as DeclarationDiagnosticProducing);
}
if (isEnclosingDeclaration(input)) {
enclosingDeclaration = previousEnclosingDeclaration;
}
if (canProdiceDiagnostic && !suppressNewDiagnosticContexts) {
if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
getSymbolAccessibilityDiagnostic = oldDiag;
}
if (shouldEnterSuppressNewDiagnosticsContextContext) {
Expand Down
3 changes: 2 additions & 1 deletion src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ namespace FourSlash {
"getDocumentHighlights",
];
const proxy = {} as ts.LanguageService;
for (const k in ls) {
const keys = ts.getAllKeys(ls);
for (const k of keys) {
const key = k as keyof typeof ls;
if (cacheableMembers.indexOf(key) === -1) {
proxy[key] = (...args: any[]) => (ls[key] as Function)(...args);
Expand Down