Skip to content

Commit dbeb682

Browse files
committed
Merge branch 'master' into optimizeParser
# Conflicts: # src/compiler/parser.ts
2 parents 969f064 + 9c77195 commit dbeb682

File tree

149 files changed

+2568
-1498
lines changed

Some content is hidden

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

149 files changed

+2568
-1498
lines changed

.gitmodules

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[submodule "tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter"]
2+
path = tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter
3+
url = https://github.com/Microsoft/TypeScript-React-Starter
4+
[submodule "tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter"]
5+
path = tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter
6+
url = https://github.com/Microsoft/TypeScript-Node-Starter.git
7+
[submodule "tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter"]
8+
path = tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter
9+
url = https://github.com/Microsoft/TypeScript-React-Native-Starter.git
10+
[submodule "tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter"]
11+
path = tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter
12+
url = https://github.com/Microsoft/TypeScript-Vue-Starter.git
13+
[submodule "tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter"]
14+
path = tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter
15+
url = https://github.com/Microsoft/TypeScript-WeChat-Starter.git

src/compiler/checker.ts

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6454,7 +6454,10 @@ namespace ts {
64546454
}
64556455
for (let i = numTypeArguments; i < numTypeParameters; i++) {
64566456
const mapper = createTypeMapper(typeParameters, typeArguments);
6457-
const defaultType = getDefaultFromTypeParameter(typeParameters[i]);
6457+
let defaultType = getDefaultFromTypeParameter(typeParameters[i]);
6458+
if (defaultType && isTypeIdenticalTo(defaultType, emptyObjectType) && isJavaScriptImplicitAny) {
6459+
defaultType = anyType;
6460+
}
64586461
typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny);
64596462
}
64606463
}
@@ -13469,10 +13472,14 @@ namespace ts {
1346913472
}
1347013473

1347113474
function isInParameterInitializerBeforeContainingFunction(node: Node) {
13475+
let inBindingInitializer = false;
1347213476
while (node.parent && !isFunctionLike(node.parent)) {
13473-
if (node.parent.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node.parent).initializer === node) {
13477+
if (isParameter(node.parent) && (inBindingInitializer || node.parent.initializer === node)) {
1347413478
return true;
1347513479
}
13480+
if (isBindingElement(node.parent) && node.parent.initializer === node) {
13481+
inBindingInitializer = true;
13482+
}
1347613483

1347713484
node = node.parent;
1347813485
}
@@ -14197,7 +14204,7 @@ namespace ts {
1419714204
// type with those properties for which the binding pattern specifies a default value.
1419814205
if (contextualTypeHasPattern) {
1419914206
for (const prop of getPropertiesOfType(contextualType)) {
14200-
if (!propertiesTable.get(prop.escapedName)) {
14207+
if (!propertiesTable.get(prop.escapedName) && !(spread && getPropertyOfType(spread, prop.escapedName))) {
1420114208
if (!(prop.flags & SymbolFlags.Optional)) {
1420214209
error(prop.valueDeclaration || (<TransientSymbol>prop).bindingElement,
1420314210
Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value);
@@ -14378,19 +14385,7 @@ namespace ts {
1437814385
const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined;
1437914386
// We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement
1438014387
if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) {
14381-
const childrenTypes: Type[] = [];
14382-
for (const child of (parent as JsxElement).children) {
14383-
// In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that
14384-
// because then type of children property will have constituent of string type.
14385-
if (child.kind === SyntaxKind.JsxText) {
14386-
if (!child.containsOnlyWhiteSpaces) {
14387-
childrenTypes.push(stringType);
14388-
}
14389-
}
14390-
else {
14391-
childrenTypes.push(checkExpression(child, checkMode));
14392-
}
14393-
}
14388+
const childrenTypes: Type[] = checkJsxChildren(parent as JsxElement, checkMode);
1439414389

1439514390
if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
1439614391
// Error if there is a attribute named "children" explicitly specified and children element.
@@ -14430,6 +14425,23 @@ namespace ts {
1443014425
}
1443114426
}
1443214427

14428+
function checkJsxChildren(node: JsxElement | JsxFragment, checkMode?: CheckMode) {
14429+
const childrenTypes: Type[] = [];
14430+
for (const child of node.children) {
14431+
// In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that
14432+
// because then type of children property will have constituent of string type.
14433+
if (child.kind === SyntaxKind.JsxText) {
14434+
if (!child.containsOnlyWhiteSpaces) {
14435+
childrenTypes.push(stringType);
14436+
}
14437+
}
14438+
else {
14439+
childrenTypes.push(checkExpression(child, checkMode));
14440+
}
14441+
}
14442+
return childrenTypes;
14443+
}
14444+
1443314445
/**
1443414446
* Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element.
1443514447
* (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used)
@@ -14964,6 +14976,9 @@ namespace ts {
1496414976
if (isNodeOpeningLikeElement) {
1496514977
checkJsxAttributesAssignableToTagNameAttributes(<JsxOpeningLikeElement>node);
1496614978
}
14979+
else {
14980+
checkJsxChildren((node as JsxOpeningFragment).parent);
14981+
}
1496714982
}
1496814983

1496914984
/**
@@ -17164,7 +17179,7 @@ namespace ts {
1716417179
if (targetDeclarationKind !== SyntaxKind.Unknown) {
1716517180
const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind);
1716617181
// function/variable declaration should be ambient
17167-
return !!(decl.flags & NodeFlags.Ambient);
17182+
return !!decl && !!(decl.flags & NodeFlags.Ambient);
1716817183
}
1716917184
return false;
1717017185
}

src/compiler/factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3709,7 +3709,7 @@ namespace ts {
37093709
while (statementOffset < numStatements) {
37103710
const statement = source[statementOffset];
37113711
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
3712-
target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
3712+
append(target, visitor ? visitNode(statement, visitor, isStatement) : statement);
37133713
}
37143714
else {
37153715
break;

src/compiler/parser.ts

Lines changed: 12 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,7 +2274,7 @@ namespace ts {
22742274
isStartOfType(/*inStartOfParameter*/ true);
22752275
}
22762276

2277-
function parseParameter(requireEqualsToken?: boolean): ParameterDeclaration {
2277+
function parseParameter(): ParameterDeclaration {
22782278
const node = <ParameterDeclaration>createNodeWithJSDoc(SyntaxKind.Parameter);
22792279
if (token() === SyntaxKind.ThisKeyword) {
22802280
node.name = createIdentifier(/*isIdentifier*/ true);
@@ -2303,15 +2303,11 @@ namespace ts {
23032303

23042304
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
23052305
node.type = parseParameterType();
2306-
node.initializer = parseInitializer(/*inParameter*/ true, requireEqualsToken);
2306+
node.initializer = parseInitializer();
23072307

23082308
return finishNode(node);
23092309
}
23102310

2311-
function parseParameterWithEqualsToken(): ParameterDeclaration {
2312-
return parseParameter(/*requireEqualsToken*/ true);
2313-
}
2314-
23152311
function fillSignature(
23162312
returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken,
23172313
flags: SignatureFlags,
@@ -2364,10 +2360,7 @@ namespace ts {
23642360
setYieldContext(!!(flags & SignatureFlags.Yield));
23652361
setAwaitContext(!!(flags & SignatureFlags.Await));
23662362

2367-
const result = parseDelimitedList(ParsingContext.Parameters,
2368-
flags & SignatureFlags.JSDoc ? parseJSDocParameter :
2369-
flags & SignatureFlags.RequireCompleteParameterList ? parseParameterWithEqualsToken :
2370-
parseParameter);
2363+
const result = parseDelimitedList(ParsingContext.Parameters, flags & SignatureFlags.JSDoc ? parseJSDocParameter : parseParameter);
23712364

23722365
setYieldContext(savedYieldContext);
23732366
setAwaitContext(savedAwaitContext);
@@ -2491,7 +2484,7 @@ namespace ts {
24912484
// Although type literal properties cannot not have initializers, we attempt
24922485
// to parse an initializer so we can report in the checker that an interface
24932486
// property or type literal property cannot have an initializer.
2494-
(<PropertySignature>node).initializer = parseNonParameterInitializer();
2487+
(<PropertySignature>node).initializer = parseInitializer();
24952488
}
24962489
}
24972490
parseTypeMemberSemicolon();
@@ -3030,34 +3023,8 @@ namespace ts {
30303023
return expr;
30313024
}
30323025

3033-
function parseInitializer(inParameter: boolean, requireEqualsToken?: boolean): Expression {
3034-
if (token() !== SyntaxKind.EqualsToken) {
3035-
// It's not uncommon during typing for the user to miss writing the '=' token. Check if
3036-
// there is no newline after the last token and if we're on an expression. If so, parse
3037-
// this as an equals-value clause with a missing equals.
3038-
// NOTE: There are two places where we allow equals-value clauses. The first is in a
3039-
// variable declarator. The second is with a parameter. For variable declarators
3040-
// it's more likely that a { would be a allowed (as an object literal). While this
3041-
// is also allowed for parameters, the risk is that we consume the { as an object
3042-
// literal when it really will be for the block following the parameter.
3043-
if (scanner.hasPrecedingLineBreak() || (inParameter && token() === SyntaxKind.OpenBraceToken) || !isStartOfExpression()) {
3044-
// preceding line break, open brace in a parameter (likely a function body) or current token is not an expression -
3045-
// do not try to parse initializer
3046-
return undefined;
3047-
}
3048-
if (inParameter && requireEqualsToken) {
3049-
// = is required when speculatively parsing arrow function parameters,
3050-
// so return a fake initializer as a signal that the equals token was missing
3051-
const result = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics._0_expected, "=") as Identifier;
3052-
result.escapedText = "= not found" as __String;
3053-
return result;
3054-
}
3055-
}
3056-
3057-
// Initializer[In, Yield] :
3058-
// = AssignmentExpression[?In, ?Yield]
3059-
parseExpected(SyntaxKind.EqualsToken);
3060-
return parseAssignmentExpressionOrHigher();
3026+
function parseInitializer(): Expression | undefined {
3027+
return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher() : undefined;
30613028
}
30623029

30633030
function parseAssignmentExpressionOrHigher(): Expression {
@@ -5227,7 +5194,7 @@ namespace ts {
52275194
const node = <BindingElement>createNode(SyntaxKind.BindingElement);
52285195
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
52295196
node.name = parseIdentifierOrPattern();
5230-
node.initializer = parseInitializer(/*inParameter*/ false);
5197+
node.initializer = parseInitializer();
52315198
return finishNode(node);
52325199
}
52335200

@@ -5244,7 +5211,7 @@ namespace ts {
52445211
node.propertyName = propertyName;
52455212
node.name = parseIdentifierOrPattern();
52465213
}
5247-
node.initializer = parseInitializer(/*inParameter*/ false);
5214+
node.initializer = parseInitializer();
52485215
return finishNode(node);
52495216
}
52505217

@@ -5283,7 +5250,7 @@ namespace ts {
52835250
node.name = parseIdentifierOrPattern();
52845251
node.type = parseTypeAnnotation();
52855252
if (!isInOrOfKeyword(token())) {
5286-
node.initializer = parseNonParameterInitializer();
5253+
node.initializer = parseInitializer();
52875254
}
52885255
return finishNode(node);
52895256
}
@@ -5385,8 +5352,8 @@ namespace ts {
53855352
//
53865353
// The checker may still error in the static case to explicitly disallow the yield expression.
53875354
node.initializer = hasModifier(node, ModifierFlags.Static)
5388-
? allowInAnd(parseNonParameterInitializer)
5389-
: doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, parseNonParameterInitializer);
5355+
? allowInAnd(parseInitializer)
5356+
: doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, parseInitializer);
53905357

53915358
parseSemicolon();
53925359
return finishNode(node);
@@ -5404,10 +5371,6 @@ namespace ts {
54045371
return parsePropertyDeclaration(<PropertyDeclaration>node);
54055372
}
54065373

5407-
function parseNonParameterInitializer() {
5408-
return parseInitializer(/*inParameter*/ false);
5409-
}
5410-
54115374
function parseAccessorDeclaration(node: AccessorDeclaration, kind: AccessorDeclaration["kind"]): AccessorDeclaration {
54125375
node.kind = kind;
54135376
node.name = parsePropertyName();
@@ -5722,7 +5685,7 @@ namespace ts {
57225685
function parseEnumMember(): EnumMember {
57235686
const node = <EnumMember>createNodeWithJSDoc(SyntaxKind.EnumMember);
57245687
node.name = parsePropertyName();
5725-
node.initializer = allowInAnd(parseNonParameterInitializer);
5688+
node.initializer = allowInAnd(parseInitializer);
57265689
return finishNode(node);
57275690
}
57285691

src/compiler/sys.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ namespace ts {
125125
};
126126

127127
export let sys: System = (() => {
128+
const utf8ByteOrderMark = "\u00EF\u00BB\u00BF";
129+
128130
function getNodeSystem(): System {
129131
const _fs = require("fs");
130132
const _path = require("path");
@@ -348,7 +350,7 @@ namespace ts {
348350
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
349351
// If a BOM is required, emit one
350352
if (writeByteOrderMark) {
351-
data = "\uFEFF" + data;
353+
data = utf8ByteOrderMark + data;
352354
}
353355

354356
let fd: number;
@@ -549,7 +551,7 @@ namespace ts {
549551
writeFile(path: string, data: string, writeByteOrderMark?: boolean) {
550552
// If a BOM is required, emit one
551553
if (writeByteOrderMark) {
552-
data = "\uFEFF" + data;
554+
data = utf8ByteOrderMark + data;
553555
}
554556

555557
ChakraHost.writeFile(path, data);

src/harness/externalCompileRunner.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ interface ExecResult {
99
status: number;
1010
}
1111

12+
interface UserConfig {
13+
types: string[];
14+
}
15+
1216
abstract class ExternalCompileRunnerBase extends RunnerBase {
1317
abstract testDir: string;
1418
abstract report(result: ExecResult, cwd: string): string;
@@ -33,18 +37,34 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
3337
const cp = require("child_process");
3438

3539
it("should build successfully", () => {
36-
const cwd = path.join(__dirname, "../../", this.testDir, directoryName);
40+
let cwd = path.join(__dirname, "../../", this.testDir, directoryName);
3741
const timeout = 600000; // 600s = 10 minutes
42+
const stdio = isWorker ? "pipe" : "inherit";
43+
let types: string[];
44+
if (fs.existsSync(path.join(cwd, "test.json"))) {
45+
const update = cp.spawnSync("git", ["submodule", "update", "--remote"], { cwd, timeout, shell: true, stdio });
46+
if (update.status !== 0) throw new Error(`git submodule update for ${directoryName} failed!`);
47+
48+
const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig;
49+
ts.Debug.assert(!!config.types, "Bad format from test.json: Types field must be present.");
50+
types = config.types;
51+
52+
cwd = path.join(cwd, directoryName);
53+
}
3854
if (fs.existsSync(path.join(cwd, "package.json"))) {
3955
if (fs.existsSync(path.join(cwd, "package-lock.json"))) {
4056
fs.unlinkSync(path.join(cwd, "package-lock.json"));
4157
}
42-
const stdio = isWorker ? "pipe" : "inherit";
4358
const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio });
4459
if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`);
4560
}
61+
const args = [path.join(__dirname, "tsc.js")];
62+
if (types) {
63+
args.push("--types", types.join(","));
64+
}
65+
args.push("--noEmit");
4666
Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => {
47-
return this.report(cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }), cwd);
67+
return this.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd);
4868
});
4969
});
5070
});

src/lib/es5.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ declare function encodeURI(uri: string): string;
6262
*/
6363
declare function encodeURIComponent(uriComponent: string): string;
6464

65+
/**
66+
* Computes a new string in which certain characters have been replaced by a hexadecimal escape sequence.
67+
* @param string A string value
68+
*/
69+
declare function escape(string: string): string;
70+
71+
/**
72+
* Computes a new string in which hexadecimal escape sequences are replaced with the character that it represents.
73+
* @param string A string value
74+
*/
75+
declare function unescape(string: string): string;
76+
6577
interface PropertyDescriptor {
6678
configurable?: boolean;
6779
enumerable?: boolean;

0 commit comments

Comments
 (0)