2014-07-13 01:04:16 +02:00
// This file contains the build logic for the public repo
2017-09-15 00:42:06 +02:00
// @ts-check
2017-12-19 22:40:32 +01:00
/// <reference types="jake" />
2014-07-13 01:04:16 +02:00
2018-06-11 00:20:58 +02:00
var fs = require ( "fs" ) ;
var os = require ( "os" ) ;
var path = require ( "path" ) ;
var child_process = require ( "child_process" ) ;
var fold = require ( "travis-fold" ) ;
var ts = require ( "./lib/typescript" ) ;
2018-06-08 02:53:44 +02:00
const getDirSize = require ( "./scripts/build/getDirSize" ) ;
2017-02-08 03:14:23 +01:00
2018-06-11 00:20:58 +02:00
// Variables
2018-06-11 04:28:38 +02:00
var parserDirectory = "src/parser/" ;
2018-06-11 00:20:58 +02:00
var compilerDirectory = "src/compiler/" ;
var serverDirectory = "src/server/" ;
var harnessDirectory = "src/harness/" ;
var libraryDirectory = "src/lib/" ;
var scriptsDirectory = "scripts/" ;
var unittestsDirectory = "src/harness/unittests/" ;
var docDirectory = "doc/" ;
var lclDirectory = "src/loc/lcl" ;
var builtDirectory = "built/" ;
var builtLocalDirectory = "built/local/" ;
var LKGDirectory = "lib/" ;
var copyright = "CopyrightNotice.txt" ;
var thirdParty = "ThirdPartyNoticeText.txt" ;
var defaultTestTimeout = 40000 ;
2018-06-11 04:28:38 +02:00
// Task to build the tests infrastructure using the built compiler
var run = path . join ( builtLocalDirectory , "run.js" ) ;
2018-06-11 00:20:58 +02:00
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
var nodeModulesPathPrefix = path . resolve ( "./node_modules/.bin/" ) + path . delimiter ;
if ( process . env . path !== undefined ) {
process . env . path = nodeModulesPathPrefix + process . env . path ;
}
else if ( process . env . PATH !== undefined ) {
process . env . PATH = nodeModulesPathPrefix + process . env . PATH ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
/ * *
* @param diagnostics { ts . Diagnostic [ ] }
* @param [ pretty ] { boolean }
* /
function diagnosticsToString ( diagnostics , pretty ) {
const host = {
getCurrentDirectory() { return process . cwd ( ) ; } ,
getCanonicalFileName ( fileName ) { return fileName ; } ,
getNewLine() { return os . EOL ; }
} ;
return pretty ? ts . formatDiagnosticsWithColorAndContext ( diagnostics , host ) :
ts . formatDiagnostics ( diagnostics , host ) ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
/** @param diagnostics {ts.Diagnostic[]} */
function reportDiagnostics ( diagnostics ) {
console . log ( diagnosticsToString ( diagnostics , process . stdout . isTTY ) ) ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
/** @param jsonPath {string} */
function readJson ( jsonPath ) {
const jsonText = fs . readFileSync ( jsonPath , "utf8" ) ;
const result = ts . parseConfigFileTextToJson ( jsonPath , jsonText ) ;
if ( result . error ) {
reportDiagnostics ( [ result . error ] ) ;
throw new Error ( "An error occurred during parse." ) ;
}
return result . config ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
/** @param configPath {string} */
function filesFromConfig ( configPath ) {
const config = readJson ( configPath ) ;
const configFileContent = ts . parseJsonConfigFileContent ( config , ts . sys , path . dirname ( configPath ) ) ;
if ( configFileContent . errors && configFileContent . errors . length ) {
reportDiagnostics ( configFileContent . errors ) ;
throw new Error ( "An error occurred during parse." ) ;
}
return configFileContent . fileNames ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 04:28:38 +02:00
/** @param configPath {string} */
function filesAndOutputFromConfig ( configPath ) {
const config = readJson ( configPath ) ;
const configFileContent = ts . parseJsonConfigFileContent ( config , ts . sys , path . dirname ( configPath ) ) ;
if ( configFileContent . errors && configFileContent . errors . length ) {
reportDiagnostics ( configFileContent . errors ) ;
throw new Error ( "An error occurred during parse." ) ;
}
return { files : configFileContent.fileNames , output : configFileContent.options.outFile } ;
}
2018-06-11 00:20:58 +02:00
function toNs ( diff ) {
return diff [ 0 ] * 1 e9 + diff [ 1 ] ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
function mark() {
if ( ! fold . isTravis ( ) ) return ;
var stamp = process . hrtime ( ) ;
var id = Math . floor ( Math . random ( ) * 0xFFFFFFFF ) . toString ( 16 ) ;
console . log ( "travis_time:start:" + id + "\r" ) ;
return {
stamp : stamp ,
id : id
} ;
}
2018-06-10 22:26:16 +02:00
2018-06-11 00:20:58 +02:00
function measure ( marker ) {
if ( ! fold . isTravis ( ) ) return ;
var diff = process . hrtime ( marker . stamp ) ;
var total = [ marker . stamp [ 0 ] + diff [ 0 ] , marker . stamp [ 1 ] + diff [ 1 ] ] ;
console . log ( "travis_time:end:" + marker . id + ":start=" + toNs ( marker . stamp ) + ",finish=" + toNs ( total ) + ",duration=" + toNs ( diff ) + "\r" ) ;
}
2018-06-10 22:26:16 +02:00
2018-06-11 00:20:58 +02:00
function removeConstModifierFromEnumDeclarations ( text ) {
2018-06-11 04:28:38 +02:00
return text . replace ( /^(\s*)(export )?const enum (\S+) {(\s*)$/gm , '$1$2enum $3 {$4' ) ;
2018-06-11 00:20:58 +02:00
}
2018-06-10 22:26:16 +02:00
2018-06-11 04:28:38 +02:00
compileOutputConfigFile ( 'src/parser/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/compiler/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/services/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/typescriptServices/tsconfig.json' , [ ] , [ copyright ] , function ( ) {
jake . cpR ( servicesFile , nodePackageFile , { silent : true } ) ;
prependFile ( copyright , standaloneDefinitionsFile ) ;
// Stanalone/web definition file using global 'ts' namespace
jake . cpR ( standaloneDefinitionsFile , nodeDefinitionsFile , { silent : true } ) ;
var definitionFileContents = fs . readFileSync ( nodeDefinitionsFile ) . toString ( ) ;
definitionFileContents = removeConstModifierFromEnumDeclarations ( definitionFileContents ) ;
fs . writeFileSync ( standaloneDefinitionsFile , definitionFileContents ) ;
// Official node package definition file, pointed to by 'typings' in package.json
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
var nodeDefinitionsFileContents = definitionFileContents + "\nexport = ts;" ;
fs . writeFileSync ( nodeDefinitionsFile , nodeDefinitionsFileContents ) ;
// Node package definition file to be distributed without the package. Created by replacing
// 'ts' namespace with '"typescript"' as a module.
var nodeStandaloneDefinitionsFileContents = definitionFileContents . replace ( /declare (namespace|module) ts/g , 'declare module "typescript"' ) ;
fs . writeFileSync ( nodeStandaloneDefinitionsFile , nodeStandaloneDefinitionsFileContents ) ;
} ) ;
compileOutputConfigFile ( 'src/core/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/harness/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/testRunner/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/tsc/tsconfig.json' , [ ] , [ copyright ] ) ;
compileOutputConfigFile ( 'src/server/tsconfig.json' , [ ] , [ copyright ] ) ;
compileOutputConfigFile ( 'src/tsserver/tsconfig.json' , [ ] , [ copyright ] ) ;
compileOutputConfigFile ( 'src/tsserverLibrary/tsconfig.json' , [ ] , [ ] , function ( ) {
prependFile ( copyright , tsserverLibraryDefinitionFile ) ;
// Appending exports at the end of the server library
var tsserverLibraryDefinitionFileContents =
fs . readFileSync ( tsserverLibraryDefinitionFile ) . toString ( ) +
"\nexport = ts;" +
"\nexport as namespace ts;" ;
tsserverLibraryDefinitionFileContents = removeConstModifierFromEnumDeclarations ( tsserverLibraryDefinitionFileContents ) ;
2018-06-11 20:32:27 +02:00
// Normalize line endings
2018-06-11 21:26:47 +02:00
tsserverLibraryDefinitionFileContents = tsserverLibraryDefinitionFileContents . replace ( /\r\n/g , "\n" ) ;
2018-06-11 04:28:38 +02:00
fs . writeFileSync ( tsserverLibraryDefinitionFile , tsserverLibraryDefinitionFileContents ) ;
} ) ;
compileOutputConfigFile ( 'src/typingsInstaller/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/typingsInstallerCore/tsconfig.json' ) ;
compileOutputConfigFile ( 'src/watchGuard/tsconfig.json' ) ;
compileConfigFile ( 'built/local/cancellationToken.js' , [ ] , 'src/cancellationToken/tsconfig.json' , [ copyright ] ) ;
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
var typesMapOutputPath = path . join ( builtLocalDirectory , 'typesMap.json' ) ;
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
/** @type {{ libs: string[], paths?: Record<string, string>, sources?: Record<string, string[]> }} */
var libraries = readJson ( "./src/lib/libs.json" ) ;
/ * *
* . lcg file is what localization team uses to know what messages to localize .
* The file is always generated in 'enu\diagnosticMessages.generated.json.lcg'
* /
var generatedLCGFile = path . join ( builtLocalDirectory , "enu" , "diagnosticMessages.generated.json.lcg" ) ;
/ * *
* The localization target produces the two following transformations :
* 1 . 'src\loc\lcl\<locale>\diagnosticMessages.generated.json.lcl' = > 'built\local\<locale>\diagnosticMessages.generated.json'
* convert localized resources into a . json file the compiler can understand
* 2 . 'src\compiler\diagnosticMessages.generated.json' = > 'built\local\ENU\diagnosticMessages.generated.json.lcg'
* generate the lcg file ( source of messages to localize ) from the diagnosticMessages . generated . json
* /
var localizationTargets = [ "cs" , "de" , "es" , "fr" , "it" , "ja" , "ko" , "pl" , "pt-br" , "ru" , "tr" , "zh-cn" , "zh-tw" ] . map ( function ( f ) {
return path . join ( builtLocalDirectory , f ) ;
} ) . concat ( path . dirname ( generatedLCGFile ) ) ;
// Prepends the contents of prefixFile to destinationFile
function prependFile ( prefixFile , destinationFile ) {
if ( ! fs . existsSync ( prefixFile ) ) {
fail ( prefixFile + " does not exist!" ) ;
2018-06-10 22:23:16 +02:00
}
2018-06-11 00:20:58 +02:00
if ( ! fs . existsSync ( destinationFile ) ) {
fail ( destinationFile + " failed to be created!" ) ;
}
var temp = "temptemp" ;
jake . cpR ( prefixFile , temp , { silent : true } ) ;
fs . appendFileSync ( temp , fs . readFileSync ( destinationFile ) ) ;
fs . renameSync ( temp , destinationFile ) ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
// concatenate a list of sourceFiles to a destinationFile
function concatenateFiles ( destinationFile , sourceFiles ) {
var temp = "temptemp" ;
// append all files in sequence
var text = "" ;
for ( var i = 0 ; i < sourceFiles . length ; i ++ ) {
if ( ! fs . existsSync ( sourceFiles [ i ] ) ) {
fail ( sourceFiles [ i ] + " does not exist!" ) ;
}
if ( i > 0 ) { text += "\n\n" ; }
text += fs . readFileSync ( sourceFiles [ i ] ) . toString ( ) . replace ( /\r?\n/g , "\n" ) ;
}
fs . writeFileSync ( temp , text ) ;
// Move the file to the final destination
fs . renameSync ( temp , destinationFile ) ;
}
var useDebugMode = true ;
var host = process . env . TYPESCRIPT_HOST || process . env . host || "node" ;
var compilerFilename = "tsc.js" ;
var LKGCompiler = path . join ( LKGDirectory , compilerFilename ) ;
var builtLocalCompiler = path . join ( builtLocalDirectory , compilerFilename ) ;
2018-06-11 04:28:38 +02:00
function compileOutputConfigFile ( configFile , prereqs , prefixes , callback ) {
const info = filesAndOutputFromConfig ( configFile ) ;
compileConfigFile ( info . output , prereqs , configFile , prefixes , false , callback ) ;
}
function compileConfigFile ( outFile , prereqs , configFile , prefixes , useBuiltCompiler = false , callback ) {
const allPrereqs = filesFromConfig ( configFile ) . concat ( prereqs || [ ] ) . concat ( configFile ) ;
2018-06-11 19:16:10 +02:00
outFile = outFile . replace ( /\//g , path . sep ) ;
2018-06-11 04:28:38 +02:00
file ( outFile , allPrereqs , function ( ) {
const startCompileTime = mark ( ) ;
const compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler ;
2018-06-11 05:05:12 +02:00
const cmd = ` ${ host } ${ compilerPath } -b ${ configFile } ` ;
2018-06-11 04:28:38 +02:00
console . log ( cmd + "\n" ) ;
var ex = jake . createExec ( [ cmd ] ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
if ( ! useDebugMode && prefixes && fs . existsSync ( outFile ) ) {
for ( var i in prefixes ) {
prependFile ( prefixes [ i ] , outFile ) ;
}
}
if ( callback ) {
callback ( ) ;
}
measure ( startCompileTime ) ;
complete ( ) ;
} ) ;
ex . addListener ( "error" , function ( ) {
fs . unlinkSync ( outFile ) ;
fail ( "Compilation of " + outFile + " unsuccessful" ) ;
measure ( startCompileTime ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
}
2018-06-11 00:20:58 +02:00
/ * *
* Compiles a file from a list of sources
* @param { string } outFile the target file name
* @param { string [ ] } sources an array of the names of the source files
* @param { string [ ] } prereqs prerequisite tasks to compiling the file
* @param { string [ ] } prefixes a list of files to prepend to the target file
* @param { boolean } useBuiltCompiler true to use the built compiler , false to use the LKG
* @param { object } [ opts ] property bag containing auxiliary options
* @param { boolean } [ opts . noOutFile ] true to compile without using -- out
* @param { boolean } [ opts . generateDeclarations ] true to compile using -- declaration
* @param { string } [ opts . outDir ] value for '--outDir' command line option
* @param { boolean } [ opts . keepComments ] false to compile using -- removeComments
* @param { boolean } [ opts . preserveConstEnums ] true if compiler should keep const enums in code
* @param { boolean } [ opts . noResolve ] true if compiler should not include non - rooted files in compilation
* @param { boolean } [ opts . stripInternal ] true if compiler should remove declarations marked as internal
* @param { boolean } [ opts . inlineSourceMap ] true if compiler should inline sourceMap
* @param { string [ ] } [ opts . types ] array of types to include in compilation
* @param { string } [ opts . lib ] explicit libs to include .
* @param { function ( ) : void } [ callback ] a function to execute after the compilation process ends
* /
function compileFile ( outFile , sources , prereqs , prefixes , useBuiltCompiler , opts , callback ) {
2018-06-11 04:28:38 +02:00
file ( outFile , prereqs , function ( ) {
2018-06-11 00:20:58 +02:00
var startCompileTime = mark ( ) ;
opts = opts || { } ;
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler ;
var options = "--noImplicitAny --noImplicitThis --alwaysStrict --noEmitOnError" ;
if ( opts . types ) {
options += " --types " + opts . types . join ( "," ) ;
}
options += " --pretty" ;
// Keep comments when specifically requested
// or when in debug mode.
if ( ! ( opts . keepComments || useDebugMode ) ) {
options += " --removeComments" ;
}
if ( opts . generateDeclarations ) {
options += " --declaration" ;
2018-06-10 19:58:16 +02:00
}
2018-06-11 00:20:58 +02:00
if ( opts . preserveConstEnums || useDebugMode ) {
options += " --preserveConstEnums" ;
2018-06-10 19:59:03 +02:00
}
2018-06-11 00:20:58 +02:00
if ( opts . outDir ) {
options += " --outDir " + opts . outDir ;
}
if ( ! opts . noOutFile ) {
options += " --out " + outFile ;
}
else {
options += " --module commonjs" ;
}
if ( opts . noResolve ) {
options += " --noResolve" ;
}
if ( useDebugMode ) {
if ( opts . inlineSourceMap ) {
options += " --inlineSourceMap --inlineSources" ;
}
else {
options += " --sourcemap" ;
}
}
options += " --newLine LF" ;
if ( opts . stripInternal ) {
options += " --stripInternal" ;
}
2018-06-11 04:28:38 +02:00
options += " --target es5" ;
2018-06-11 00:20:58 +02:00
if ( opts . lib ) {
options += " --lib " + opts . lib ;
}
else {
options += " --lib es5" ;
}
options += " --noUnusedLocals --noUnusedParameters --strictNullChecks" ;
var cmd = host + " " + compilerPath + " " + options + " " ;
cmd = cmd + sources . join ( " " ) ;
console . log ( cmd + "\n" ) ;
var ex = jake . createExec ( [ cmd ] ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
if ( ! useDebugMode && prefixes && fs . existsSync ( outFile ) ) {
for ( var i in prefixes ) {
prependFile ( prefixes [ i ] , outFile ) ;
}
}
if ( callback ) {
callback ( ) ;
}
measure ( startCompileTime ) ;
complete ( ) ;
2018-06-10 19:59:03 +02:00
} ) ;
2018-06-11 00:20:58 +02:00
ex . addListener ( "error" , function ( ) {
fs . unlinkSync ( outFile ) ;
fail ( "Compilation of " + outFile + " unsuccessful" ) ;
measure ( startCompileTime ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
}
// Prerequisite task for built directory and library typings
directory ( builtLocalDirectory ) ;
var libraryTargets = libraries . libs . map ( function ( lib ) {
var relativeSources = [ "header.d.ts" ] . concat ( libraries . sources && libraries . sources [ lib ] || [ lib + ".d.ts" ] ) ;
var relativeTarget = libraries . paths && libraries . paths [ lib ] || ( "lib." + lib + ".d.ts" ) ;
var sources = [ copyright ] . concat ( relativeSources . map ( s = > path . join ( libraryDirectory , s ) ) ) ;
var target = path . join ( builtLocalDirectory , relativeTarget ) ;
file ( target , [ builtLocalDirectory ] . concat ( sources ) , function ( ) {
concatenateFiles ( target , sources ) ;
2018-06-10 19:58:16 +02:00
} ) ;
2018-06-11 00:20:58 +02:00
return target ;
} ) ;
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
// Lib target to build the library files
desc ( "Builds the library targets" ) ;
task ( "lib" , libraryTargets ) ;
// Generate diagnostics
var processDiagnosticMessagesJs = path . join ( scriptsDirectory , "processDiagnosticMessages.js" ) ;
2018-06-11 04:28:38 +02:00
var diagnosticMessagesJson = path . join ( parserDirectory , "diagnosticMessages.json" ) ;
var diagnosticInfoMapTs = path . join ( parserDirectory , "diagnosticInformationMap.generated.ts" ) ;
compileConfigFile ( processDiagnosticMessagesJs , [ ] , "./scripts/processDiagnosticMessages.tsconfig.json" )
2018-06-11 00:20:58 +02:00
2018-06-11 04:28:38 +02:00
var generatedDiagnosticMessagesJSON = path . join ( parserDirectory , "diagnosticMessages.generated.json" ) ;
2018-06-11 00:20:58 +02:00
var builtGeneratedDiagnosticMessagesJSON = path . join ( builtLocalDirectory , "diagnosticMessages.generated.json" ) ;
// Localize diagnostics script
var generateLocalizedDiagnosticMessagesJs = path . join ( scriptsDirectory , "generateLocalizedDiagnosticMessages.js" ) ;
var generateLocalizedDiagnosticMessagesTs = path . join ( scriptsDirectory , "generateLocalizedDiagnosticMessages.ts" ) ;
file ( generateLocalizedDiagnosticMessagesTs ) ;
compileFile ( generateLocalizedDiagnosticMessagesJs ,
[ generateLocalizedDiagnosticMessagesTs ] ,
[ generateLocalizedDiagnosticMessagesTs ] ,
[ ] ,
/*useBuiltCompiler*/ false , { noOutFile : true , types : [ "node" , "xml2js" ] } ) ;
// Localize diagnostics
file ( generatedLCGFile , [ generateLocalizedDiagnosticMessagesJs , diagnosticInfoMapTs , generatedDiagnosticMessagesJSON ] , function ( ) {
var cmd = host + " " + generateLocalizedDiagnosticMessagesJs + " " + lclDirectory + " " + builtLocalDirectory + " " + generatedDiagnosticMessagesJSON ;
console . log ( cmd ) ;
var ex = jake . createExec ( [ cmd ] ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
complete ( ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
task ( "localize" , [ generatedLCGFile ] ) ;
var buildProtocolTs = path . join ( scriptsDirectory , "buildProtocol.ts" ) ;
var buildProtocolJs = path . join ( scriptsDirectory , "buildProtocol.js" ) ;
var buildProtocolDts = path . join ( builtLocalDirectory , "protocol.d.ts" ) ;
var typescriptServicesDts = path . join ( builtLocalDirectory , "typescriptServices.d.ts" ) ;
file ( buildProtocolTs ) ;
compileFile ( buildProtocolJs ,
[ buildProtocolTs ] ,
[ buildProtocolTs ] ,
[ ] ,
/*useBuiltCompiler*/ false ,
{ noOutFile : true , lib : "es6" } ) ;
2018-06-11 04:28:38 +02:00
file ( buildProtocolDts , [ buildProtocolTs , buildProtocolJs , typescriptServicesDts ] , function ( ) {
2018-06-11 00:20:58 +02:00
var protocolTs = path . join ( serverDirectory , "protocol.ts" ) ;
2018-06-11 04:28:38 +02:00
var cmd = host + " " + buildProtocolJs + " " + protocolTs + " " + typescriptServicesDts + " " + buildProtocolDts ;
2018-06-11 00:20:58 +02:00
console . log ( cmd ) ;
var ex = jake . createExec ( [ cmd ] ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
complete ( ) ;
} ) ;
2018-06-11 04:28:38 +02:00
ex . addListener ( "error" , function ( e , status ) {
fail ( "Process exited with code " + status ) ;
} ) ;
2018-06-11 00:20:58 +02:00
ex . run ( ) ;
} , { async : true } ) ;
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
file ( diagnosticInfoMapTs , [ processDiagnosticMessagesJs , diagnosticMessagesJson ] , function ( ) {
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson ;
console . log ( cmd ) ;
var ex = jake . createExec ( [ cmd ] ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
complete ( ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
file ( builtGeneratedDiagnosticMessagesJSON , [ generatedDiagnosticMessagesJSON ] , function ( ) {
if ( fs . existsSync ( builtLocalDirectory ) ) {
jake . cpR ( generatedDiagnosticMessagesJSON , builtGeneratedDiagnosticMessagesJSON ) ;
2018-06-10 19:58:16 +02:00
}
} ) ;
2018-06-11 00:20:58 +02:00
desc ( "Generates a diagnostic file in TypeScript based on an input JSON file" ) ;
task ( "generate-diagnostics" , [ diagnosticInfoMapTs ] ) ;
// Publish nightly
var configurePrereleaseJs = path . join ( scriptsDirectory , "configurePrerelease.js" ) ;
var configurePrereleaseTs = path . join ( scriptsDirectory , "configurePrerelease.ts" ) ;
var packageJson = "package.json" ;
var versionFile = path . join ( compilerDirectory , "core.ts" ) ;
file ( configurePrereleaseTs ) ;
compileFile ( /*outfile*/ configurePrereleaseJs ,
/*sources*/ [ configurePrereleaseTs ] ,
/*prereqs*/ [ configurePrereleaseTs ] ,
/*prefixes*/ [ ] ,
/*useBuiltCompiler*/ false ,
{ noOutFile : true , generateDeclarations : false , keepComments : false , noResolve : false , stripInternal : false } ) ;
task ( "setDebugMode" , function ( ) {
useDebugMode = true ;
2018-06-10 19:59:03 +02:00
} ) ;
2018-06-11 00:20:58 +02:00
task ( "configure-nightly" , [ configurePrereleaseJs ] , function ( ) {
var cmd = host + " " + configurePrereleaseJs + " dev " + packageJson + " " + versionFile ;
2018-06-10 19:59:03 +02:00
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-11 00:20:58 +02:00
desc ( "Configure, build, test, and publish the nightly release." ) ;
task ( "publish-nightly" , [ "configure-nightly" , "LKG" , "clean" , "setDebugMode" , "runtests-parallel" ] , function ( ) {
var cmd = "npm publish --tag next" ;
console . log ( cmd ) ;
exec ( cmd ) ;
} ) ;
task ( "configure-insiders" , [ configurePrereleaseJs ] , function ( ) {
var cmd = host + " " + configurePrereleaseJs + " insiders " + packageJson + " " + versionFile ;
2018-06-10 19:58:16 +02:00
console . log ( cmd ) ;
exec ( cmd ) ;
2018-06-10 22:23:16 +02:00
} , { async : true } ) ;
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Configure, build, test, and publish the insiders release." ) ;
task ( "publish-insiders" , [ "configure-insiders" , "LKG" , "clean" , "setDebugMode" , "runtests-parallel" ] , function ( ) {
var cmd = "npm publish --tag insiders" ;
console . log ( cmd ) ;
exec ( cmd ) ;
2018-06-10 19:58:16 +02:00
} ) ;
2018-06-11 00:20:58 +02:00
var importDefinitelyTypedTestsDirectory = path . join ( scriptsDirectory , "importDefinitelyTypedTests" ) ;
var importDefinitelyTypedTestsJs = path . join ( importDefinitelyTypedTestsDirectory , "importDefinitelyTypedTests.js" ) ;
var importDefinitelyTypedTestsTs = path . join ( importDefinitelyTypedTestsDirectory , "importDefinitelyTypedTests.ts" ) ;
file ( importDefinitelyTypedTestsTs ) ;
file ( importDefinitelyTypedTestsJs , [ "tsd-scripts" , importDefinitelyTypedTestsTs ] , function ( ) {
var cmd = host + " " + LKGCompiler + " -p " + importDefinitelyTypedTestsDirectory ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
task ( "importDefinitelyTypedTests" , [ importDefinitelyTypedTestsJs ] , function ( ) {
var cmd = host + " " + importDefinitelyTypedTestsJs + " ./ ../DefinitelyTyped" ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-11 04:28:38 +02:00
var tscFile = path . join ( builtLocalDirectory , "tsc.js" ) ;
var cancellationTokenFile = path . join ( builtLocalDirectory , "cancellationToken.js" ) ;
var watchGuardFile = path . join ( builtLocalDirectory , "watchGuard.js" ) ;
var serverFile = path . join ( builtLocalDirectory , "tsserver.js" ) ;
var typingsInstallerFile = path . join ( builtLocalDirectory , "typingsInstaller.js" ) ;
2018-06-11 00:20:58 +02:00
var servicesFile = path . join ( builtLocalDirectory , "typescriptServices.js" ) ;
var standaloneDefinitionsFile = path . join ( builtLocalDirectory , "typescriptServices.d.ts" ) ;
var nodePackageFile = path . join ( builtLocalDirectory , "typescript.js" ) ;
var nodeDefinitionsFile = path . join ( builtLocalDirectory , "typescript.d.ts" ) ;
var nodeStandaloneDefinitionsFile = path . join ( builtLocalDirectory , "typescript_standalone.d.ts" ) ;
2018-06-11 04:28:38 +02:00
var tsserverLibraryFile = path . join ( builtLocalDirectory , "tsserverlibrary.js" ) ;
var tsserverLibraryDefinitionFile = path . join ( builtLocalDirectory , "tsserverlibrary.d.ts" ) ;
2018-06-11 00:20:58 +02:00
file ( typescriptServicesDts , [ servicesFile ] ) ;
2018-06-11 04:28:38 +02:00
file ( typesMapOutputPath , /** @type {*} */ ( function ( ) {
2018-06-11 00:20:58 +02:00
var content = fs . readFileSync ( path . join ( serverDirectory , 'typesMap.json' ) ) ;
// Validate that it's valid JSON
try {
JSON . parse ( content . toString ( ) ) ;
} catch ( e ) {
console . log ( "Parse error in typesMap.json: " + e ) ;
}
fs . writeFileSync ( typesMapOutputPath , content ) ;
} ) ) ;
// Local target to build the language service server library
desc ( "Builds language service server library" ) ;
task ( "lssl" , [ tsserverLibraryFile , tsserverLibraryDefinitionFile , typesMapOutputPath ] ) ;
2018-06-10 19:58:16 +02:00
2018-06-10 22:23:16 +02:00
desc ( "Emit the start of the build fold" ) ;
2018-06-11 00:20:58 +02:00
task ( "build-fold-start" , [ ] , function ( ) {
2018-06-10 22:23:16 +02:00
if ( fold . isTravis ( ) ) console . log ( fold . start ( "build" ) ) ;
} ) ;
2015-09-18 22:13:26 +02:00
2018-06-10 22:23:16 +02:00
desc ( "Emit the end of the build fold" ) ;
2018-06-11 00:20:58 +02:00
task ( "build-fold-end" , [ ] , function ( ) {
2018-06-10 22:23:16 +02:00
if ( fold . isTravis ( ) ) console . log ( fold . end ( "build" ) ) ;
} ) ;
2015-09-18 02:55:07 +02:00
2018-06-11 00:20:58 +02:00
// Local target to build the compiler and services
desc ( "Builds the full compiler and services" ) ;
2018-06-11 05:05:12 +02:00
task ( "local" , [ "build-fold-start" , "generate-diagnostics" , "lib" ,
tscFile ,
servicesFile ,
typingsInstallerFile ,
cancellationTokenFile ,
watchGuardFile ,
nodeDefinitionsFile ,
serverFile ,
buildProtocolDts ,
builtGeneratedDiagnosticMessagesJSON ,
run ,
"lssl" , "localize" , "build-fold-end" ] ) ;
2018-06-11 00:20:58 +02:00
// Local target to build only tsc.js
desc ( "Builds only the compiler" ) ;
task ( "tsc" , [ "generate-diagnostics" , "lib" , tscFile ] ) ;
// Local target to build the compiler and services
desc ( "Sets release mode flag" ) ;
task ( "release" , function ( ) {
useDebugMode = false ;
} ) ;
// Set the default task to "local"
task ( "default" , [ "local" ] ) ;
// Cleans the built directory
desc ( "Cleans the compiler output, declare files, and tests" ) ;
task ( "clean" , function ( ) {
jake . rmRf ( builtDirectory ) ;
} ) ;
// Generate Markdown spec
var word2mdJs = path . join ( scriptsDirectory , "word2md.js" ) ;
var word2mdTs = path . join ( scriptsDirectory , "word2md.ts" ) ;
var specWord = path . join ( docDirectory , "TypeScript Language Specification.docx" ) ;
var specMd = path . join ( docDirectory , "spec.md" ) ;
file ( word2mdTs ) ;
// word2md script
compileFile ( word2mdJs ,
[ word2mdTs ] ,
[ word2mdTs ] ,
[ ] ,
/*useBuiltCompiler*/ false ,
{
lib : "scripthost,es5"
} ) ;
// The generated spec.md; built for the 'generate-spec' task
file ( specMd , [ word2mdJs , specWord ] , function ( ) {
var specWordFullPath = path . resolve ( specWord ) ;
var specMDFullPath = path . resolve ( specMd ) ;
var cmd = "cscript //nologo " + word2mdJs + ' "' + specWordFullPath + '" ' + '"' + specMDFullPath + '"' ;
console . log ( cmd ) ;
child_process . exec ( cmd , function ( ) {
complete ( ) ;
} ) ;
} , { async : true } ) ;
desc ( "Generates a Markdown version of the Language Specification" ) ;
task ( "generate-spec" , [ specMd ] ) ;
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc ( "Makes a new LKG out of the built js files" ) ;
task ( "LKG" , [ "clean" , "release" , "local" ] . concat ( libraryTargets ) , ( ) = > {
const sizeBefore = getDirSize ( LKGDirectory ) ;
var expectedFiles = [ tscFile , servicesFile , serverFile , nodePackageFile , nodeDefinitionsFile , standaloneDefinitionsFile , tsserverLibraryFile , tsserverLibraryDefinitionFile , cancellationTokenFile , typingsInstallerFile , buildProtocolDts , watchGuardFile ] .
concat ( libraryTargets ) .
concat ( localizationTargets ) ;
var missingFiles = expectedFiles . filter ( f = > ! fs . existsSync ( f ) ) ;
if ( missingFiles . length > 0 ) {
fail ( new Error ( "Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
". The following files are missing:\n" + missingFiles . join ( "\n" ) ) ) ;
}
// Copy all the targets into the LKG directory
jake . mkdirP ( LKGDirectory ) ;
2018-06-11 04:28:38 +02:00
expectedFiles . forEach ( f = > {
if ( f . endsWith ( ".d.ts" ) ) {
// remove-internal all the .d.ts files
jake . createExec ( [ host , "node_modules/remove-internal/lib/cli.js" , f , "--outdir" , LKGDirectory ] ) . run ( ) ;
}
else {
jake . cpR ( f , LKGDirectory ) ;
}
} ) ;
2018-06-11 00:20:58 +02:00
2018-06-11 05:05:12 +02:00
/ *
2018-06-11 00:20:58 +02:00
const sizeAfter = getDirSize ( LKGDirectory ) ;
if ( sizeAfter > ( sizeBefore * 1.10 ) ) {
throw new Error ( "The lib folder increased by 10% or more. This likely indicates a bug." ) ;
2018-06-11 05:05:12 +02:00
} * /
2018-06-11 00:20:58 +02:00
} ) ;
// Test directory
directory ( builtLocalDirectory ) ;
var internalTests = "internal/" ;
var localBaseline = "tests/baselines/local/" ;
var refBaseline = "tests/baselines/reference/" ;
var localRwcBaseline = path . join ( internalTests , "baselines/rwc/local" ) ;
var refRwcBaseline = path . join ( internalTests , "baselines/rwc/reference" ) ;
var localTest262Baseline = path . join ( internalTests , "baselines/test262/local" ) ;
var refTest262Baseline = path . join ( internalTests , "baselines/test262/reference" ) ;
desc ( "Builds the test infrastructure using the built compiler" ) ;
task ( "tests" , [ "local" , run ] . concat ( libraryTargets ) ) ;
function exec ( cmd , completeHandler , errorHandler ) {
var ex = jake . createExec ( [ cmd ] , /** @type {jake.ExecOptions} */ ( { windowsVerbatimArguments : true , interactive : true } ) ) ;
// Add listeners for output and error
ex . addListener ( "stdout" , function ( output ) {
process . stdout . write ( output ) ;
} ) ;
ex . addListener ( "stderr" , function ( error ) {
process . stderr . write ( error ) ;
} ) ;
ex . addListener ( "cmdEnd" , function ( ) {
if ( completeHandler ) {
completeHandler ( ) ;
}
complete ( ) ;
} ) ;
ex . addListener ( "error" , function ( e , status ) {
if ( errorHandler ) {
errorHandler ( e , status ) ;
}
else {
fail ( "Process exited with code " + status ) ;
}
} ) ;
ex . run ( ) ;
}
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
const del = require ( "del" ) ;
function cleanTestDirs() {
// Clean the local baselines directory
if ( fs . existsSync ( localBaseline ) ) {
del . sync ( localBaseline ) ;
}
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
// Clean the local Rwc baselines directory
if ( fs . existsSync ( localRwcBaseline ) ) {
del . sync ( localRwcBaseline ) ;
}
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
jake . mkdirP ( localRwcBaseline ) ;
jake . mkdirP ( localTest262Baseline ) ;
jake . mkdirP ( localBaseline ) ;
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
// used to pass data from jake command line directly to run.js
function writeTestConfigFile ( tests , runners , light , taskConfigsFolder , workerCount , stackTraceLimit , colors , testTimeout ) {
var testConfigContents = JSON . stringify ( {
runners : runners ? runners . split ( "," ) : undefined ,
test : tests ? [ tests ] : undefined ,
light : light ,
workerCount : workerCount ,
taskConfigsFolder : taskConfigsFolder ,
stackTraceLimit : stackTraceLimit ,
noColor : ! colors ,
timeout : testTimeout
2018-06-10 19:58:16 +02:00
} ) ;
2018-06-11 00:20:58 +02:00
fs . writeFileSync ( 'test.config' , testConfigContents ) ;
}
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
function deleteTemporaryProjectOutput() {
if ( fs . existsSync ( path . join ( localBaseline , "projectOutput/" ) ) ) {
jake . rmRf ( path . join ( localBaseline , "projectOutput/" ) ) ;
2018-06-10 19:58:16 +02:00
}
}
2016-05-24 01:00:56 +02:00
function runConsoleTests ( defaultReporter , runInParallel ) {
2016-06-07 19:32:03 +02:00
var dirty = process . env . dirty ;
2016-04-13 03:40:39 +02:00
if ( ! dirty ) {
cleanTestDirs ( ) ;
}
2017-06-08 21:24:20 +02:00
var debug = process . env . debug || process . env [ "debug-brk" ] || process . env . d ;
var inspect = process . env . inspect || process . env [ "inspect-brk" ] || process . env . i ;
2017-06-06 22:33:19 +02:00
var testTimeout = process . env . timeout || defaultTestTimeout ;
2017-11-06 20:24:17 +01:00
var runners = process . env . runners || process . env . runner || process . env . ru ;
2017-06-06 22:33:19 +02:00
var tests = process . env . test || process . env . tests || process . env . t ;
2017-10-20 02:15:54 +02:00
var light = process . env . light === undefined || process . env . light !== "false" ;
2016-06-07 19:32:03 +02:00
var stackTraceLimit = process . env . stackTraceLimit ;
2014-07-13 01:04:16 +02:00
var testConfigFile = 'test.config' ;
2016-08-19 23:34:14 +02:00
if ( fs . existsSync ( testConfigFile ) ) {
2014-07-13 01:04:16 +02:00
fs . unlinkSync ( testConfigFile ) ;
}
2016-05-24 01:00:56 +02:00
var workerCount , taskConfigsFolder ;
if ( runInParallel ) {
// generate name to store task configuration files
var prefix = os . tmpdir ( ) + "/ts-tests" ;
var i = 1 ;
do {
taskConfigsFolder = prefix + i ;
i ++ ;
} while ( fs . existsSync ( taskConfigsFolder ) ) ;
fs . mkdirSync ( taskConfigsFolder ) ;
2017-06-06 22:33:19 +02:00
workerCount = process . env . workerCount || process . env . p || os . cpus ( ) . length ;
2016-05-24 01:00:56 +02:00
}
2014-09-03 19:37:32 +02:00
if ( tests && tests . toLocaleLowerCase ( ) === "rwc" ) {
2016-11-22 02:25:38 +01:00
testTimeout = 800000 ;
2014-09-03 19:37:32 +02:00
}
2018-01-08 21:28:04 +01:00
if ( tests || runners || light || testTimeout || taskConfigsFolder ) {
writeTestConfigFile ( tests , runners , light , taskConfigsFolder , workerCount , stackTraceLimit , colors , testTimeout ) ;
}
2017-07-25 23:35:22 +02:00
var colorsFlag = process . env . color || process . env . colors ;
var colors = colorsFlag !== "false" && colorsFlag !== "0" ;
2017-02-07 23:36:15 +01:00
var reporter = process . env . reporter || process . env . r || defaultReporter ;
var bail = process . env . bail || process . env . b ;
2016-05-16 20:53:44 +02:00
var lintFlag = process . env . lint !== 'false' ;
2015-10-26 18:25:01 +01:00
2014-07-26 02:01:01 +02:00
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
2016-08-19 23:34:14 +02:00
if ( ! runInParallel ) {
2018-06-11 00:20:58 +02:00
var startTime = mark ( ) ;
2017-02-07 23:36:15 +01:00
var args = [ ] ;
args . push ( "-R" , reporter ) ;
if ( tests ) {
args . push ( "-g" , ` " ${ tests } " ` ) ;
}
if ( colors ) {
args . push ( "--colors" ) ;
}
else {
args . push ( "--no-colors" ) ;
}
if ( bail ) {
args . push ( "--bail" ) ;
}
2017-06-08 21:24:20 +02:00
if ( inspect ) {
args . unshift ( "--inspect-brk" ) ;
}
else if ( debug ) {
args . unshift ( "--debug-brk" ) ;
}
else {
args . push ( "-t" , testTimeout ) ;
}
2018-06-11 00:20:58 +02:00
args . push ( run ) ;
2017-02-07 23:36:15 +01:00
var cmd = "mocha " + args . join ( " " ) ;
2015-10-24 01:27:44 +02:00
console . log ( cmd ) ;
2016-06-10 07:07:07 +02:00
var savedNodeEnv = process . env . NODE_ENV ;
process . env . NODE_ENV = "development" ;
2016-05-20 22:40:34 +02:00
exec ( cmd , function ( ) {
2016-06-10 07:07:07 +02:00
process . env . NODE_ENV = savedNodeEnv ;
2018-06-11 00:20:58 +02:00
measure ( startTime ) ;
2016-05-24 23:29:52 +02:00
runLinter ( ) ;
2016-05-20 22:40:34 +02:00
finish ( ) ;
2016-08-19 23:34:14 +02:00
} , function ( e , status ) {
2016-06-10 07:07:07 +02:00
process . env . NODE_ENV = savedNodeEnv ;
2018-06-11 00:20:58 +02:00
measure ( startTime ) ;
2016-05-26 01:23:51 +02:00
finish ( status ) ;
} ) ;
2018-06-11 00:20:58 +02:00
2016-05-24 01:00:56 +02:00
}
else {
2016-06-10 07:07:07 +02:00
var savedNodeEnv = process . env . NODE_ENV ;
process . env . NODE_ENV = "development" ;
2018-06-11 00:20:58 +02:00
var startTime = mark ( ) ;
exec ( host + " " + run , function ( ) {
2016-06-10 07:07:07 +02:00
process . env . NODE_ENV = savedNodeEnv ;
2018-06-11 00:20:58 +02:00
measure ( startTime ) ;
runLinter ( ) ;
2017-09-15 00:42:06 +02:00
finish ( ) ;
} , function ( e , status ) {
process . env . NODE_ENV = savedNodeEnv ;
2018-06-11 00:20:58 +02:00
measure ( startTime ) ;
2017-09-15 00:42:06 +02:00
finish ( status ) ;
2016-05-24 01:00:56 +02:00
} ) ;
}
2016-06-06 20:37:59 +02:00
2016-05-26 01:23:51 +02:00
function failWithStatus ( status ) {
fail ( "Process exited with code " + status ) ;
}
2016-06-06 20:37:59 +02:00
2016-05-26 01:23:51 +02:00
function finish ( errorStatus ) {
2016-05-24 01:00:56 +02:00
deleteTemporaryProjectOutput ( ) ;
2016-05-26 01:23:51 +02:00
if ( errorStatus !== undefined ) {
failWithStatus ( errorStatus ) ;
2016-05-20 22:40:34 +02:00
}
2016-05-26 01:23:51 +02:00
else {
complete ( ) ;
}
2016-05-24 01:00:56 +02:00
}
function runLinter() {
2016-06-01 03:43:51 +02:00
if ( ! lintFlag || dirty ) {
2016-05-24 01:00:56 +02:00
return ;
}
var lint = jake . Task [ 'lint' ] ;
lint . addListener ( 'complete' , function ( ) {
complete ( ) ;
} ) ;
lint . invoke ( ) ;
}
2018-06-10 19:59:03 +02:00
}
2014-07-13 01:04:16 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true." ) ;
2018-06-11 04:28:38 +02:00
task ( "runtests-parallel" , [ "build-rules" , "tests" , builtLocalDirectory , run ] , function ( ) {
2018-06-11 00:20:58 +02:00
runConsoleTests ( 'min' , /*runInParallel*/ true ) ;
} , { async : true } ) ;
2014-09-02 21:19:58 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Runs the tests using the built run.js file. Optional arguments are: t[ests]=regex r[eporter]=[list|spec|json|<more>] d[ebug]=true color[s]=false lint=true bail=false dirty=false." ) ;
2018-06-11 04:28:38 +02:00
task ( "runtests" , [ "build-rules" , "tests" , builtLocalDirectory , run ] , function ( ) {
2018-06-11 00:20:58 +02:00
runConsoleTests ( 'mocha-fivemat-progress-reporter' , /*runInParallel*/ false ) ;
} , { async : true } ) ;
2014-09-02 21:19:58 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Generates code coverage data via instanbul" ) ;
task ( "generate-code-coverage" , [ "tests" , builtLocalDirectory ] , function ( ) {
var testTimeout = process . env . timeout || defaultTestTimeout ;
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-10 01:48:08 +02:00
2018-06-11 00:20:58 +02:00
// Browser tests
var nodeServerOutFile = "tests/webTestServer.js" ;
var nodeServerInFile = "tests/webTestServer.ts" ;
compileFile ( nodeServerOutFile , [ nodeServerInFile ] , [ builtLocalDirectory , tscFile ] , [ ] , /*useBuiltCompiler:*/ true , { noOutFile : true , lib : "es6" } ) ;
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Runs browserify on run.js to produce a file suitable for running tests in the browser" ) ;
2018-06-11 04:28:38 +02:00
task ( "browserify" , [ ] , function ( ) {
2018-06-11 00:20:58 +02:00
// Shell out to `gulp`, since we do the work to handle sourcemaps correctly w/o inline maps there
var cmd = 'gulp browserify --silent' ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-10 22:23:16 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], browser=[chrome|IE]" ) ;
task ( "runtests-browser" , [ "browserify" , nodeServerOutFile ] , function ( ) {
cleanTestDirs ( ) ;
host = "node" ;
2018-06-11 04:28:38 +02:00
var browser = process . env . browser || process . env . b || ( os . platform ( ) === "win32" ? "edge" : "chrome" ) ;
2018-06-11 00:20:58 +02:00
var runners = process . env . runners || process . env . runner || process . env . ru ;
var tests = process . env . test || process . env . tests || process . env . t ;
var light = process . env . light || false ;
var testConfigFile = 'test.config' ;
if ( fs . existsSync ( testConfigFile ) ) {
fs . unlinkSync ( testConfigFile ) ;
}
if ( tests || runners || light ) {
writeTestConfigFile ( tests , runners , light ) ;
2018-06-10 22:23:16 +02:00
}
2018-06-10 19:59:03 +02:00
2018-06-11 00:20:58 +02:00
tests = tests ? tests : '' ;
var cmd = host + " tests/webTestServer.js " + browser + " " + JSON . stringify ( tests ) ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
function getDiffTool() {
var program = process . env [ 'DIFF' ] ;
if ( ! program ) {
fail ( "Add the 'DIFF' environment variable to the path of the program you want to use." ) ;
}
return program ;
2018-06-10 22:23:16 +02:00
}
2016-08-11 18:53:38 +02:00
2018-06-11 00:20:58 +02:00
// Baseline Diff
desc ( "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable" ) ;
task ( 'diff' , function ( ) {
var cmd = '"' + getDiffTool ( ) + '" ' + refBaseline + ' ' + localBaseline ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-10 22:23:16 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable" ) ;
task ( 'diff-rwc' , function ( ) {
var cmd = '"' + getDiffTool ( ) + '" ' + refRwcBaseline + ' ' + localRwcBaseline ;
console . log ( cmd ) ;
exec ( cmd ) ;
} , { async : true } ) ;
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Builds the test sources and automation in debug mode" ) ;
task ( "tests-debug" , [ "setDebugMode" , "tests" ] ) ;
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
// Makes the test results the new baseline
desc ( "Makes the most recent test results the new baseline, overwriting the old baseline" ) ;
task ( "baseline-accept" , function ( ) {
acceptBaseline ( localBaseline , refBaseline ) ;
} ) ;
2018-06-10 19:58:16 +02:00
2018-06-10 22:26:16 +02:00
function acceptBaseline ( sourceFolder , targetFolder ) {
console . log ( 'Accept baselines from ' + sourceFolder + ' to ' + targetFolder ) ;
var deleteEnding = '.delete' ;
acceptBaselineFolder ( sourceFolder , targetFolder ) ;
function acceptBaselineFolder ( sourceFolder , targetFolder ) {
var files = fs . readdirSync ( sourceFolder ) ;
for ( var i in files ) {
var filename = files [ i ] ;
var fullLocalPath = path . join ( sourceFolder , filename ) ;
var stat = fs . statSync ( fullLocalPath ) ;
if ( stat . isFile ( ) ) {
if ( filename . substr ( filename . length - deleteEnding . length ) === deleteEnding ) {
filename = filename . substr ( 0 , filename . length - deleteEnding . length ) ;
fs . unlinkSync ( path . join ( targetFolder , filename ) ) ;
}
else {
var target = path . join ( targetFolder , filename ) ;
if ( fs . existsSync ( target ) ) {
fs . unlinkSync ( target ) ;
}
jake . mkdirP ( path . dirname ( target ) ) ;
fs . renameSync ( path . join ( sourceFolder , filename ) , target ) ;
}
}
else if ( stat . isDirectory ( ) ) {
acceptBaselineFolder ( fullLocalPath , path . join ( targetFolder , filename ) ) ;
}
}
}
}
2018-06-11 00:20:58 +02:00
desc ( "Makes the most recent rwc test results the new baseline, overwriting the old baseline" ) ;
task ( "baseline-accept-rwc" , function ( ) {
acceptBaseline ( localRwcBaseline , refRwcBaseline ) ;
} ) ;
2018-06-10 19:58:16 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Makes the most recent test262 test results the new baseline, overwriting the old baseline" ) ;
task ( "baseline-accept-test262" , function ( ) {
acceptBaseline ( localTest262Baseline , refTest262Baseline ) ;
} ) ;
2018-06-10 22:23:16 +02:00
2018-06-10 23:56:48 +02:00
2018-06-11 00:20:58 +02:00
// Webhost
var webhostPath = "tests/webhost/webtsc.ts" ;
var webhostJsPath = "tests/webhost/webtsc.js" ;
compileFile ( webhostJsPath , [ webhostPath ] , [ tscFile , webhostPath ] . concat ( libraryTargets ) , [ ] , /*useBuiltCompiler*/ true ) ;
2018-06-10 23:56:48 +02:00
2018-06-11 00:20:58 +02:00
desc ( "Builds the tsc web host" ) ;
task ( "webhost" , [ webhostJsPath ] , function ( ) {
jake . cpR ( path . join ( builtLocalDirectory , "lib.d.ts" ) , "tests/webhost/" , { silent : true } ) ;
} ) ;
// Perf compiler
var perftscPath = "tests/perftsc.ts" ;
var perftscJsPath = "built/local/perftsc.js" ;
compileFile ( perftscJsPath , [ perftscPath ] , [ tscFile , perftscPath , "tests/perfsys.ts" ] . concat ( libraryTargets ) , [ ] , /*useBuiltCompiler*/ true ) ;
desc ( "Builds augmented version of the compiler for perf tests" ) ;
task ( "perftsc" , [ perftscJsPath ] ) ;
// Instrumented compiler
var loggedIOpath = harnessDirectory + 'loggedIO.ts' ;
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js' ;
file ( loggedIOJsPath , [ builtLocalDirectory , loggedIOpath ] , function ( ) {
var temp = builtLocalDirectory + 'temp' ;
jake . mkdirP ( temp ) ;
var options = "--target es5 --lib es6 --types --outdir " + temp + ' ' + loggedIOpath ;
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " " ;
console . log ( cmd + "\n" ) ;
var ex = jake . createExec ( [ cmd ] ) ;
ex . addListener ( "cmdEnd" , function ( ) {
fs . renameSync ( temp + '/harness/loggedIO.js' , loggedIOJsPath ) ;
jake . rmRf ( temp ) ;
complete ( ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
var instrumenterPath = harnessDirectory + 'instrumenter.ts' ;
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js' ;
compileFile ( instrumenterJsPath , [ instrumenterPath ] , [ tscFile , instrumenterPath ] . concat ( libraryTargets ) , [ ] , /*useBuiltCompiler*/ true , { lib : "es6" , types : [ "node" ] , noOutFile : true , outDir : builtLocalDirectory } ) ;
desc ( "Builds an instrumented tsc.js - run with test=[testname]" ) ;
task ( 'tsc-instrumented' , [ loggedIOJsPath , instrumenterJsPath , tscFile ] , function ( ) {
var test = process . env . test || process . env . tests || process . env . t || "iocapture" ;
var cmd = host + ' ' + instrumenterJsPath + " record " + test + " " + builtLocalDirectory + compilerFilename ;
console . log ( cmd ) ;
var ex = jake . createExec ( [ cmd ] ) ;
ex . addListener ( "cmdEnd" , function ( ) {
complete ( ) ;
} ) ;
ex . run ( ) ;
} , { async : true } ) ;
desc ( "Updates the sublime plugin's tsserver" ) ;
task ( "update-sublime" , [ "local" , serverFile ] , function ( ) {
jake . cpR ( serverFile , "../TypeScript-Sublime-Plugin/tsserver/" ) ;
jake . cpR ( serverFile + ".map" , "../TypeScript-Sublime-Plugin/tsserver/" ) ;
} ) ;
var tslintRuleDir = "scripts/tslint/rules" ;
var tslintRules = fs . readdirSync ( tslintRuleDir ) ;
var tslintRulesFiles = tslintRules . map ( function ( p ) {
return path . join ( tslintRuleDir , p ) ;
} ) ;
var tslintRulesOutFiles = tslintRules . map ( function ( p ) {
return path . join ( builtLocalDirectory , "tslint/rules" , p . replace ( ".ts" , ".js" ) ) ;
} ) ;
var tslintFormattersDir = "scripts/tslint/formatters" ;
var tslintFormatters = [
"autolinkableStylishFormatter" ,
] ;
var tslintFormatterFiles = tslintFormatters . map ( function ( p ) {
return path . join ( tslintFormattersDir , p + ".ts" ) ;
} ) ;
var tslintFormattersOutFiles = tslintFormatters . map ( function ( p ) {
return path . join ( builtLocalDirectory , "tslint/formatters" , p + ".js" ) ;
} ) ;
desc ( "Compiles tslint rules to js" ) ;
task ( "build-rules" , [ "build-rules-start" ] . concat ( tslintRulesOutFiles ) . concat ( tslintFormattersOutFiles ) . concat ( [ "build-rules-end" ] ) ) ;
tslintRulesFiles . forEach ( function ( ruleFile , i ) {
compileFile ( tslintRulesOutFiles [ i ] , [ ruleFile ] , [ ruleFile ] , [ ] , /*useBuiltCompiler*/ false ,
{ noOutFile : true , generateDeclarations : false , outDir : path.join ( builtLocalDirectory , "tslint/rules" ) , lib : "es6" } ) ;
} ) ;
tslintFormatterFiles . forEach ( function ( ruleFile , i ) {
compileFile ( tslintFormattersOutFiles [ i ] , [ ruleFile ] , [ ruleFile ] , [ ] , /*useBuiltCompiler*/ false ,
{ noOutFile : true , generateDeclarations : false , outDir : path.join ( builtLocalDirectory , "tslint/formatters" ) , lib : "es6" } ) ;
} ) ;
desc ( "Emit the start of the build-rules fold" ) ;
task ( "build-rules-start" , [ ] , function ( ) {
if ( fold . isTravis ( ) ) console . log ( fold . start ( "build-rules" ) ) ;
} ) ;
desc ( "Emit the end of the build-rules fold" ) ;
task ( "build-rules-end" , [ ] , function ( ) {
if ( fold . isTravis ( ) ) console . log ( fold . end ( "build-rules" ) ) ;
} ) ;
desc ( "Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex" ) ;
task ( "lint" , [ "build-rules" ] , ( ) = > {
if ( fold . isTravis ( ) ) console . log ( fold . start ( "lint" ) ) ;
function lint ( project , cb ) {
const fix = process . env . fix || process . env . f ;
const cmd = ` node node_modules/tslint/bin/tslint --project ${ project } --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish ${ fix ? " --fix" : "" } ` ;
console . log ( "Linting: " + cmd ) ;
jake . exec ( [ cmd ] , cb , /** @type {jake.ExecOptions} */ ( { interactive : true , windowsVerbatimArguments : true } ) ) ;
}
lint ( "scripts/tslint/tsconfig.json" , ( ) = > lint ( "src/tsconfig-base.json" , ( ) = > {
if ( fold . isTravis ( ) ) console . log ( fold . end ( "lint" ) ) ;
complete ( ) ;
} ) ) ;
} ) ;