Skip to content

Commit e1bf8b3

Browse files
Merge branch 'master' into release-3.8
2 parents 20c0e8b + 0aab63b commit e1bf8b3

File tree

63 files changed

+5513
-498
lines changed

Some content is hidden

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

63 files changed

+5513
-498
lines changed

scripts/configurePrerelease.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
/// <reference types="node"/>
2-
import { normalize } from "path";
2+
import { normalize, relative } from "path";
33
import assert = require("assert");
44
import { readFileSync, writeFileSync } from "fs";
5-
const args = process.argv.slice(2);
6-
75

86
/**
97
* A minimal description for a parsed package.json object.
@@ -15,9 +13,11 @@ interface PackageJson {
1513
}
1614

1715
function main(): void {
16+
const args = process.argv.slice(2);
1817
if (args.length < 3) {
18+
const thisProgramName = relative(process.cwd(), __filename);
1919
console.log("Usage:");
20-
console.log("\tnode configureNightly.js <dev|insiders> <package.json location> <file containing version>");
20+
console.log(`\tnode ${thisProgramName} <dev|insiders> <package.json location> <file containing version>`);
2121
return;
2222
}
2323

src/compiler/binder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1865,7 +1865,7 @@ namespace ts {
18651865
Accessor = 2
18661866
}
18671867

1868-
if (inStrictMode) {
1868+
if (inStrictMode && !isAssignmentTarget(node)) {
18691869
const seen = createUnderscoreEscapedMap<ElementKind>();
18701870

18711871
for (const prop of node.properties) {

src/compiler/checker.ts

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4501,6 +4501,8 @@ namespace ts {
45014501
}
45024502

45034503
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration {
4504+
const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType;
4505+
if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s
45044506
let typeParameters: TypeParameterDeclaration[] | undefined;
45054507
let typeArguments: TypeNode[] | undefined;
45064508
if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) {
@@ -4530,15 +4532,12 @@ namespace ts {
45304532
}
45314533
else {
45324534
const returnType = getReturnTypeOfSignature(signature);
4533-
returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context);
4534-
}
4535-
if (context.flags & NodeBuilderFlags.SuppressAnyReturnType) {
4536-
if (returnTypeNode && returnTypeNode.kind === SyntaxKind.AnyKeyword) {
4537-
returnTypeNode = undefined;
4535+
if (returnType && !(suppressAny && isTypeAny(returnType))) {
4536+
returnTypeNode = typeToTypeNodeHelper(returnType, context);
4537+
}
4538+
else if (!suppressAny) {
4539+
returnTypeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword);
45384540
}
4539-
}
4540-
else if (!returnTypeNode) {
4541-
returnTypeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword);
45424541
}
45434542
context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum
45444543
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments);
@@ -14410,7 +14409,8 @@ namespace ts {
1441014409
}
1441114410

1441214411
function isEmptyResolvedType(t: ResolvedType) {
14413-
return t.properties.length === 0 &&
14412+
return t !== anyFunctionType &&
14413+
t.properties.length === 0 &&
1441414414
t.callSignatures.length === 0 &&
1441514415
t.constructSignatures.length === 0 &&
1441614416
!t.stringIndexInfo &&
@@ -19045,7 +19045,7 @@ namespace ts {
1904519045
return getTypeOfSymbol(symbol);
1904619046
}
1904719047
if (diagnostic && symbol.valueDeclaration) {
19048-
addRelatedInfo(diagnostic, createDiagnosticForNode(symbol.valueDeclaration, Diagnostics._0_is_declared_here, symbolToString(symbol)));
19048+
addRelatedInfo(diagnostic, createDiagnosticForNode(symbol.valueDeclaration, Diagnostics._0_needs_an_explicit_type_annotation, symbolToString(symbol)));
1904919049
}
1905019050
}
1905119051
}
@@ -19777,13 +19777,22 @@ namespace ts {
1977719777
}
1977819778

1977919779
function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
19780-
// We are in a branch of obj?.foo === value or obj?.foo !== value. We remove undefined and null from
19781-
// the type of obj if (a) the operator is === and the type of value doesn't include undefined or (b) the
19782-
// operator is !== and the type of value is undefined.
19783-
const effectiveTrue = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken ? assumeTrue : !assumeTrue;
19784-
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
19785-
const valueNonNullish = !(getTypeFacts(getTypeOfExpression(value)) & (doubleEquals ? TypeFacts.EQUndefinedOrNull : TypeFacts.EQUndefined));
19786-
return effectiveTrue === valueNonNullish ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
19780+
// We are in a branch of obj?.foo === value (or any one of the other equality operators). We narrow obj as follows:
19781+
// When operator is === and type of value excludes undefined, null and undefined is removed from type of obj in true branch.
19782+
// When operator is !== and type of value excludes undefined, null and undefined is removed from type of obj in false branch.
19783+
// When operator is == and type of value excludes null and undefined, null and undefined is removed from type of obj in true branch.
19784+
// When operator is != and type of value excludes null and undefined, null and undefined is removed from type of obj in false branch.
19785+
// When operator is === and type of value is undefined, null and undefined is removed from type of obj in false branch.
19786+
// When operator is !== and type of value is undefined, null and undefined is removed from type of obj in true branch.
19787+
// When operator is == and type of value is null or undefined, null and undefined is removed from type of obj in false branch.
19788+
// When operator is != and type of value is null or undefined, null and undefined is removed from type of obj in true branch.
19789+
const equalsOperator = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
19790+
const nullableFlags = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? TypeFlags.Nullable : TypeFlags.Undefined;
19791+
const valueType = getTypeOfExpression(value);
19792+
// Note that we include any and unknown in the exclusion test because their domain includes null and undefined.
19793+
const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) ||
19794+
equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags)));
19795+
return removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
1978719796
}
1978819797

1978919798
function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
@@ -23234,10 +23243,6 @@ namespace ts {
2323423243
const assignmentKind = getAssignmentTargetKind(node);
2323523244
const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
2323623245
if (isPrivateIdentifier(right)) {
23237-
if (isOptionalChain(node)) {
23238-
grammarErrorOnNode(right, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
23239-
return anyType;
23240-
}
2324123246
checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldGet);
2324223247
}
2324323248
const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType;
@@ -32417,7 +32422,7 @@ namespace ts {
3241732422
}
3241832423
if (isInstancePropertyWithoutInitializer(member)) {
3241932424
const propName = (<PropertyDeclaration>member).name;
32420-
if (isIdentifier(propName)) {
32425+
if (isIdentifier(propName) || isPrivateIdentifier(propName)) {
3242132426
const type = getTypeOfSymbol(getSymbolOfNode(member));
3242232427
if (!(type.flags & TypeFlags.AnyOrUnknown || getFalsyFlags(type) & TypeFlags.Undefined)) {
3242332428
if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
@@ -32436,7 +32441,7 @@ namespace ts {
3243632441
!(<PropertyDeclaration>node).initializer;
3243732442
}
3243832443

32439-
function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) {
32444+
function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier, propType: Type, constructor: ConstructorDeclaration) {
3244032445
const reference = createPropertyAccess(createThis(), propName);
3244132446
reference.expression.parent = reference;
3244232447
reference.parent = constructor;
@@ -35972,30 +35977,32 @@ namespace ts {
3597235977
throw Debug.assertNever(prop, "Unexpected syntax kind:" + (<Node>prop).kind);
3597335978
}
3597435979

35975-
const effectiveName = getPropertyNameForPropertyNameNode(name);
35976-
if (effectiveName === undefined) {
35977-
continue;
35978-
}
35980+
if (!inDestructuring) {
35981+
const effectiveName = getPropertyNameForPropertyNameNode(name);
35982+
if (effectiveName === undefined) {
35983+
continue;
35984+
}
3597935985

35980-
const existingKind = seen.get(effectiveName);
35981-
if (!existingKind) {
35982-
seen.set(effectiveName, currentKind);
35983-
}
35984-
else {
35985-
if ((currentKind & DeclarationMeaning.PropertyAssignmentOrMethod) && (existingKind & DeclarationMeaning.PropertyAssignmentOrMethod)) {
35986-
grammarErrorOnNode(name, Diagnostics.Duplicate_identifier_0, getTextOfNode(name));
35986+
const existingKind = seen.get(effectiveName);
35987+
if (!existingKind) {
35988+
seen.set(effectiveName, currentKind);
3598735989
}
35988-
else if ((currentKind & DeclarationMeaning.GetOrSetAccessor) && (existingKind & DeclarationMeaning.GetOrSetAccessor)) {
35989-
if (existingKind !== DeclarationMeaning.GetOrSetAccessor && currentKind !== existingKind) {
35990-
seen.set(effectiveName, currentKind | existingKind);
35990+
else {
35991+
if ((currentKind & DeclarationMeaning.PropertyAssignmentOrMethod) && (existingKind & DeclarationMeaning.PropertyAssignmentOrMethod)) {
35992+
grammarErrorOnNode(name, Diagnostics.Duplicate_identifier_0, getTextOfNode(name));
35993+
}
35994+
else if ((currentKind & DeclarationMeaning.GetOrSetAccessor) && (existingKind & DeclarationMeaning.GetOrSetAccessor)) {
35995+
if (existingKind !== DeclarationMeaning.GetOrSetAccessor && currentKind !== existingKind) {
35996+
seen.set(effectiveName, currentKind | existingKind);
35997+
}
35998+
else {
35999+
return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
36000+
}
3599136001
}
3599236002
else {
35993-
return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
36003+
return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
3599436004
}
3599536005
}
35996-
else {
35997-
return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
35998-
}
3599936006
}
3600036007
}
3600136008
}

src/compiler/corePublic.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace ts {
2-
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
3-
// If changing the text in this section, be sure to test `configureNightly` too.
2+
// WARNING: The script `configurePrerelease.ts` uses a regexp to parse out these values.
3+
// If changing the text in this section, be sure to test `configurePrerelease` too.
44
export const versionMajorMinor = "3.8";
55
/** The version of the TypeScript compiler release */
66
export const version = `${versionMajorMinor}.0-beta`;

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,6 +2851,10 @@
28512851
"category": "Error",
28522852
"code": 2781
28532853
},
2854+
"'{0}' needs an explicit type annotation.": {
2855+
"category": "Message",
2856+
"code": 2782
2857+
},
28542858

28552859
"Import declaration '{0}' is using private name '{1}'.": {
28562860
"category": "Error",

src/compiler/emitter.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,13 @@ namespace ts {
9191
}
9292
else {
9393
const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile, options));
94+
const isJsonFile = isJsonSourceFile(sourceFile);
9495
// If json file emits to the same location skip writing it, if emitDeclarationOnly skip writing it
95-
const isJsonEmittedToSameLocation = isJsonSourceFile(sourceFile) &&
96+
const isJsonEmittedToSameLocation = isJsonFile &&
9697
comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo;
9798
const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath;
9899
const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
99-
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
100+
const declarationFilePath = (forceDtsPaths || (getEmitDeclarations(options) && !isJsonFile)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
100101
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
101102
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined };
102103
}
@@ -144,7 +145,7 @@ namespace ts {
144145

145146
/* @internal */
146147
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
147-
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts));
148+
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts) && !fileExtensionIs(inputFileName, Extension.Json));
148149
return changeExtension(
149150
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir),
150151
Extension.Dts
@@ -400,12 +401,13 @@ namespace ts {
400401
return;
401402
}
402403
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
404+
const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson);
403405
// Setup and perform the transformation to retrieve declarations from the input files
404-
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(sourceFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : sourceFiles;
406+
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
405407
if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) {
406408
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
407409
// Do that here when emitting only dts files
408-
sourceFiles.forEach(collectLinkedAliases);
410+
filesForEmit.forEach(collectLinkedAliases);
409411
}
410412
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
411413
if (length(declarationTransform.diagnostics)) {

src/compiler/parser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4680,10 +4680,12 @@ namespace ts {
46804680
const propertyAccess = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
46814681
propertyAccess.expression = expression;
46824682
propertyAccess.questionDotToken = questionDotToken;
4683-
// checker will error on private identifiers in optional chains, so don't have to catch them here
46844683
propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true);
46854684
if (questionDotToken || expression.flags & NodeFlags.OptionalChain) {
46864685
propertyAccess.flags |= NodeFlags.OptionalChain;
4686+
if (isPrivateIdentifier(propertyAccess.name)) {
4687+
parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
4688+
}
46874689
}
46884690
return finishNode(propertyAccess);
46894691
}

src/compiler/program.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ namespace ts {
853853
}
854854
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
855855
for (const fileName of parsedRef.commandLine.fileNames) {
856-
if (!fileExtensionIs(fileName, Extension.Dts)) {
856+
if (!fileExtensionIs(fileName, Extension.Dts) && !fileExtensionIs(fileName, Extension.Json)) {
857857
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
858858
}
859859
}
@@ -2500,8 +2500,8 @@ namespace ts {
25002500
}
25012501

25022502
function getProjectReferenceRedirectProject(fileName: string) {
2503-
// Ignore dts
2504-
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts)) {
2503+
// Ignore dts or any json files
2504+
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts) || fileExtensionIs(fileName, Extension.Json)) {
25052505
return undefined;
25062506
}
25072507

@@ -2562,7 +2562,7 @@ namespace ts {
25622562
}
25632563
else {
25642564
forEach(resolvedRef.commandLine.fileNames, fileName => {
2565-
if (!fileExtensionIs(fileName, Extension.Dts)) {
2565+
if (!fileExtensionIs(fileName, Extension.Dts) && !fileExtensionIs(fileName, Extension.Json)) {
25662566
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
25672567
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
25682568
}

0 commit comments

Comments
 (0)