diff --git a/Gulpfile.js b/Gulpfile.js index 09dd06f398..3de5e5150a 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -22,6 +22,7 @@ const through2 = require("through2"); const merge2 = require("merge2"); const os = require("os"); const fold = require("travis-fold"); +const ts = require("./lib/typescript"); const gulp = helpMaker(originalGulp); Error.stackTraceLimit = 1000; @@ -66,10 +67,10 @@ const cmdLineOptions = minimist(process.argv.slice(2), { const noop = () => {}; // tslint:disable-line no-empty /** - * @param {string} cmd - * @param {string[]} args - * @param {() => void} complete - * @param {(e: *, status: number) => void} error + * @param {string} cmd + * @param {string[]} args + * @param {() => void} complete + * @param {(e: *, status: number) => void} error */ function exec(cmd, args, complete = noop, error = noop) { console.log(`${cmd} ${args.join(" ")}`); @@ -82,12 +83,42 @@ function exec(cmd, args, complete = noop, error = noop) { } /** - * @param {string} cmd + * @param {string} cmd */ function possiblyQuote(cmd) { return cmd.indexOf(" ") >= 0 ? `"${cmd}"` : cmd; } +/** + * @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); +} + +/** @param diagnostics {ts.Diagnostic[]} */ +function reportDiagnostics(diagnostics) { + console.log(diagnosticsToString(diagnostics, process.stdout.isTTY)); +} + +/** @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; +} + let useDebugMode = true; let host = cmdLineOptions.host; @@ -113,81 +144,8 @@ const nodeModulesPathPrefix = path.resolve("./node_modules/.bin/"); const isWin = /^win/.test(process.platform); const mocha = path.join(nodeModulesPathPrefix, "mocha") + (isWin ? ".cmd" : ""); -const es2015LibrarySources = [ - "es2015.core.d.ts", - "es2015.collection.d.ts", - "es2015.generator.d.ts", - "es2015.iterable.d.ts", - "es2015.promise.d.ts", - "es2015.proxy.d.ts", - "es2015.reflect.d.ts", - "es2015.symbol.d.ts", - "es2015.symbol.wellknown.d.ts" -]; - -const es2015LibrarySourceMap = es2015LibrarySources.map(source => - ({ target: "lib." + source, sources: ["header.d.ts", source] })); - -const es2016LibrarySource = ["es2016.array.include.d.ts"]; - -const es2016LibrarySourceMap = es2016LibrarySource.map(source => - ({ target: "lib." + source, sources: ["header.d.ts", source] })); - -const es2017LibrarySource = [ - "es2017.object.d.ts", - "es2017.sharedmemory.d.ts", - "es2017.string.d.ts", - "es2017.intl.d.ts", - "es2017.typedarrays.d.ts", -]; - -const es2017LibrarySourceMap = es2017LibrarySource.map(source => - ({ target: "lib." + source, sources: ["header.d.ts", source] })); - -const es2018LibrarySource = [ - "es2018.regexp.d.ts", - "es2018.promise.d.ts", - "es2018.intl.d.ts" -]; -const es2018LibrarySourceMap = es2018LibrarySource.map(source => - ({ target: "lib." + source, sources: ["header.d.ts", source] })); - -const esnextLibrarySource = [ - "esnext.asynciterable.d.ts", - "esnext.array.d.ts" -]; - -const esnextLibrarySourceMap = esnextLibrarySource.map(source => - ({ target: "lib." + source, sources: ["header.d.ts", source] })); - -const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"]; - -const librarySourceMap = [ - // Host library - { target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] }, - { target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] }, - { target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] }, - { target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] }, - - // JavaScript library - { target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] }, - { target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] }, - { target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] }, - { target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] }, - { target: "lib.es2018.d.ts", sources: ["header.d.ts", "es2018.d.ts"] }, - { target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] }, - - // JavaScript + all host library - { target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) }, - { target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2018.full.d.ts", sources: ["header.d.ts", "es2018.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, -].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, es2018LibrarySourceMap, esnextLibrarySourceMap); - -const libraryTargets = librarySourceMap.map(f => - path.join(builtLocalDirectory, f.target)); +/** @type {{ libs: string[], paths?: Record, sources?: Record }} */ +const libraries = readJson("./src/lib/libs.json"); /** * .lcg file is what localization team uses to know what messages to localize. @@ -206,16 +164,18 @@ const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt .map(f => path.join(builtLocalDirectory, f, "diagnosticMessages.generated.json")) .concat(generatedLCGFile); -for (const i in libraryTargets) { - const entry = librarySourceMap[i]; - const target = libraryTargets[i]; - const sources = [copyright].concat(entry.sources.map(s => path.join(libraryDirectory, s))); +const libraryTargets = libraries.libs.map(lib => { + const relativeSources = ["header.d.ts"].concat(libraries.sources && libraries.sources[lib] || [lib + ".d.ts"]); + const relativeTarget = libraries.paths && libraries.paths[lib] || ("lib." + lib + ".d.ts"); + const sources = [copyright].concat(relativeSources.map(s => path.join(libraryDirectory, s))); + const target = path.join(builtLocalDirectory, relativeTarget); gulp.task(target, /*help*/ false, [], () => gulp.src(sources) .pipe(newer(target)) .pipe(concat(target, { newLine: "\n\n" })) .pipe(gulp.dest("."))); -} + return target; +}); const configurePreleleaseJs = path.join(scriptsDirectory, "configurePrerelease.js"); const configurePreleleaseTs = path.join(scriptsDirectory, "configurePrerelease.ts"); @@ -223,8 +183,8 @@ const packageJson = "package.json"; const versionFile = path.join(compilerDirectory, "core.ts"); /** - * @param {string | string[]} source - * @param {string | string[]} dest + * @param {string | string[]} source + * @param {string | string[]} dest * @returns {boolean} */ function needsUpdate(source, dest) { @@ -291,7 +251,7 @@ function needsUpdate(source, dest) { } /** - * @param {tsc.Settings} base + * @param {tsc.Settings} base * @param {boolean=} useBuiltCompiler * @returns {tsc.Settings} */ @@ -443,7 +403,7 @@ const nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript /** @type {string} */ let copyrightContent; /** - * @param {boolean} outputCopyright + * @param {boolean} outputCopyright */ function prependCopyright(outputCopyright = !useDebugMode) { return insert.prepend(outputCopyright ? (copyrightContent || (copyrightContent = fs.readFileSync(copyright).toString())) : ""); @@ -667,9 +627,9 @@ function restoreSavedNodeEnv() { } /** - * @param {string} defaultReporter - * @param {boolean} runInParallel - * @param {(e?: any) => void} done + * @param {string} defaultReporter + * @param {boolean} runInParallel + * @param {(e?: any) => void} done */ function runConsoleTests(defaultReporter, runInParallel, done) { const lintFlag = cmdLineOptions.lint; @@ -747,8 +707,8 @@ function runConsoleTests(defaultReporter, runInParallel, done) { }); /** - * @param {any=} err - * @param {number=} status + * @param {any=} err + * @param {number=} status */ function failWithStatus(err, status) { if (err || status) { @@ -767,8 +727,8 @@ function runConsoleTests(defaultReporter, runInParallel, done) { } /** - * @param {any=} error - * @param {number=} errorStatus + * @param {any=} error + * @param {number=} errorStatus */ function finish(error, errorStatus) { restoreSavedNodeEnv(); @@ -886,7 +846,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo }); /** - * @param {(e?: any) => void} done + * @param {(e?: any) => void} done */ function cleanTestDirs(done) { // Clean the local baselines & Rwc baselines directories @@ -906,13 +866,13 @@ function cleanTestDirs(done) { /** * used to pass data from jake command line directly to run.js - * @param {string} tests - * @param {string} runners - * @param {boolean} light - * @param {string=} taskConfigsFolder - * @param {number=} workerCount - * @param {string=} stackTraceLimit - * @param {number=} timeout + * @param {string} tests + * @param {string} runners + * @param {boolean} light + * @param {string=} taskConfigsFolder + * @param {number=} workerCount + * @param {string=} stackTraceLimit + * @param {number=} timeout */ function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout) { const testConfigContents = JSON.stringify({ diff --git a/Jakefile.js b/Jakefile.js index 4596352530..3a50a6ee11 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -36,22 +36,45 @@ else if (process.env.PATH !== undefined) { process.env.PATH = nodeModulesPathPrefix + process.env.PATH; } +/** + * @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); +} + +/** @param diagnostics {ts.Diagnostic[]} */ +function reportDiagnostics(diagnostics) { + console.log(diagnosticsToString(diagnostics, process.stdout.isTTY)); +} + +/** @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; +} + +/** @param configPath {string} */ function filesFromConfig(configPath) { - var configText = fs.readFileSync(configPath).toString(); - var config = ts.parseConfigFileTextToJson(configPath, configText); - if (config.error) { - throw new Error(diagnosticsToString([config.error])); - } - const configFileContent = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath)); + const config = readJson(configPath); + const configFileContent = ts.parseJsonConfigFileContent(config, ts.sys, path.dirname(configPath)); if (configFileContent.errors && configFileContent.errors.length) { - throw new Error(diagnosticsToString(configFileContent.errors)); + reportDiagnostics(configFileContent.errors); + throw new Error("An error occurred during parse."); } - return configFileContent.fileNames; - - function diagnosticsToString(s) { - return s.map(function(e) { return ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine); }).join(ts.sys.newLine); - } } function toNs(diff) { @@ -91,88 +114,8 @@ var harnessSources = filesFromConfig("./src/harness/tsconfig.json"); var typesMapOutputPath = path.join(builtLocalDirectory, 'typesMap.json'); -var es2015LibrarySources = [ - "es2015.core.d.ts", - "es2015.collection.d.ts", - "es2015.generator.d.ts", - "es2015.iterable.d.ts", - "es2015.promise.d.ts", - "es2015.proxy.d.ts", - "es2015.reflect.d.ts", - "es2015.symbol.d.ts", - "es2015.symbol.wellknown.d.ts" -]; - -var es2015LibrarySourceMap = es2015LibrarySources.map(function (source) { - return { target: "lib." + source, sources: ["header.d.ts", source] }; -}); - -var es2016LibrarySource = ["es2016.array.include.d.ts"]; - -var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) { - return { target: "lib." + source, sources: ["header.d.ts", source] }; -}); - -var es2017LibrarySource = [ - "es2017.object.d.ts", - "es2017.sharedmemory.d.ts", - "es2017.string.d.ts", - "es2017.intl.d.ts", - "es2017.typedarrays.d.ts", -]; - -var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) { - return { target: "lib." + source, sources: ["header.d.ts", source] }; -}); - -var es2018LibrarySource = [ - "es2018.regexp.d.ts", - "es2018.promise.d.ts", - "es2018.intl.d.ts" -]; - -var es2018LibrarySourceMap = es2018LibrarySource.map(function (source) { - return { target: "lib." + source, sources: ["header.d.ts", source] }; -}); - -var esnextLibrarySource = [ - "esnext.asynciterable.d.ts", - "esnext.array.d.ts" -]; - -var esnextLibrarySourceMap = esnextLibrarySource.map(function (source) { - return { target: "lib." + source, sources: ["header.d.ts", source] }; -}); - -var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"]; - -var librarySourceMap = [ - // Host library - { target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] }, - { target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] }, - { target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] }, - { target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] }, - - // JavaScript library - { target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] }, - { target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] }, - { target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] }, - { target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] }, - { target: "lib.es2018.d.ts", sources: ["header.d.ts", "es2018.d.ts"] }, - { target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] }, - - // JavaScript + all host library - { target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) }, - { target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.es2018.full.d.ts", sources: ["header.d.ts", "es2018.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, - { target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") }, -].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, es2018LibrarySourceMap, esnextLibrarySourceMap); - -var libraryTargets = librarySourceMap.map(function (f) { - return path.join(builtLocalDirectory, f.target); -}); +/** @type {{ libs: string[], paths?: Record, sources?: Record }} */ +var libraries = readJson("./src/lib/libs.json"); /** * .lcg file is what localization team uses to know what messages to localize. @@ -348,18 +291,16 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts // Prerequisite task for built directory and library typings directory(builtLocalDirectory); -for (var i in libraryTargets) { - (function (i) { - var entry = librarySourceMap[i]; - var target = libraryTargets[i]; - var sources = [copyright].concat(entry.sources.map(function (s) { - return path.join(libraryDirectory, s); - })); - file(target, [builtLocalDirectory].concat(sources), function () { - concatenateFiles(target, sources); - }); - })(i); -} +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); + }); + return target; +}); // Lib target to build the library files desc("Builds the library targets"); diff --git a/src/lib/libs.json b/src/lib/libs.json new file mode 100644 index 0000000000..a7f7c445db --- /dev/null +++ b/src/lib/libs.json @@ -0,0 +1,101 @@ +{ + "libs": [ + // JavaScript only + "es5", + "es2015", + "es2016", + "es2017", + "es2018", + "esnext", + // Host only + "dom.generated", + "dom.iterable", + "webworker.generated", + "scripthost", + // By-feature options + "es2015.core", + "es2015.collection", + "es2015.generator", + "es2015.iterable", + "es2015.promise", + "es2015.proxy", + "es2015.reflect", + "es2015.symbol", + "es2015.symbol.wellknown", + "es2016.array.include", + "es2017.object", + "es2017.sharedmemory", + "es2017.string", + "es2017.intl", + "es2017.typedarrays", + "es2018.regexp", + "es2018.promise", + "es2018.intl", + "esnext.asynciterable", + "esnext.array", + // Default libraries + "es5.full", + "es2015.full", + "es2016.full", + "es2017.full", + "esnext.full" + ], + "paths": { + "dom.generated": "lib.dom.d.ts", + "webworker.generated": "lib.webworker.d.ts", + "es5.full": "lib.d.ts", + "es2015.full": "lib.es6.d.ts" + }, + "sources": { + "es5.full": [ + "es5.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts" + ], + "es2015.full": [ + "es5.d.ts", + "es2015.core.d.ts", + "es2015.collection.d.ts", + "es2015.generator.d.ts", + "es2015.iterable.d.ts", + "es2015.promise.d.ts", + "es2015.proxy.d.ts", + "es2015.reflect.d.ts", + "es2015.symbol.d.ts", + "es2015.symbol.wellknown.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts", + "dom.iterable.d.ts" + ], + "es2016.full": [ + "es2016.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts", + "dom.iterable.d.ts" + ], + "es2017.full": [ + "es2017.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts", + "dom.iterable.d.ts" + ], + "es2018.full": [ + "es2018.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts", + "dom.iterable.d.ts" + ], + "esnext.full": [ + "esnext.d.ts", + "dom.generated.d.ts", + "webworker.importscripts.d.ts", + "scripthost.d.ts", + "dom.iterable.d.ts" + ] + } +} \ No newline at end of file