Skip to content

Commit

Permalink
Merge branch 'master' into there-can-be-only-one
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Feb 15, 2020
2 parents 3d7348f + 7cc4a8d commit ea9dbe1
Show file tree
Hide file tree
Showing 166 changed files with 2,448 additions and 1,365 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ jobs:
npm install
npm update
npm test
- name: Validate the browser can import TypeScript
run: gulp test-browser-integration

7 changes: 6 additions & 1 deletion Gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ task("runtests").flags = {
" --shardId": "1-based ID of this shard (default: 1)",
};

const runTestsParallel = () => runConsoleTests("built/local/run.js", "min", /*runInParallel*/ true, /*watchMode*/ false);
const runTestsParallel = () => runConsoleTests("built/local/run.js", "min", /*runInParallel*/ cmdLineOptions.workers > 1, /*watchMode*/ false);
task("runtests-parallel", series(preBuild, preTest, runTestsParallel, postTest));
task("runtests-parallel").description = "Runs all the tests in parallel using the built run.js file.";
task("runtests-parallel").flags = {
Expand All @@ -472,6 +472,11 @@ task("runtests-parallel").flags = {
" --shardId": "1-based ID of this shard (default: 1)",
};


task("test-browser-integration", () => exec(process.execPath, ["scripts/browserIntegrationTest.js"]));
task("test-browser-integration").description = "Runs scripts/browserIntegrationTest.ts which tests that typescript.js loads in a browser";


task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true, waitForExit: false }));
task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable";

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"through2": "latest",
"travis-fold": "latest",
"typescript": "next",
"playwright": "latest",
"vinyl": "latest",
"vinyl-sourcemaps-apply": "latest",
"xml2js": "^0.4.19"
Expand Down
39 changes: 39 additions & 0 deletions scripts/browserIntegrationTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const playwright = require("playwright");
const chalk = require("chalk");
const { join } = require("path");
const { readFileSync } = require("fs");

// Turning this on will leave the Chromium browser open, giving you the
// chance to open up the web inspector.
const debugging = false;

(async () => {
for (const browserType of ["chromium", "firefox", "webkit"]) {
const browser = await playwright[browserType].launch({ headless: !debugging });
const context = await browser.newContext();
const page = await context.newPage();

const errorCaught = err => {
console.error(chalk.red("There was an error running built/typescript.js in " + browserType));
console.log(err.toString());
process.exitCode = 1;
};

page.on("error", errorCaught);
page.on("pageerror", errorCaught);
page.on("console", log => console[log._type](log._text));

await page.setContent(`
<html>
<script>${readFileSync(join("built", "local", "typescript.js"), "utf8")}</script>
</html>
`);

if (!debugging) {
await browser.close();
}
else {
console.log("Not closing the browser, you'll need to exit the process in your terminal manually");
}
}
})();
24 changes: 20 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9596,7 +9596,7 @@ namespace ts {
// When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
// mode, if the underlying property is optional we remove 'undefined' from the type.
prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) :
prop.type = strictNullChecks && isOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
if (modifiersProp) {
Expand Down Expand Up @@ -11343,6 +11343,11 @@ namespace ts {
function getTypeFromTypeReference(node: TypeReferenceType): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
// handle LS queries on the `const` in `x as const` by resolving to the type of `x`
if (isConstTypeReference(node) && isAssertionExpression(node.parent)) {
links.resolvedSymbol = unknownSymbol;
return links.resolvedType = checkExpressionCached(node.parent.expression);
}
let symbol: Symbol | undefined;
let type: Type | undefined;
const meaning = SymbolFlags.Type;
Expand Down Expand Up @@ -13696,7 +13701,7 @@ namespace ts {
const templateMapper = combineTypeMappers(mapper, createTypeMapper([getTypeParameterFromMappedType(type)], [key]));
const propType = instantiateType(getTemplateTypeFromMappedType(<MappedType>type.target || type), templateMapper);
const modifiers = getMappedTypeModifiers(type);
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) :
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
}
Expand Down Expand Up @@ -22608,6 +22613,7 @@ namespace ts {

function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) {
checkJsxOpeningLikeElementOrOpeningFragment(node);
resolveUntypedCall(node); // ensure type arguments and parameters are typechecked, even if there is an arity error
}

function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type {
Expand Down Expand Up @@ -24995,14 +25001,14 @@ namespace ts {
}

// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
function getCandidateForOverloadFailure(
node: CallLikeExpression,
candidates: Signature[],
args: readonly Expression[],
hasCandidatesOutArray: boolean,
): Signature {
Debug.assert(candidates.length > 0); // Else should not have called this.
checkNodeDeferred(node);
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
// Don't do this if there is a `candidatesOutArray`,
// because then we want the chosen best candidate to be one of the overloads, not a combination.
Expand Down Expand Up @@ -29299,7 +29305,7 @@ namespace ts {
}

function isPrivateWithinAmbient(node: Node): boolean {
return hasModifier(node, ModifierFlags.Private) && !!(node.flags & NodeFlags.Ambient);
return (hasModifier(node, ModifierFlags.Private) || isPrivateIdentifierPropertyDeclaration(node)) && !!(node.flags & NodeFlags.Ambient);
}

function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags {
Expand Down Expand Up @@ -33971,6 +33977,16 @@ namespace ts {
currentNode = node;
instantiationCount = 0;
switch (node.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.Decorator:
case SyntaxKind.JsxOpeningElement:
// These node kinds are deferred checked when overload resolution fails
// To save on work, we ensure the arguments are checked just once, in
// a deferred way
resolveUntypedCall(node as CallLikeExpression);
break;
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.MethodDeclaration:
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6576,18 +6576,19 @@ namespace ts {
return finishNode(node);
}

function parseNamespaceExport(): NamespaceExport {
const node = <NamespaceExport>createNode(SyntaxKind.NamespaceExport);
function parseNamespaceExport(pos: number): NamespaceExport {
const node = <NamespaceExport>createNode(SyntaxKind.NamespaceExport, pos);
node.name = parseIdentifier();
return finishNode(node);
}

function parseExportDeclaration(node: ExportDeclaration): ExportDeclaration {
node.kind = SyntaxKind.ExportDeclaration;
node.isTypeOnly = parseOptional(SyntaxKind.TypeKeyword);
const namespaceExportPos = scanner.getStartPos();
if (parseOptional(SyntaxKind.AsteriskToken)) {
if (parseOptional(SyntaxKind.AsKeyword)) {
node.exportClause = parseNamespaceExport();
node.exportClause = parseNamespaceExport(namespaceExportPos);
}
parseExpected(SyntaxKind.FromKeyword);
node.moduleSpecifier = parseModuleSpecifier();
Expand Down
12 changes: 8 additions & 4 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ namespace ts {
IsNamedExternalExport = 1 << 4,
IsDefaultExternalExport = 1 << 5,
IsDerivedClass = 1 << 6,
UseImmediatelyInvokedFunctionExpression = 1 << 7,

HasAnyDecorators = HasConstructorDecorators | HasMemberDecorators,
NeedsName = HasStaticInitializedProperties | HasMemberDecorators,
MayNeedImmediatelyInvokedFunctionExpression = HasAnyDecorators | HasStaticInitializedProperties,
UseImmediatelyInvokedFunctionExpression = HasAnyDecorators | HasStaticInitializedProperties,
IsExported = IsExportOfNamespace | IsDefaultExternalExport | IsNamedExternalExport,
}

Expand Down Expand Up @@ -590,7 +589,6 @@ namespace ts {
if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace;
else if (isDefaultExternalModuleExport(node)) facts |= ClassFacts.IsDefaultExternalExport;
else if (isNamedExternalModuleExport(node)) facts |= ClassFacts.IsNamedExternalExport;
if (languageVersion <= ScriptTarget.ES5 && (facts & ClassFacts.MayNeedImmediatelyInvokedFunctionExpression)) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression;
return facts;
}

Expand Down Expand Up @@ -661,6 +659,12 @@ namespace ts {
const iife = createImmediatelyInvokedArrowFunction(statements);
setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper);

// Class comment is already added by the ES2015 transform when targeting ES5 or below.
// Only add if targetting ES2015+ to prevent duplicates
if (languageVersion > ScriptTarget.ES5) {
addSyntheticLeadingComment(iife, SyntaxKind.MultiLineCommentTrivia, "* @class ");
}

const varStatement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
Expand All @@ -669,7 +673,7 @@ namespace ts {
/*type*/ undefined,
iife
)
])
], languageVersion > ScriptTarget.ES5 ? NodeFlags.Let : undefined)
);

setOriginalNode(varStatement, node);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3520,7 +3520,7 @@ namespace ts {
/* @internal */ createPromiseType(type: Type): Type;

/* @internal */ isTypeAssignableTo(source: Type, target: Type): boolean;
/* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
/* @internal */ createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
/* @internal */ createSignature(
declaration: SignatureDeclaration,
typeParameters: TypeParameter[] | undefined,
Expand Down
29 changes: 27 additions & 2 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4225,6 +4225,9 @@ namespace ts {
}

export function getModifierFlags(node: Node): ModifierFlags {
if (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken) {
return ModifierFlags.None;
}
if (node.modifierFlagsCache & ModifierFlags.HasComputedFlags) {
return node.modifierFlagsCache & ~ModifierFlags.HasComputedFlags;
}
Expand Down Expand Up @@ -5072,6 +5075,28 @@ namespace ts {
this.original = undefined;
}

function Token(this: Node, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;
this.end = end;
this.kind = kind;
this.id = 0;
this.flags = NodeFlags.None;
this.transformFlags = TransformFlags.None;
this.parent = undefined!;
}

function Identifier(this: Node, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;
this.end = end;
this.kind = kind;
this.id = 0;
this.flags = NodeFlags.None;
this.transformFlags = TransformFlags.None;
this.parent = undefined!;
this.original = undefined;
this.flowNode = undefined;
}

function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) {
this.fileName = fileName;
this.text = text;
Expand All @@ -5081,8 +5106,8 @@ namespace ts {
// eslint-disable-next-line prefer-const
export let objectAllocator: ObjectAllocator = {
getNodeConstructor: () => <any>Node,
getTokenConstructor: () => <any>Node,
getIdentifierConstructor: () => <any>Node,
getTokenConstructor: () => <any>Token,
getIdentifierConstructor: () => <any>Identifier,
getPrivateIdentifierConstructor: () => <any>Node,
getSourceFileConstructor: () => <any>Node,
getSymbolConstructor: () => <any>Symbol,
Expand Down
31 changes: 31 additions & 0 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,37 @@ namespace FourSlash {
}
}

public baselineRename(marker: string, options: FourSlashInterface.RenameOptions) {
const position = this.getMarkerByName(marker).position;
const locations = this.languageService.findRenameLocations(
this.activeFile.fileName,
position,
options.findInStrings ?? false,
options.findInComments ?? false,
options.providePrefixAndSuffixTextForRename);

if (!locations) {
this.raiseError(`baselineRename failed. Could not rename at the provided position.`);
}

const renamesByFile = ts.group(locations, l => l.fileName);
const baselineContent = renamesByFile.map(renames => {
const { fileName } = renames[0];
const sortedRenames = ts.sort(renames, (a, b) => b.textSpan.start - a.textSpan.start);
let baselineFileContent = this.getFileContent(fileName);
for (const { textSpan } of sortedRenames) {
const isOriginalSpan = fileName === this.activeFile.fileName && ts.textSpanIntersectsWithPosition(textSpan, position);
baselineFileContent =
baselineFileContent.slice(0, textSpan.start) +
(isOriginalSpan ? "[|RENAME|]" : "RENAME") +
baselineFileContent.slice(textSpan.start + textSpan.length);
}
return `/*====== ${fileName} ======*/\n\n${baselineFileContent}`;
}).join("\n\n") + "\n";

Harness.Baseline.runBaseline(this.getBaselineFileNameForContainingTestFile(), baselineContent);
}

public verifyQuickInfoExists(negative: boolean) {
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (negative) {
Expand Down
9 changes: 9 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,10 @@ namespace FourSlashInterface {
this.state.verifyRenameLocations(startRanges, options);
}

public baselineRename(marker: string, options: RenameOptions) {
this.state.baselineRename(marker, options);
}

public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: FourSlash.TextSpan,
displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[]) {
this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags);
Expand Down Expand Up @@ -1623,4 +1627,9 @@ namespace FourSlashInterface {
template: string
};
export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string };
export interface RenameOptions {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
};
}
4 changes: 2 additions & 2 deletions src/services/codefixes/inferFromUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ namespace ts.codefix {
const callSignatures: Signature[] = usage.calls ? [getSignatureFromCalls(usage.calls)] : [];
const constructSignatures: Signature[] = usage.constructs ? [getSignatureFromCalls(usage.constructs)] : [];
const stringIndexInfo = usage.stringIndex && checker.createIndexInfo(combineFromUsage(usage.stringIndex), /*isReadonly*/ false);
return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined); // TODO: GH#18217
return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined);
}

function inferNamedTypesFromProperties(usage: Usage): Type[] {
Expand Down Expand Up @@ -1089,7 +1089,7 @@ namespace ts.codefix {
}

function getFunctionFromCalls(calls: CallUsage[]) {
return checker.createAnonymousType(undefined!, createSymbolTable(), [getSignatureFromCalls(calls)], emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
return checker.createAnonymousType(/*symbol*/ undefined, createSymbolTable(), [getSignatureFromCalls(calls)], emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
}

function getSignatureFromCalls(calls: CallUsage[]): Signature {
Expand Down
10 changes: 6 additions & 4 deletions src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1927,10 +1927,12 @@ namespace ts.FindAllReferences {
}

const exportSpecifier = getDeclarationOfKind<ExportSpecifier>(symbol, SyntaxKind.ExportSpecifier);
const localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
if (localSymbol) {
const res = cbSymbol(localSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.Node);
if (res) return res;
if (!isForRenamePopulateSearchSymbolSet || exportSpecifier && !exportSpecifier.propertyName) {
const localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
if (localSymbol) {
const res = cbSymbol(localSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.Node);
if (res) return res;
}
}

// symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
Expand Down
Loading

0 comments on commit ea9dbe1

Please sign in to comment.