diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2211436c84..490c87f3b7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3844,21 +3844,40 @@ module ts { } // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order + // A nit here is that we reorder only signatures that belong to the same symbol, + // so order how inherited signatures are processed is still preserved. + // interface A { (x: string): void } + // interface B extends A { (x: 'foo'): string } + // var b: B; + // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function collectCandidates(node: CallExpression, signatures: Signature[]): Signature[]{ var result: Signature[] = []; var lastParent: Node; + var lastSymbol: Symbol; + var cutoffPos: number = 0; var pos: number; for (var i = 0; i < signatures.length; i++) { var signature = signatures[i]; if (isCandidateSignature(node, signature)) { - var parent = signature.declaration ? signature.declaration.parent : undefined; - if (lastParent && parent === lastParent) { - pos++; + var symbol = signature.declaration && getSymbolOfNode(signature.declaration); + var parent = signature.declaration && signature.declaration.parent; + if (!lastSymbol || symbol === lastSymbol) { + if (lastParent && parent === lastParent) { + pos++; + } + else { + lastParent = parent; + pos = cutoffPos; + } } else { + // current declaration belongs to a different symbol + // set cutoffPos so reorderings in the future won't change result set from 0 to cutoffPos + pos = cutoffPos = result.length; lastParent = parent; - pos = 0; } + lastSymbol = symbol; + for (var j = result.length; j > pos; j--) { result[j] = result[j - 1]; } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 25d304bda7..da08aec616 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -23,6 +23,10 @@ module ts { name: "diagnostics", type: "boolean", }, + { + name: "emitBOM", + type: "boolean" + }, { name: "help", shortName: "h", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6a6aa628c6..8c62617f7f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -157,8 +157,8 @@ module ts { return text.substring(skipTrivia(text, node.pos), node.end); } - function writeFile(filename: string, data: string) { - compilerHost.writeFile(filename, data, hostErrorMessage => { + function writeFile(filename: string, data: string, writeByteOrderMark: boolean) { + compilerHost.writeFile(filename, data, writeByteOrderMark, hostErrorMessage => { diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage)); }); } @@ -426,7 +426,7 @@ module ts { sourceMapNameIndices.pop(); }; - function writeJavaScriptAndSourceMapFile(emitOutput: string) { + function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) { // Write source map file encodeLastRecordedSourceMapSpan(); writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({ @@ -436,11 +436,11 @@ module ts { sources: sourceMapData.sourceMapSources, names: sourceMapData.sourceMapNames, mappings: sourceMapData.sourceMapMappings - })); + }), /*writeByteOrderMark*/ false); sourceMapDataList.push(sourceMapData); // Write sourcemap url to the js file and write the js file - writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL); + writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL, writeByteOrderMark); } // Initialize source map data @@ -513,8 +513,8 @@ module ts { scopeEmitEnd = recordScopeNameEnd; } - function writeJavaScriptFile(emitOutput: string) { - writeFile(jsFilePath, emitOutput); + function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) { + writeFile(jsFilePath, emitOutput, writeByteOrderMark); } function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) { @@ -1854,7 +1854,7 @@ module ts { } writeLine(); - writeEmittedFiles(writer.getText()); + writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM); } function emitDeclarations(jsFilePath: string, root?: SourceFile) { @@ -2448,7 +2448,7 @@ module ts { // TODO(shkamat): Should we not write any declaration file if any of them can produce error, // or should we just not write this file like we are doing now if (!reportedDeclarationError) { - writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText()); + writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText(), compilerOptions.emitBOM); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5ab0dad085..a7b2db64fb 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -417,7 +417,7 @@ module ts { nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext; } - export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, byteOrderMark: ByteOrderMark, version: number = 0, isOpen: boolean = false): SourceFile { + export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: number = 0, isOpen: boolean = false): SourceFile { var file: SourceFile; var scanner: Scanner; var token: SyntaxKind; @@ -3556,7 +3556,6 @@ module ts { file.nodeCount = nodeCount; file.identifierCount = identifierCount; file.version = version; - file.byteOrderMark = byteOrderMark; file.isOpen = isOpen; file.languageVersion = languageVersion; return file; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 564f22b9f0..e215979d2d 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -6,7 +6,7 @@ interface System { useCaseSensitiveFileNames: boolean; write(s: string): void; readFile(fileName: string, encoding?: string): string; - writeFile(fileName: string, data: string): void; + writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void; watchFile?(fileName: string, callback: (fileName: string) => void): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; @@ -75,15 +75,21 @@ var sys: System = (function () { } } - function writeFile(fileName: string, data: string): void { + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { fileStream.Open(); binaryStream.Open(); try { // Write characters in UTF-8 encoding fileStream.Charset = "utf-8"; fileStream.WriteText(data); - // Skip byte order mark and copy remaining data to binary stream - fileStream.Position = 3; + // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM). + // If not, start from position 0, as the BOM will be added automatically when charset==utf8. + if (writeByteOrderMark) { + fileStream.Position = 0; + } + else { + fileStream.Position = 3; + } fileStream.CopyTo(binaryStream); binaryStream.SaveToFile(fileName, 2 /*overwrite*/); } @@ -175,7 +181,12 @@ var sys: System = (function () { return buffer.toString("utf8"); } - function writeFile(fileName: string, data: string): void { + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { + // If a BOM is required, emit one + if (writeByteOrderMark) { + data = '\uFEFF' + data; + } + _fs.writeFileSync(fileName, data, "utf8"); } diff --git a/src/compiler/tc.ts b/src/compiler/tc.ts index 9c77211525..706fe3c596 100644 --- a/src/compiler/tc.ts +++ b/src/compiler/tc.ts @@ -142,10 +142,10 @@ module ts { } text = ""; } - return text !== undefined ? createSourceFile(filename, text, languageVersion, ByteOrderMark.None) : undefined; + return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined; } - function writeFile(fileName: string, data: string, onError?: (message: string) => void) { + function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { function directoryExists(directoryPath: string): boolean { if (hasProperty(existingDirectories, directoryPath)) { @@ -168,7 +168,7 @@ module ts { try { ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - sys.writeFile(fileName, data); + sys.writeFile(fileName, data, writeByteOrderMark); } catch (e) { if (onError) onError(e.message); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9fb8c9a419..2c9284052d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -525,7 +525,6 @@ module ts { nodeCount: number; identifierCount: number; symbolCount: number; - byteOrderMark: ByteOrderMark; isOpen: boolean; version: number; languageVersion: ScriptTarget; @@ -940,6 +939,7 @@ module ts { codepage?: number; declaration?: boolean; diagnostics?: boolean; + emitBOM?: boolean; help?: boolean; locale?: string; mapRoot?: string; @@ -1131,17 +1131,10 @@ module ts { getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile; getDefaultLibFilename(): string; getCancellationToken? (): CancellationToken; - writeFile(filename: string, data: string, onError?: (message: string) => void): void; + writeFile(filename: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void; getCurrentDirectory(): string; getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; } - - export enum ByteOrderMark { - None = 0, - Utf8 = 1, - Utf16BigEndian = 2, - Utf16LittleEndian = 3, - } } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index c4bd2f9719..e08981142e 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -118,6 +118,10 @@ class CompilerBaselineRunner extends RunnerBase { } }); + function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string { + return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : ""; + } + function getErrorBaseline(toBeCompiled: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], result: Harness.Compiler.CompilerResult @@ -282,6 +286,7 @@ class CompilerBaselineRunner extends RunnerBase { var jsCode = ''; for (var i = 0; i < result.files.length; i++) { jsCode += '//// [' + Harness.Path.getFileName(result.files[i].fileName) + ']\r\n'; + jsCode += getByteOrderMarkText(result.files[i]); jsCode += result.files[i].code; // Re-enable this if we want to do another comparison of old vs new compiler baselines // jsCode += SyntacticCleaner.clean(result.files[i].code); @@ -291,6 +296,7 @@ class CompilerBaselineRunner extends RunnerBase { jsCode += '\r\n\r\n'; for (var i = 0; i < result.files.length; i++) { jsCode += '//// [' + Harness.Path.getFileName(result.declFilesCode[i].fileName) + ']\r\n'; + jsCode += getByteOrderMarkText(result.declFilesCode[i]); jsCode += result.declFilesCode[i].code; } } @@ -320,6 +326,7 @@ class CompilerBaselineRunner extends RunnerBase { var sourceMapCode = ''; for (var i = 0; i < result.sourceMaps.length; i++) { sourceMapCode += '//// [' + Harness.Path.getFileName(result.sourceMaps[i].fileName) + ']\r\n'; + sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]); sourceMapCode += result.sourceMaps[i].code; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 25cc615c8e..6cba438e31 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1895,12 +1895,12 @@ module FourSlash { var result = ''; var fourslashFilename = 'fourslash.ts'; var tsFn = 'tests/cases/fourslash/' + fourslashFilename; - fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); - libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); + fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false); + libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3, /*version*/ 0, /*isOpen*/ false); var files: { [filename: string]: ts.SourceFile; } = {}; files[fourslashFilename] = fourslashSourceFile; - files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); + files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false); files['lib.d.ts'] = libdtsSourceFile; var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index a3e1256694..7abfbd4f19 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -534,7 +534,7 @@ module Harness { export var libText = IO.readFile(libFolder + "lib.d.ts"); export var libTextMinimal = IO.readFile('bin/lib.core.d.ts'); - export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string) => void): ts.CompilerHost { + export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string, writeByteOrderMark:boolean) => void): ts.CompilerHost { return { getCurrentDirectory: sys.getCurrentDirectory, getCancellationToken: (): any => undefined, @@ -544,7 +544,7 @@ module Harness { } else { var lib = 'lib.d.ts'; if (fn.substr(fn.length - lib.length) === lib) { - return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion, ts.ByteOrderMark.None); + return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion); } // Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC return null; @@ -712,6 +712,10 @@ module Harness { // Not supported yet break; + case 'emitbom': + options.emitBOM = !!setting.value; + break; + default: throw new Error('Unsupported compiler setting ' + setting.flag); } @@ -720,18 +724,15 @@ module Harness { var filemap: { [name: string]: ts.SourceFile; } = {}; var register = (file: { unitName: string; content: string; }) => { var filename = Path.switchToForwardSlashes(file.unitName); - filemap[filename] = ts.createSourceFile(filename, file.content, options.target, ts.ByteOrderMark.None); + filemap[filename] = ts.createSourceFile(filename, file.content, options.target); }; inputFiles.forEach(register); otherFiles.forEach(register); - var fileOutputs: { - fileName: string; - file: string; - }[] = []; + var fileOutputs: GeneratedFile[] = []; var programFiles = inputFiles.map(file => file.unitName); - var program = ts.createProgram(programFiles, options, createCompilerHost(filemap, (fn, contents) => fileOutputs.push({ fileName: fn, file: contents }))); + var program = ts.createProgram(programFiles, options, createCompilerHost(filemap, (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }))); var hadParseErrors = program.getDiagnostics().length > 0; @@ -810,6 +811,7 @@ module Harness { export interface GeneratedFile { fileName: string; code: string; + writeByteOrderMark: boolean; } function stringEndsWith(str: string, end: string) { @@ -837,19 +839,18 @@ module Harness { public sourceMapRecord: string; /** @param fileResults an array of strings for the fileName and an ITextWriter with its code */ - constructor(fileResults: { fileName: string; file: string; }[], errors: MinimalDiagnostic[], sourceMapRecordLines: string[]) { + constructor(fileResults: GeneratedFile[], errors: MinimalDiagnostic[], sourceMapRecordLines: string[]) { var lines: string[] = []; fileResults.forEach(emittedFile => { - var fileObj = { fileName: emittedFile.fileName, code: emittedFile.file }; if (isDTS(emittedFile.fileName)) { // .d.ts file, add to declFiles emit - this.declFilesCode.push(fileObj); + this.declFilesCode.push(emittedFile); } else if (isJS(emittedFile.fileName)) { // .js file, add to files - this.files.push(fileObj); + this.files.push(emittedFile); } else if (isJSMap(emittedFile.fileName)) { - this.sourceMaps.push(fileObj); + this.sourceMaps.push(emittedFile); } else { throw new Error('Unrecognized file extension for file ' + emittedFile.fileName); } @@ -896,7 +897,7 @@ module Harness { var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines // List of allowed metadata names - var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve", "newline", "newlines"]; + var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 400cae2abe..4ca56bb299 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -7,7 +7,7 @@ module Harness.LanguageService { public editRanges: { length: number; textChangeRange: TypeScript.TextChangeRange; }[] = []; public lineMap: TypeScript.LineMap = null; - constructor(public fileName: string, public content: string, public isOpen = true, public byteOrderMark: ts.ByteOrderMark = ts.ByteOrderMark.None) { + constructor(public fileName: string, public content: string, public isOpen = true) { this.setContent(content); } @@ -132,7 +132,6 @@ module Harness.LanguageService { getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));} getScriptVersion(fileName: string): number { return this.shimHost.getScriptVersion(fileName);} getScriptIsOpen(fileName: string): boolean { return this.shimHost.getScriptIsOpen(fileName); } - getScriptByteOrderMark(fileName: string): ts.ByteOrderMark { return this.shimHost.getScriptByteOrderMark(fileName);} getLocalizedDiagnosticMessages(): any { JSON.parse(this.shimHost.getLocalizedDiagnosticMessages());} getCancellationToken(): ts.CancellationToken { return this.shimHost.getCancellationToken(); } } @@ -145,10 +144,9 @@ module Harness.LanguageService { fileName: string, compilationSettings: ts.CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - byteOrderMark: ts.ByteOrderMark, version: number, isOpen: boolean): ts.SourceFile { - return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen); + return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); } public updateDocument( @@ -262,10 +260,6 @@ module Harness.LanguageService { return this.getScriptInfo(fileName).isOpen; } - public getScriptByteOrderMark(fileName: string): ts.ByteOrderMark { - return this.getScriptInfo(fileName).byteOrderMark; - } - public getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index e6ec6d6f9d..5ddcf57804 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -25,10 +25,8 @@ interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase { emittedFiles: string[]; // List of files that wre emitted by the compiler } -interface BatchCompileProjectTestCaseEmittedFile { +interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.GeneratedFile { emittedFileName: string; - code: string; - fileName: string; } interface BatchCompileProjectTestCaseResult { @@ -139,7 +137,7 @@ class ProjectRunner extends RunnerBase { function getSourceFile(filename: string, languageVersion: ts.ScriptTarget): ts.SourceFile { var sourceFile: ts.SourceFile = undefined; if (filename === 'lib.d.ts') { - sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion, ts.ByteOrderMark.None); + sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion); } else { assert.isTrue(!ts.filter(readInputFiles, sourceFile => sourceFile.filename == filename).length, "Compiler trying to read same file again: " + filename); @@ -154,7 +152,7 @@ class ProjectRunner extends RunnerBase { } if (text !== undefined) { - sourceFile = ts.createSourceFile(filename, text, languageVersion, ts.ByteOrderMark.None); + sourceFile = ts.createSourceFile(filename, text, languageVersion); } } @@ -164,7 +162,7 @@ class ProjectRunner extends RunnerBase { return sourceFile; } - function writeFile(filename: string, data: string) { + function writeFile(filename: string, data: string, writeByteOrderMark: boolean) { var diskFileName = ts.isRootedDiskPath(filename) ? filename : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(filename); @@ -207,9 +205,9 @@ class ProjectRunner extends RunnerBase { } } ensureDirectoryStructure(ts.getDirectoryPath(ts.normalizePath(outputFilePath))); - sys.writeFile(outputFilePath, data); + sys.writeFile(outputFilePath, data, writeByteOrderMark); - outputFiles.push({ emittedFileName: filename, code: data, fileName: diskRelativeName }); + outputFiles.push({ emittedFileName: filename, code: data, fileName: diskRelativeName, writeByteOrderMark: writeByteOrderMark }); } function getCurrentDirectory() { diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 98006cd6bc..576b06e343 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -107,7 +107,7 @@ module RWC { catch (e) { // Leave fileContents undefined; } - return ts.createSourceFile(fileName, fileContents, languageVersion, ts.ByteOrderMark.None); + return ts.createSourceFile(fileName, fileContents, languageVersion); }, getDefaultLibFilename: () => libPath, writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false), diff --git a/src/services/services.ts b/src/services/services.ts index aaac93c9ee..be05a48cee 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -320,7 +320,6 @@ module ts { public identifierCount: number; public symbolCount: number; public statements: NodeArray; - public byteOrderMark: ByteOrderMark; public version: number; public isOpen: boolean; public languageVersion: ScriptTarget; @@ -417,11 +416,11 @@ module ts { ? TypeScript.Parser.parse(this.filename, text, this.languageVersion, TypeScript.isDTSFile(this.filename)) : TypeScript.IncrementalParser.parse(oldSyntaxTree, textChangeRange, text); - return SourceFileObject.createSourceFileObject(this.languageVersion, this.filename, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree); + return SourceFileObject.createSourceFileObject(this.languageVersion, this.filename, scriptSnapshot, version, isOpen, newSyntaxTree); } - public static createSourceFileObject(languageVersion: ScriptTarget, filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, syntaxTree: TypeScript.SyntaxTree) { - var newSoruceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, byteOrderMark, version, isOpen); + public static createSourceFileObject(languageVersion: ScriptTarget, filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, syntaxTree: TypeScript.SyntaxTree) { + var newSoruceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen); newSoruceFile.scriptSnapshot = scriptSnapshot; newSoruceFile.syntaxTree = syntaxTree; return newSoruceFile; @@ -445,7 +444,6 @@ module ts { getScriptFileNames(): string[]; getScriptVersion(fileName: string): number; getScriptIsOpen(fileName: string): boolean; - getScriptByteOrderMark(fileName: string): ByteOrderMark; getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot; getLocalizedDiagnosticMessages(): any; getCancellationToken(): CancellationToken; @@ -694,7 +692,6 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, referencedFiles: string[]): SourceFile; @@ -824,7 +821,6 @@ module ts { filename: string; version: number; isOpen: boolean; - byteOrderMark: ByteOrderMark; sourceText?: TypeScript.IScriptSnapshot; } @@ -893,8 +889,7 @@ module ts { this.filenameToEntry[TypeScript.switchToForwardSlashes(filename)] = { filename: filename, version: host.getScriptVersion(filename), - isOpen: host.getScriptIsOpen(filename), - byteOrderMark: host.getScriptByteOrderMark(filename) + isOpen: host.getScriptIsOpen(filename) }; } @@ -941,10 +936,6 @@ module ts { return this.getEntry(filename).isOpen; } - public getByteOrderMark(filename: string): ByteOrderMark { - return this.getEntry(filename).byteOrderMark; - } - public getScriptSnapshot(filename: string): TypeScript.IScriptSnapshot { var file = this.getEntry(filename); if (!file.sourceText) { @@ -1143,14 +1134,13 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - byteOrderMark: ByteOrderMark, version: number, isOpen: boolean): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); var entry = lookUp(bucket, filename); if (!entry) { - var sourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen); + var sourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); bucket[filename] = entry = { sourceFile: sourceFile, @@ -1255,7 +1245,7 @@ module ts { getDefaultLibFilename: (): string => { throw Error("TOD:: getDefaultLibfilename"); }, - writeFile: (filename, data) => { + writeFile: (filename, data, writeByteOrderMark) => { throw Error("TODO: write file"); }, getCurrentDirectory: (): string => { @@ -1360,7 +1350,7 @@ module ts { sourceFile = documentRegistry.updateDocument(sourceFile, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange); } else { - sourceFile = documentRegistry.acquireDocument(filename, compilationSettings, scriptSnapshot, hostCache.getByteOrderMark(filename), version, isOpen, []); + sourceFile = documentRegistry.acquireDocument(filename, compilationSettings, scriptSnapshot, version, isOpen, []); } // Remeber the new sourceFile diff --git a/src/services/shims.ts b/src/services/shims.ts index f02b9b6208..891b9e1d91 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -50,7 +50,6 @@ module ts { getScriptFileNames(): string; getScriptVersion(fileName: string): number; getScriptIsOpen(fileName: string): boolean; - getScriptByteOrderMark(fileName: string): number; getScriptSnapshot(fileName: string): ScriptSnapshotShim; getLocalizedDiagnosticMessages(): string; getCancellationToken(): CancellationToken; @@ -170,6 +169,7 @@ module ts { useCaseSensitiveFileResolution?: boolean; gatherDiagnostics?: boolean; codepage?: number; + emitBOM?: boolean; } function languageVersionToScriptTarget(languageVersion: LanguageVersion): ScriptTarget { @@ -232,6 +232,7 @@ module ts { options.declaration = settings.generateDeclarationFiles; //options.useCaseSensitiveFileResolution = settings.useCaseSensitiveFileResolution; options.codepage = settings.codepage; + options.emitBOM = settings.emitBOM; return options; } @@ -252,6 +253,7 @@ module ts { settings.generateDeclarationFiles = options.declaration; // settings.useCaseSensitiveFileResolution = options.useCaseSensitiveFileResolution; settings.codepage = options.codepage; + settings.emitBOM = options.emitBOM; return settings; } @@ -355,10 +357,6 @@ module ts { return this.shimHost.getScriptIsOpen(fileName); } - public getScriptByteOrderMark(fileName: string): ByteOrderMark { - return this.shimHost.getScriptByteOrderMark(fileName); - } - public getLocalizedDiagnosticMessages(): any { var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages(); if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") { diff --git a/tests/baselines/reference/emitBOM.js b/tests/baselines/reference/emitBOM.js new file mode 100644 index 0000000000..c1616f6386 --- /dev/null +++ b/tests/baselines/reference/emitBOM.js @@ -0,0 +1,11 @@ +//// [emitBOM.ts] + +// JS and d.ts output should have a BOM but not the sourcemap +var x; + +//// [emitBOM.js] +var x; +//# sourceMappingURL=emitBOM.js.map + +//// [emitBOM.d.ts] +declare var x: any; diff --git a/tests/baselines/reference/emitBOM.js.map b/tests/baselines/reference/emitBOM.js.map new file mode 100644 index 0000000000..46a584bf79 --- /dev/null +++ b/tests/baselines/reference/emitBOM.js.map @@ -0,0 +1,2 @@ +//// [emitBOM.js.map] +{"version":3,"file":"emitBOM.js","sourceRoot":"","sources":["emitBOM.ts"],"names":[],"mappings":"AAEA,IAAI,CAAC,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/emitBOM.sourcemap.txt b/tests/baselines/reference/emitBOM.sourcemap.txt new file mode 100644 index 0000000000..19dd3247a7 --- /dev/null +++ b/tests/baselines/reference/emitBOM.sourcemap.txt @@ -0,0 +1,28 @@ +=================================================================== +JsFile: emitBOM.js +mapUrl: emitBOM.js.map +sourceRoot: +sources: emitBOM.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/emitBOM.js +sourceFile:emitBOM.ts +------------------------------------------------------------------- +>>>var x; +1 > +2 >^^^^ +3 > ^ +4 > ^ +5 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + >// JS and d.ts output should have a BOM but not the sourcemap + > +2 >var +3 > x +4 > ; +1 >Emitted(1, 1) Source(3, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(3, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(3, 6) + SourceIndex(0) +4 >Emitted(1, 7) Source(3, 7) + SourceIndex(0) +--- +>>>//# sourceMappingURL=emitBOM.js.map \ No newline at end of file diff --git a/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js b/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js new file mode 100644 index 0000000000..54089541fd --- /dev/null +++ b/tests/baselines/reference/inheritedOverloadedSpecializedSignatures.js @@ -0,0 +1,47 @@ +//// [inheritedOverloadedSpecializedSignatures.ts] +interface A { + (key:string):void; +} + +interface B extends A { + (key:'foo'):string; +} + +var b:B; +// Should not error +b('foo').charAt(0); + +interface A { + (x: 'A1'): string; + (x: string): void; +} + +interface B extends A { + (x: 'B1'): number; +} + +interface A { + (x: 'A2'): boolean; +} + +interface B { + (x: 'B2'): string[]; +} + +var b: B; +// non of these lines should error +var x1: string[] = b('B2'); +var x2: number = b('B1'); +var x3: boolean = b('A2'); +var x4: string = b('A1'); +var x5: void = b('A0'); + +//// [inheritedOverloadedSpecializedSignatures.js] +var b; +b('foo').charAt(0); +var b; +var x1 = b('B2'); +var x2 = b('B1'); +var x3 = b('A2'); +var x4 = b('A1'); +var x5 = b('A0'); diff --git a/tests/cases/compiler/emitBOM.ts b/tests/cases/compiler/emitBOM.ts new file mode 100644 index 0000000000..f503cd4de7 --- /dev/null +++ b/tests/cases/compiler/emitBOM.ts @@ -0,0 +1,6 @@ +//@emitBOM: true +//@declaration: true +//@sourcemap: true + +// JS and d.ts output should have a BOM but not the sourcemap +var x; \ No newline at end of file diff --git a/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts b/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts new file mode 100644 index 0000000000..c513cecb2c --- /dev/null +++ b/tests/cases/compiler/inheritedOverloadedSpecializedSignatures.ts @@ -0,0 +1,36 @@ +interface A { + (key:string):void; +} + +interface B extends A { + (key:'foo'):string; +} + +var b:B; +// Should not error +b('foo').charAt(0); + +interface A { + (x: 'A1'): string; + (x: string): void; +} + +interface B extends A { + (x: 'B1'): number; +} + +interface A { + (x: 'A2'): boolean; +} + +interface B { + (x: 'B2'): string[]; +} + +var b: B; +// non of these lines should error +var x1: string[] = b('B2'); +var x2: number = b('B1'); +var x3: boolean = b('A2'); +var x4: string = b('A1'); +var x5: void = b('A0'); \ No newline at end of file diff --git a/tests/perfsys.ts b/tests/perfsys.ts index d2e3215c56..d3f7ff2ab0 100644 --- a/tests/perfsys.ts +++ b/tests/perfsys.ts @@ -8,26 +8,26 @@ module perftest { export interface IO { getOut(): string; - getErr(): string; } export var readFile = sys.readFile; var writeFile = sys.writeFile; export var write = sys.write; - export var writeErr = sys.writeErr; var resolvePath = sys.resolvePath; export var getExecutingFilePath = sys.getExecutingFilePath; export var getCurrentDirectory = sys.getCurrentDirectory; + var exit = sys.exit; var args = sys.args; // augment sys so first ts.executeCommandLine call will be finish silently - sys.writeErr = (s: string) => { }; + sys.write = (s: string) => { }; + sys.exit = (code: number) => { }; sys.args = [] export function restoreSys() { sys.args = args; - sys.writeErr = writeErr; + sys.write = write; } export function hasLogIOFlag() { @@ -90,17 +90,14 @@ module perftest { return path } - sys.writeFile = (path: string, data: string) => { }; + sys.writeFile = (path: string, data: string) => { }; var out: string = ""; - var err: string = ""; sys.write = (s: string) => { out += s; }; - sys.writeErr = (s: string) => { err += s; }; return { getOut: () => out, - getErr: () => err }; } } diff --git a/tests/perftc.ts b/tests/perftc.ts index 6ab29de006..cedfe254e9 100644 --- a/tests/perftc.ts +++ b/tests/perftc.ts @@ -13,8 +13,9 @@ if (perftest.hasLogIOFlag()) { getDefaultLibFilename: () => ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(perftest.getExecutingFilePath())), "lib.d.ts"), writeFile: (f: string, content: string) => { throw new Error("Unexpected operation: writeFile"); }, getCurrentDirectory: () => perftest.getCurrentDirectory(), - getCanonicalFileName: getCanonicalFileName, - useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames + getCanonicalFileName: ts.getCanonicalFileName, + useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, + getNewLine: () => sys.newLine }; var commandLine = ts.parseCommandLine(perftest.getArgsWithoutLogIOFlag()); @@ -26,5 +27,4 @@ else { var io = perftest.prepare(); ts.executeCommandLine(perftest.getArgsWithoutIOLogFile()); perftest.write(io.getOut()); - perftest.writeErr(io.getErr()); }