Skip to content

Commit 6a7a8c7

Browse files
author
Noj
committed
Merge branch 'master' of github.com:Microsoft/TypeScript into nojvek-jsx-fragment-factory
2 parents 4eaec97 + 4bda7ce commit 6a7a8c7

File tree

930 files changed

+87925
-26625
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

930 files changed

+87925
-26625
lines changed

.github/ISSUE_TEMPLATE/Bug_report.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ assignees: ''
77

88
---
99

10-
<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨
10+
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
1111
1212
Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Even if you think you've found a *bug*, please read the FAQ first, especially the Common "Bugs" That Aren't Bugs section!
1313

.gitmodules

Whitespace-only changes.

scripts/request-pr-review.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ main().catch(console.error);
4242

4343
async function main() {
4444
const gh = new Octokit({ auth: options.token });
45-
const response = await gh.pulls.createReviewRequest({
45+
const response = await gh.pulls.requestReviewers({
4646
owner: options.owner,
4747
repo: options.repo,
4848
pull_number,

src/compiler/binder.ts

+30-7
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,9 @@ namespace ts {
905905
function isNarrowingBinaryExpression(expr: BinaryExpression) {
906906
switch (expr.operatorToken.kind) {
907907
case SyntaxKind.EqualsToken:
908+
case SyntaxKind.BarBarEqualsToken:
909+
case SyntaxKind.AmpersandAmpersandEqualsToken:
910+
case SyntaxKind.QuestionQuestionEqualsToken:
908911
return containsNarrowableReference(expr.left);
909912
case SyntaxKind.EqualsEqualsToken:
910913
case SyntaxKind.ExclamationEqualsToken:
@@ -1041,12 +1044,18 @@ namespace ts {
10411044
}
10421045
}
10431046

1047+
function isLogicalAssignmentExpression(node: Node) {
1048+
node = skipParentheses(node);
1049+
return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind);
1050+
}
1051+
10441052
function isTopLevelLogicalExpression(node: Node): boolean {
10451053
while (isParenthesizedExpression(node.parent) ||
10461054
isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken) {
10471055
node = node.parent;
10481056
}
10491057
return !isStatementCondition(node) &&
1058+
!isLogicalAssignmentExpression(node.parent) &&
10501059
!isLogicalExpression(node.parent) &&
10511060
!(isOptionalChain(node.parent) && node.parent.expression === node);
10521061
}
@@ -1063,7 +1072,7 @@ namespace ts {
10631072

10641073
function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) {
10651074
doWithConditionalBranches(bind, node, trueTarget, falseTarget);
1066-
if (!node || !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
1075+
if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
10671076
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
10681077
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
10691078
}
@@ -1404,17 +1413,27 @@ namespace ts {
14041413
}
14051414
}
14061415

1407-
function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
1416+
function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
14081417
const preRightLabel = createBranchLabel();
1409-
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
1418+
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) {
14101419
bindCondition(node.left, preRightLabel, falseTarget);
14111420
}
14121421
else {
14131422
bindCondition(node.left, trueTarget, preRightLabel);
14141423
}
14151424
currentFlow = finishFlowLabel(preRightLabel);
14161425
bind(node.operatorToken);
1417-
bindCondition(node.right, trueTarget, falseTarget);
1426+
1427+
if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) {
1428+
doWithConditionalBranches(bind, node.right, trueTarget, falseTarget);
1429+
bindAssignmentTargetFlow(node.left);
1430+
1431+
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
1432+
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
1433+
}
1434+
else {
1435+
bindCondition(node.right, trueTarget, falseTarget);
1436+
}
14181437
}
14191438

14201439
function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) {
@@ -1500,14 +1519,15 @@ namespace ts {
15001519
// TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
15011520
// we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
15021521
// For now, though, since the common cases are chained `+`, leaving it recursive is fine
1503-
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
1522+
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken ||
1523+
isLogicalOrCoalescingAssignmentOperator(operator)) {
15041524
if (isTopLevelLogicalExpression(node)) {
15051525
const postExpressionLabel = createBranchLabel();
1506-
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
1526+
bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);
15071527
currentFlow = finishFlowLabel(postExpressionLabel);
15081528
}
15091529
else {
1510-
bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!);
1530+
bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!);
15111531
}
15121532
completeNode();
15131533
}
@@ -3607,6 +3627,9 @@ namespace ts {
36073627
if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) {
36083628
transformFlags |= TransformFlags.AssertES2020;
36093629
}
3630+
else if (isLogicalOrCoalescingAssignmentOperator(operatorTokenKind)) {
3631+
transformFlags |= TransformFlags.AssertESNext;
3632+
}
36103633
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
36113634
// Destructuring object assignments with are ES2015 syntax
36123635
// and possibly ES2018 if they contain rest

src/compiler/builder.ts

+42-13
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ namespace ts {
148148
/**
149149
* true if build info is emitted
150150
*/
151-
emittedBuildInfo?: boolean;
151+
buildInfoEmitPending: boolean;
152152
/**
153153
* Already seen emitted files
154154
*/
@@ -173,7 +173,7 @@ namespace ts {
173173
const compilerOptions = newProgram.getCompilerOptions();
174174
state.compilerOptions = compilerOptions;
175175
// With --out or --outFile, any change affects all semantic diagnostics so no need to cache them
176-
if (!compilerOptions.outFile && !compilerOptions.out) {
176+
if (!outFile(compilerOptions)) {
177177
state.semanticDiagnosticsPerFile = createMap<readonly Diagnostic[]>();
178178
}
179179
state.changedFilesSet = createMap<true>();
@@ -197,7 +197,7 @@ namespace ts {
197197
if (changedFilesSet) {
198198
copyEntries(changedFilesSet, state.changedFilesSet);
199199
}
200-
if (!compilerOptions.outFile && !compilerOptions.out && oldState!.affectedFilesPendingEmit) {
200+
if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) {
201201
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
202202
state.affectedFilesPendingEmitKind = cloneMapOrUndefined(oldState!.affectedFilesPendingEmitKind);
203203
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
@@ -250,14 +250,14 @@ namespace ts {
250250
BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined)
251251
.forEach(file => state.changedFilesSet.set(file.resolvedPath, true));
252252
}
253-
else if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
253+
else if (oldCompilerOptions && !outFile(compilerOptions) && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
254254
// Add all files to affectedFilesPendingEmit since emit changed
255255
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
256256
Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size);
257257
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
258258
}
259259

260-
state.emittedBuildInfo = !state.changedFilesSet.size && !state.affectedFilesPendingEmit;
260+
state.buildInfoEmitPending = !!state.changedFilesSet.size;
261261
return state;
262262
}
263263

@@ -374,7 +374,7 @@ namespace ts {
374374
// so operations are performed directly on program, return program
375375
const program = Debug.checkDefined(state.program);
376376
const compilerOptions = program.getCompilerOptions();
377-
if (compilerOptions.outFile || compilerOptions.out) {
377+
if (outFile(compilerOptions)) {
378378
Debug.assert(!state.semanticDiagnosticsPerFile);
379379
return program;
380380
}
@@ -611,7 +611,7 @@ namespace ts {
611611
isBuildInfoEmit?: boolean
612612
) {
613613
if (isBuildInfoEmit) {
614-
state.emittedBuildInfo = true;
614+
state.buildInfoEmitPending = false;
615615
}
616616
else if (affected === state.program) {
617617
state.changedFilesSet.clear();
@@ -624,6 +624,7 @@ namespace ts {
624624
}
625625
if (isPendingEmit) {
626626
state.affectedFilesPendingEmitIndex!++;
627+
state.buildInfoEmitPending = true;
627628
}
628629
else {
629630
state.affectedFilesIndex!++;
@@ -688,19 +689,21 @@ namespace ts {
688689
}
689690

690691
export type ProgramBuildInfoDiagnostic = string | [string, readonly ReusableDiagnostic[]];
692+
export type ProgramBuilderInfoFilePendingEmit = [string, BuilderFileEmit];
691693
export interface ProgramBuildInfo {
692694
fileInfos: MapLike<BuilderState.FileInfo>;
693695
options: CompilerOptions;
694696
referencedMap?: MapLike<string[]>;
695697
exportedModulesMap?: MapLike<string[]>;
696698
semanticDiagnosticsPerFile?: ProgramBuildInfoDiagnostic[];
699+
affectedFilesPendingEmit?: ProgramBuilderInfoFilePendingEmit[];
697700
}
698701

699702
/**
700703
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
701704
*/
702705
function getProgramBuildInfo(state: Readonly<ReusableBuilderProgramState>, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
703-
if (state.compilerOptions.outFile || state.compilerOptions.out) return undefined;
706+
if (outFile(state.compilerOptions)) return undefined;
704707
const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory();
705708
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory));
706709
const fileInfos: MapLike<BuilderState.FileInfo> = {};
@@ -751,6 +754,17 @@ namespace ts {
751754
result.semanticDiagnosticsPerFile = semanticDiagnosticsPerFile;
752755
}
753756

757+
if (state.affectedFilesPendingEmit) {
758+
const affectedFilesPendingEmit: ProgramBuilderInfoFilePendingEmit[] = [];
759+
const seenFiles = createMap<true>();
760+
for (const path of state.affectedFilesPendingEmit.slice(state.affectedFilesPendingEmitIndex).sort(compareStringsCaseSensitive)) {
761+
if (addToSeen(seenFiles, path)) {
762+
affectedFilesPendingEmit.push([relativeToBuildInfo(path), state.affectedFilesPendingEmitKind!.get(path)!]);
763+
}
764+
}
765+
result.affectedFilesPendingEmit = affectedFilesPendingEmit;
766+
}
767+
754768
return result;
755769

756770
function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
@@ -916,13 +930,23 @@ namespace ts {
916930
else if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
917931
(builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile;
918932
(builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).emitNextAffectedFile = emitNextAffectedFile;
933+
builderProgram.emitBuildInfo = emitBuildInfo;
919934
}
920935
else {
921936
notImplemented();
922937
}
923938

924939
return builderProgram;
925940

941+
function emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult {
942+
if (state.buildInfoEmitPending) {
943+
const result = Debug.checkDefined(state.program).emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken);
944+
state.buildInfoEmitPending = false;
945+
return result;
946+
}
947+
return emitSkippedWithNoDiagnostics;
948+
}
949+
926950
/**
927951
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
928952
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
@@ -933,10 +957,10 @@ namespace ts {
933957
let emitKind = BuilderFileEmit.Full;
934958
let isPendingEmitFile = false;
935959
if (!affected) {
936-
if (!state.compilerOptions.out && !state.compilerOptions.outFile) {
960+
if (!outFile(state.compilerOptions)) {
937961
const pendingAffectedFile = getNextAffectedFilePendingEmit(state);
938962
if (!pendingAffectedFile) {
939-
if (state.emittedBuildInfo) {
963+
if (!state.buildInfoEmitPending) {
940964
return undefined;
941965
}
942966

@@ -993,7 +1017,7 @@ namespace ts {
9931017
function emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
9941018
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
9951019
assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile);
996-
const result = handleNoEmitOptions(builderProgram, targetSourceFile, cancellationToken);
1020+
const result = handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken);
9971021
if (result) return result;
9981022
if (!targetSourceFile) {
9991023
// Emit and report any errors we ran into.
@@ -1071,7 +1095,7 @@ namespace ts {
10711095
function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
10721096
assertSourceFileOkWithoutNextAffectedCall(state, sourceFile);
10731097
const compilerOptions = Debug.checkDefined(state.program).getCompilerOptions();
1074-
if (compilerOptions.outFile || compilerOptions.out) {
1098+
if (outFile(compilerOptions)) {
10751099
Debug.assert(!state.semanticDiagnosticsPerFile);
10761100
// We dont need to cache the diagnostics just return them from program
10771101
return Debug.checkDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken);
@@ -1142,7 +1166,10 @@ namespace ts {
11421166
referencedMap: getMapOfReferencedSet(program.referencedMap, toPath),
11431167
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap, toPath),
11441168
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toPath(isString(value) ? value : value[0]), value => isString(value) ? emptyArray : value[1]),
1145-
hasReusableDiagnostic: true
1169+
hasReusableDiagnostic: true,
1170+
affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toPath(value[0])),
1171+
affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toPath(value[0]), value => value[1]),
1172+
affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0,
11461173
};
11471174
return {
11481175
getState: () => state,
@@ -1165,6 +1192,7 @@ namespace ts {
11651192
getCurrentDirectory: notImplemented,
11661193
emitNextAffectedFile: notImplemented,
11671194
getSemanticDiagnosticsOfNextAffectedFile: notImplemented,
1195+
emitBuildInfo: notImplemented,
11681196
close: noop,
11691197
};
11701198

@@ -1195,6 +1223,7 @@ namespace ts {
11951223
getDeclarationDiagnostics: (sourceFile, cancellationToken) => getProgram().getDeclarationDiagnostics(sourceFile, cancellationToken),
11961224
getSemanticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSemanticDiagnostics(sourceFile, cancellationToken),
11971225
emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers),
1226+
emitBuildInfo: (writeFile, cancellationToken) => getProgram().emitBuildInfo(writeFile, cancellationToken),
11981227
getAllDependencies: notImplemented,
11991228
getCurrentDirectory: () => getProgram().getCurrentDirectory(),
12001229
close: noop,

src/compiler/builderPublic.ts

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ namespace ts {
9999
* in that order would be used to write the files
100100
*/
101101
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
102+
/*@internal*/
103+
emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
102104
/**
103105
* Get the current directory of the program
104106
*/

src/compiler/builderState.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ namespace ts {
403403
export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): readonly string[] {
404404
const compilerOptions = programOfThisState.getCompilerOptions();
405405
// With --out or --outFile all outputs go into single file, all files depend on each other
406-
if (compilerOptions.outFile || compilerOptions.out) {
406+
if (outFile(compilerOptions)) {
407407
return getAllFileNames(state, programOfThisState);
408408
}
409409

@@ -519,7 +519,7 @@ namespace ts {
519519
const compilerOptions = programOfThisState.getCompilerOptions();
520520
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
521521
// so returning the file itself is good enough.
522-
if (compilerOptions && (compilerOptions.out || compilerOptions.outFile)) {
522+
if (compilerOptions && outFile(compilerOptions)) {
523523
return [sourceFileWithUpdatedShape];
524524
}
525525
return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape);
@@ -534,7 +534,7 @@ namespace ts {
534534
}
535535

536536
const compilerOptions = programOfThisState.getCompilerOptions();
537-
if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) {
537+
if (compilerOptions && (compilerOptions.isolatedModules || outFile(compilerOptions))) {
538538
return [sourceFileWithUpdatedShape];
539539
}
540540

0 commit comments

Comments
 (0)