diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 5711c8f950dfc..89da312503a22 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -16,7 +16,7 @@ Please fill in the *entire* template below. --> -**TypeScript Version:** 3.3.0-dev.201xxxxx +**TypeScript Version:** 3.4.0-dev.201xxxxx **Search Terms:** diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index daec1666314a7..7a0f12ce7ceaf 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,11 +2,9 @@ Thank you for submitting a pull request! Here's a checklist you might find useful. -* [ ] There is an associated issue that is labeled - 'Bug' or 'help wanted' or is in the Community milestone +* [ ] There is an associated issue that is labeled 'Bug' or 'help wanted' * [ ] Code is up-to-date with the `master` branch -* [ ] You've successfully run `jake runtests` locally -* [ ] You've signed the CLA +* [ ] You've successfully run `gulp runtests` locally * [ ] There are new or updated unit tests validating the change Refer to CONTRIBUTING.MD for more details. diff --git a/.mailmap b/.mailmap index 5b591eb4615c4..cb3334a940433 100644 --- a/.mailmap +++ b/.mailmap @@ -121,6 +121,7 @@ Ken Howard Kevin Lang kimamula # Kenji Imamula Kitson Kelly +Krishnadas Babu Klaus Meinhardt Kyle Kelley Lorant Pinter diff --git a/.npmignore b/.npmignore index 6054bfbdb3705..482633f48fc40 100644 --- a/.npmignore +++ b/.npmignore @@ -12,7 +12,11 @@ tests tslint.json Jakefile.js .editorconfig +.failed-tests +.git +.git/ .gitattributes +.github/ .gitmodules .settings/ .travis.yml @@ -23,6 +27,5 @@ Jakefile.js test.config package-lock.json yarn.lock -.github/ CONTRIBUTING.md TEST-results.xml diff --git a/.travis.yml b/.travis.yml index 0f720b7375e62..2124f3ada33a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,7 @@ language: node_js node_js: - 'node' - '10' - - '6' - -sudo: false + - '8' env: - workerCount=3 timeout=600000 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 683c47817b7eb..4b58cc2875a78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,6 +47,16 @@ In general, things we find useful when reviewing suggestions are: # Instructions for Contributing Code +## Tips + +### Faster clones + +The TypeScript repository is relatively large. To save some time, you might want to clone it without the repo's full history using `git clone --depth=1`. + +### Using local builds + +Run `gulp` to build a version of the compiler/language service that reflects changes you've made. You can then run `node /built/local/tsc.js` in place of `tsc` in your project. For example, to run `tsc --watch` from within the root of the repository on a file called `test.ts`, you can run `node ./built/local/tsc.js --watch test.ts`. + ## Contributing bug fixes TypeScript is currently accepting contributions in the form of bug fixes. A bug must have an issue tracking it in the issue tracker that has been approved ("Milestone == Community") by the TypeScript team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort. @@ -94,7 +104,7 @@ Any changes should be made to [src/lib](https://github.com/Microsoft/TypeScript/ Library files in `built/local/` are updated automatically by running the standard build task: ```sh -jake +gulp ``` The files in `lib/` are used to bootstrap compilation and usually **should not** be updated unless publishing a new version or updating the LKG. @@ -105,49 +115,49 @@ The files `src/lib/dom.generated.d.ts` and `src/lib/webworker.generated.d.ts` bo ## Running the Tests -To run all tests, invoke the `runtests-parallel` target using jake: +To run all tests, invoke the `runtests-parallel` target using gulp: ```Shell -jake runtests-parallel +gulp runtests-parallel ``` This will run all tests; to run only a specific subset of tests, use: ```Shell -jake runtests tests= +gulp runtests --tests= ``` e.g. to run all compiler baseline tests: ```Shell -jake runtests tests=compiler +gulp runtests --tests=compiler ``` or to run a specific test: `tests\cases\compiler\2dArrays.ts` ```Shell -jake runtests tests=2dArrays +gulp runtests --tests=2dArrays ``` ## Debugging the tests -To debug the tests, invoke the `runtests-browser` task from jake. +To debug the tests, invoke the `runtests-browser` task from gulp. You will probably only want to debug one test at a time: ```Shell -jake runtests-browser tests=2dArrays +gulp runtests-browser --tests=2dArrays ``` You can specify which browser to use for debugging. Currently Chrome and IE are supported: ```Shell -jake runtests-browser tests=2dArrays browser=chrome +gulp runtests-browser --tests=2dArrays --browser=chrome ``` -You can debug with VS Code or Node instead with `jake runtests inspect=true`: +You can debug with VS Code or Node instead with `gulp runtests --inspect=true`: ```Shell -jake runtests tests=2dArrays inspect=true +gulp runtests --tests=2dArrays --inspect=true ``` ## Adding a Test @@ -187,13 +197,13 @@ Compiler testcases generate baselines that track the emitted `.js`, the errors p When a change in the baselines is detected, the test will fail. To inspect changes vs the expected baselines, use ```Shell -jake diff +gulp diff ``` After verifying that the changes in the baselines are correct, run ```Shell -jake baseline-accept +gulp baseline-accept ``` to establish the new baselines as the desired behavior. This will change the files in `tests\baselines\reference`, which should be included as part of your commit. It's important to carefully validate changes in the baselines. @@ -201,6 +211,6 @@ to establish the new baselines as the desired behavior. This will change the fil ## Localization All strings the user may see are stored in [`diagnosticMessages.json`](./src/compiler/diagnosticMessages.json). -If you make changes to it, run `jake generate-diagnostics` to push them to the `Diagnostic` interface in `diagnosticInformationMap.generated.ts`. +If you make changes to it, run `gulp generate-diagnostics` to push them to the `Diagnostic` interface in `diagnosticInformationMap.generated.ts`. See [coding guidelines on diagnostic messages](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#diagnostic-messages). diff --git a/Gulpfile.js b/Gulpfile.js index 3616e25ee80af..582c07fef3eac 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,107 +1,69 @@ -/// // @ts-check const path = require("path"); -const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) const fs = require("fs"); -const child_process = require("child_process"); -const runSequence = require("run-sequence"); +const log = require("fancy-log"); const newer = require("gulp-newer"); -const insert = require("gulp-insert"); -const { append } = require("gulp-insert"); const sourcemaps = require("gulp-sourcemaps"); const del = require("del"); const fold = require("travis-fold"); const rename = require("gulp-rename"); -const mkdirp = require("./scripts/build/mkdirp"); -const gulp = require("./scripts/build/gulp"); -const getDirSize = require("./scripts/build/getDirSize"); -const project = require("./scripts/build/project"); -const replace = require("./scripts/build/replace"); -const convertConstEnums = require("./scripts/build/convertConstEnum"); -const needsUpdate = require("./scripts/build/needsUpdate"); -const getDiffTool = require("./scripts/build/getDiffTool"); -const baselineAccept = require("./scripts/build/baselineAccept"); +const concat = require("gulp-concat"); +const merge2 = require("merge2"); +const mkdirp = require("mkdirp"); +const { src, dest, task, parallel, series, watch } = require("gulp"); +const { append, transform } = require("gulp-insert"); +const { prependFile } = require("./scripts/build/prepend"); +const { exec, readJson, needsUpdate, getDiffTool, getDirSize, rm } = require("./scripts/build/utils"); +const { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); +const { buildProject, cleanProject, watchProject } = require("./scripts/build/projects"); const cmdLineOptions = require("./scripts/build/options"); -const exec = require("./scripts/build/exec"); -const browserify = require("./scripts/build/browserify"); -const prepend = require("./scripts/build/prepend"); -const { removeSourceMaps } = require("./scripts/build/sourcemaps"); -const { CancellationTokenSource, CancelError, delay, Semaphore } = require("prex"); -const { libraryTargets, generateLibs } = require("./scripts/build/lib"); -const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); - -Error.stackTraceLimit = 1000; - -// Constants -const host = cmdLineOptions.host; + const copyright = "CopyrightNotice.txt"; +const cleanTasks = []; + +const buildScripts = () => buildProject("scripts"); +const cleanScripts = () => cleanProject("scripts"); +cleanTasks.push(cleanScripts); + +const libraries = readJson("./src/lib/libs.json"); +const libs = 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 = relativeSources.map(s => path.posix.join("src/lib", s)); + const target = `built/local/${relativeTarget}`; + return { target, relativeTarget, sources }; +}); + +const generateLibs = () => { + return merge2(libs.map(({ sources, target, relativeTarget }) => + src([copyright, ...sources]) + .pipe(newer(target)) + .pipe(concat(relativeTarget, { newLine: "\n\n" })) + .pipe(dest("built/local")))); +}; +task("lib", generateLibs) +task("lib").description = "Builds the library targets"; + +const cleanLib = () => del(libs.map(lib => lib.target)); +cleanTasks.push(cleanLib); + +const watchLib = () => watch(["src/lib/**/*"], generateLibs); -project.addTypeScript("lkg", "./lib/typescript.js"); -project.addTypeScript("built", "./built/local/typescriptServices.js"); -project.addTypeScript("default", "lkg"); // Compile using the LKG compiler by default - -const scriptsProject = "scripts/tsconfig.json"; -const configurePrereleaseJs = "scripts/configurePrerelease.js"; -const processDiagnosticMessagesJs = "scripts/processDiagnosticMessages.js"; -const generateLocalizedDiagnosticMessagesJs = "scripts/generateLocalizedDiagnosticMessages.js"; -const buildProtocolJs = "scripts/buildProtocol.js"; -const produceLKGJs = "scripts/produceLKG.js"; -const word2mdJs = "scripts/word2md.js"; -const scriptsTaskAliases = [configurePrereleaseJs, processDiagnosticMessagesJs, generateLocalizedDiagnosticMessagesJs, produceLKGJs, buildProtocolJs, word2mdJs]; -gulp.task("scripts", /*help*/ false, () => project.compile(scriptsProject), { aliases: scriptsTaskAliases }); -gulp.task("clean:scripts", /*help*/ false, () => project.clean(scriptsProject), { aliases: scriptsTaskAliases.map(alias => `clean:${alias}`)}); - -// Nightly management tasks -gulp.task( - "configure-nightly", - "Runs scripts/configurePrerelease.ts to prepare a build for nightly publishing", - [configurePrereleaseJs], - () => exec(host, [configurePrereleaseJs, "dev", "package.json", "src/compiler/core.ts"])); - -gulp.task( - "publish-nightly", - "Runs `npm publish --tag next` to create a new nightly build on npm", - ["LKG"], - () => runSequence("clean", "runtests-parallel", - () => exec("npm", ["publish", "--tag", "next"]))); - -const importDefinitelyTypedTestsProject = "scripts/importDefinitelyTypedTests/tsconfig.json"; -const importDefinitelyTypedTestsJs = "scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js"; -gulp.task(importDefinitelyTypedTestsJs, /*help*/ false, () => project.compile(importDefinitelyTypedTestsProject)); -gulp.task(`clean:${importDefinitelyTypedTestsJs}`, /*help*/ false, () => project.clean(importDefinitelyTypedTestsProject)); - -gulp.task( - "importDefinitelyTypedTests", - "Runs scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.ts to copy DT's tests to the TS-internal RWC tests", - [importDefinitelyTypedTestsJs], - () => exec(host, [importDefinitelyTypedTestsJs, "./", "../DefinitelyTyped"])); - -gulp.task( - "lib", - "Builds the library targets", - () => generateLibs([copyright])); - -// The generated diagnostics map; built for the compiler and for the "generate-diagnostics" task const diagnosticInformationMapTs = "src/compiler/diagnosticInformationMap.generated.ts"; const diagnosticMessagesJson = "src/compiler/diagnosticMessages.json"; const diagnosticMessagesGeneratedJson = "src/compiler/diagnosticMessages.generated.json"; -gulp.task(diagnosticInformationMapTs, /*help*/ false, [processDiagnosticMessagesJs], () => { +const generateDiagnostics = async () => { if (needsUpdate(diagnosticMessagesJson, [diagnosticMessagesGeneratedJson, diagnosticInformationMapTs])) { - return exec(host, [processDiagnosticMessagesJs, diagnosticMessagesJson]); + await exec(process.execPath, ["scripts/processDiagnosticMessages.js", diagnosticMessagesJson]); } -}); -gulp.task(`clean:${diagnosticInformationMapTs}`, /*help*/ false, () => del([diagnosticInformationMapTs, diagnosticMessagesGeneratedJson])); +}; +task("generate-diagnostics", series(buildScripts, generateDiagnostics)); +task("generate-diagnostics").description = "Generates a diagnostic file in TypeScript based on an input JSON file"; -const builtGeneratedDiagnosticMessagesJson = "built/local/diagnosticMessages.generated.json"; -gulp.task(builtGeneratedDiagnosticMessagesJson, /*help*/ false, [diagnosticInformationMapTs], () => - gulp.src([diagnosticMessagesGeneratedJson], { base: "src/compiler" }) - .pipe(newer(builtGeneratedDiagnosticMessagesJson)) - .pipe(gulp.dest("built/local"))); +const cleanDiagnostics = () => del([diagnosticInformationMapTs, diagnosticMessagesGeneratedJson]); +cleanTasks.push(cleanDiagnostics); -gulp.task( - "generate-diagnostics", - "Generates a diagnostic file in TypeScript based on an input JSON file", - [diagnosticInformationMapTs]); +const watchDiagnostics = () => watch(["src/compiler/diagnosticMessages.json"], task("generate-diagnostics")); // Localize diagnostics /** @@ -122,178 +84,432 @@ const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt .map(f => `built/local/${f}/diagnosticMessages.generated.json`) .concat(generatedLCGFile); -gulp.task(generatedLCGFile, /*help*/ false, [generateLocalizedDiagnosticMessagesJs, diagnosticInformationMapTs], (done) => { +const localize = async () => { if (needsUpdate(diagnosticMessagesGeneratedJson, generatedLCGFile)) { - return exec(host, [generateLocalizedDiagnosticMessagesJs, "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true }); + return exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.js", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true }); } -}); +}; -gulp.task("localize", /*help*/ false, [generatedLCGFile]); - -const servicesProject = "src/services/tsconfig.json"; -const typescriptServicesProject = "built/local/typescriptServices.tsconfig.json"; -gulp.task(typescriptServicesProject, /*help*/ false, () => { - // NOTE: flatten services so that we can properly strip @internal - project.flatten(servicesProject, typescriptServicesProject, { - compilerOptions: { - "removeComments": false, - "stripInternal": true, - "declarationMap": false, - "outFile": "typescriptServices.out.js" // must align with same task in jakefile. We fix this name below. - } - }); -}); +// Pre-build steps when targeting the LKG compiler +const lkgPreBuild = parallel(generateLibs, series(buildScripts, generateDiagnostics)); -const typescriptServicesJs = "built/local/typescriptServices.js"; -const typescriptServicesDts = "built/local/typescriptServices.d.ts"; -gulp.task(typescriptServicesJs, /*help*/ false, ["lib", "generate-diagnostics", typescriptServicesProject], () => - project.compile(typescriptServicesProject, { - js: files => files - .pipe(prepend.file(copyright)) - .pipe(rename("typescriptServices.js")), - dts: files => files - .pipe(removeSourceMaps()) - .pipe(prepend.file(copyright)) - .pipe(convertConstEnums()) - .pipe(rename("typescriptServices.d.ts")) - }), - { aliases: [typescriptServicesDts] }); +const buildTsc = () => buildProject("src/tsc"); +task("tsc", series(lkgPreBuild, buildTsc)); +task("tsc").description = "Builds the command-line compiler"; + +const cleanTsc = () => cleanProject("src/tsc"); +cleanTasks.push(cleanTsc); +task("clean-tsc", cleanTsc); +task("clean-tsc").description = "Cleans outputs for the command-line compiler"; + +const watchTsc = () => watchProject("src/tsc"); +task("watch-tsc", series(lkgPreBuild, parallel(watchLib, watchDiagnostics, watchTsc))); +task("watch-tsc").description = "Watch for changes and rebuild the command-line compiler only."; + +// Pre-build steps when targeting the built/local compiler. +const localPreBuild = parallel(generateLibs, series(buildScripts, generateDiagnostics, buildTsc)); -const typescriptJs = "built/local/typescript.js"; -gulp.task(typescriptJs, /*help*/ false, [typescriptServicesJs], () => - gulp.src([typescriptServicesJs], { base: "built/local" }) - .pipe(newer(typescriptJs)) +// Pre-build steps to use based on supplied options. +const preBuild = cmdLineOptions.lkg ? lkgPreBuild : localPreBuild; + +const buildServices = (() => { + // build typescriptServices.out.js + const buildTypescriptServicesOut = () => buildProject("src/typescriptServices/tsconfig.json", cmdLineOptions); + + // create typescriptServices.js + const createTypescriptServicesJs = () => src("built/local/typescriptServices.out.js") + .pipe(newer("built/local/typescriptServices.js")) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(prependFile(copyright)) + .pipe(rename("typescriptServices.js")) + .pipe(sourcemaps.write(".", { includeContent: false, destPath: "built/local" })) + .pipe(dest("built/local")); + + // create typescriptServices.d.ts + const createTypescriptServicesDts = () => src("built/local/typescriptServices.out.d.ts") + .pipe(newer("built/local/typescriptServices.d.ts")) + .pipe(prependFile(copyright)) + .pipe(transform(content => content.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, "$1$2enum $3 {$4"))) + .pipe(rename("typescriptServices.d.ts")) + .pipe(dest("built/local")); + + // create typescript.js + const createTypescriptJs = () => src("built/local/typescriptServices.js") + .pipe(newer("built/local/typescript.js")) + .pipe(sourcemaps.init({ loadMaps: true })) .pipe(rename("typescript.js")) - .pipe(gulp.dest("built/local"))) + .pipe(sourcemaps.write(".", { includeContent: false, destPath: "built/local" })) + .pipe(dest("built/local")); -const typescriptDts = "built/local/typescript.d.ts"; -gulp.task(typescriptDts, /*help*/ false, [typescriptServicesDts], () => - gulp.src([typescriptServicesDts], { base: "built/local" }) - .pipe(newer(typescriptDts)) + // create typescript.d.ts + const createTypescriptDts = () => src("built/local/typescriptServices.d.ts") + .pipe(newer("built/local/typescript.d.ts")) .pipe(append("\nexport = ts;")) .pipe(rename("typescript.d.ts")) - .pipe(gulp.dest("built/local"))); + .pipe(dest("built/local")); -const typescriptStandaloneDts = "built/local/typescript_standalone.d.ts"; -gulp.task(typescriptStandaloneDts, /*help*/ false, [typescriptServicesDts], () => - gulp.src([typescriptServicesDts], { base: "built/local" }) - .pipe(newer(typescriptStandaloneDts)) - .pipe(replace(/declare (namespace|module) ts/g, 'declare module "typescript"')) + // create typescript_standalone.d.ts + const createTypescriptStandaloneDts = () => src("built/local/typescriptServices.d.ts") + .pipe(newer("built/local/typescript_standalone.d.ts")) + .pipe(transform(content => content.replace(/declare (namespace|module) ts/g, 'declare module "typescript"'))) .pipe(rename("typescript_standalone.d.ts")) - .pipe(gulp.dest("built/local"))); - -// build all 'typescriptServices'-related outputs -gulp.task("services", /*help*/ false, [typescriptServicesJs, typescriptServicesDts, typescriptJs, typescriptDts, typescriptStandaloneDts]); - -const useCompiler = cmdLineOptions.lkg ? "lkg" : "built"; -const useCompilerDeps = cmdLineOptions.lkg ? ["lib", "generate-diagnostics"] : [typescriptServicesJs]; - -const tscProject = "src/tsc/tsconfig.json"; -const tscJs = "built/local/tsc.js"; -gulp.task(tscJs, /*help*/ false, useCompilerDeps, () => - project.compile(tscProject, { - typescript: useCompiler, - js: files => files.pipe(prepend.file(copyright)) - })); - -const tscReleaseProject = "src/tsc/tsconfig.release.json"; -const tscReleaseJs = "built/local/tsc.release.js"; -gulp.task(tscReleaseJs, /*help*/ false, () => - project.compile(tscReleaseProject, { - js: files => files.pipe(prepend.file(copyright)) - })); - -const cancellationTokenProject = "src/cancellationToken/tsconfig.json"; -const cancellationTokenJs = "built/local/cancellationToken.js"; -gulp.task(cancellationTokenJs, /*help*/ false, useCompilerDeps, () => project.compile(cancellationTokenProject, { typescript: useCompiler })); - -const typingsInstallerProject = "src/typingsInstaller/tsconfig.json"; -const typingsInstallerJs = "built/local/typingsInstaller.js"; -gulp.task(typingsInstallerJs, /*help*/ false, useCompilerDeps, () => project.compile(typingsInstallerProject, { typescript: useCompiler })); - -const tsserverProject = "src/tsserver/tsconfig.json"; -const tsserverJs = "built/local/tsserver.js"; -gulp.task(tsserverJs, /*help*/ false, useCompilerDeps, () => project.compile(tsserverProject, { typescript: useCompiler })); - -const watchGuardProject = "src/watchGuard/tsconfig.json"; -const watchGuardJs = "built/local/watchGuard.js"; -gulp.task(watchGuardJs, /*help*/ false, useCompilerDeps, () => project.compile(watchGuardProject, { typescript: useCompiler })); - -const typesMapJson = "built/local/typesMap.json"; -gulp.task(typesMapJson, /*help*/ false, [], () => - gulp.src("src/server/typesMap.json") - .pipe(newer(typesMapJson)) - .pipe(insert.transform(contents => (JSON.parse(contents), contents))) - .pipe(gulp.dest("built/local"))); - -const tsserverlibraryProject = "built/local/tsserverlibrary.tsconfig.json"; -gulp.task(tsserverlibraryProject, /*help*/ false, () => { - // NOTE: flatten tsserverlibrary so that we can properly strip @internal - project.flatten("src/tsserver/tsconfig.json", tsserverlibraryProject, { - exclude: ["src/tsserver/server.ts"], - compilerOptions: { - "removeComments": false, - "stripInternal": true, - "declarationMap": false, - "outFile": "tsserverlibrary.out.js" // must align with same task in jakefile. We fix this name below. - } - }); -}); + .pipe(dest("built/local")); + + return series( + buildTypescriptServicesOut, + createTypescriptServicesJs, + createTypescriptServicesDts, + createTypescriptJs, + createTypescriptDts, + createTypescriptStandaloneDts, + ); +})(); +task("services", series(preBuild, buildServices)); +task("services").description = "Builds the language service"; +task("services").flags = { + " --built": "Compile using the built version of the compiler." +} + +const cleanServices = async () => { + if (fs.existsSync("built/local/typescriptServices.tsconfig.json")) { + await cleanProject("built/local/typescriptServices.tsconfig.json"); + } + await del([ + "built/local/typescriptServices.out.js", + "built/local/typescriptServices.out.d.ts", + "built/local/typescriptServices.out.tsbuildinfo", + "built/local/typescriptServices.js", + "built/local/typescript.js", + "built/local/typescript.d.ts", + "built/local/typescript_standalone.d.ts" + ]); +}; +cleanTasks.push(cleanServices); +task("clean-services", cleanServices); +task("clean-services").description = "Cleans outputs for the language service"; + +const watchServices = () => watch([ + "src/compiler/tsconfig.json", + "src/compiler/**/*.ts", + "src/jsTyping/tsconfig.json", + "src/jsTyping/**/*.ts", + "src/services/tsconfig.json", + "src/services/**/*.ts", +], series(preBuild, buildServices)); +task("watch-services", series(preBuild, parallel(watchLib, watchDiagnostics, watchServices))); +task("watch-services").description = "Watches for changes and rebuild language service only"; +task("watch-services").flags = { + " --built": "Compile using the built version of the compiler." +} + +const buildServer = () => buildProject("src/tsserver", cmdLineOptions); +task("tsserver", series(preBuild, buildServer)); +task("tsserver").description = "Builds the language server"; +task("tsserver").flags = { + " --built": "Compile using the built version of the compiler." +} + +const cleanServer = () => cleanProject("src/tsserver"); +cleanTasks.push(cleanServer); +task("clean-tsserver", cleanServer); +task("clean-tsserver").description = "Cleans outputs for the language server"; + +const watchServer = () => watchProject("src/tsserver", cmdLineOptions); +task("watch-tsserver", series(preBuild, parallel(watchLib, watchDiagnostics, watchServer))); +task("watch-tsserver").description = "Watch for changes and rebuild the language server only"; +task("watch-tsserver").flags = { + " --built": "Compile using the built version of the compiler." +} + +task("min", series(preBuild, parallel(buildTsc, buildServer))); +task("min").description = "Builds only tsc and tsserver"; +task("min").flags = { + " --built": "Compile using the built version of the compiler." +} + +task("clean-min", series(cleanTsc, cleanServer)); +task("clean-min").description = "Cleans outputs for tsc and tsserver"; + +task("watch-min", series(preBuild, parallel(watchLib, watchDiagnostics, watchTsc, watchServer))); +task("watch-min").description = "Watches for changes to a tsc and tsserver only"; +task("watch-min").flags = { + " --built": "Compile using the built version of the compiler." +} + +const buildLssl = (() => { + // build tsserverlibrary.out.js + const buildServerLibraryOut = () => buildProject("src/tsserverlibrary/tsconfig.json", cmdLineOptions); + + // create tsserverlibrary.js + const createServerLibraryJs = () => src("built/local/tsserverlibrary.out.js") + .pipe(newer("built/local/tsserverlibrary.js")) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(prependFile(copyright)) + .pipe(rename("tsserverlibrary.js")) + .pipe(sourcemaps.write(".", { includeContent: false, destPath: "built/local" })) + .pipe(dest("built/local")); + + // create tsserverlibrary.d.ts + const createServerLibraryDts = () => src("built/local/tsserverlibrary.out.d.ts") + .pipe(newer("built/local/tsserverlibrary.d.ts")) + .pipe(prependFile(copyright)) + .pipe(transform(content => content.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, "$1$2enum $3 {$4"))) + .pipe(append("\nexport = ts;\nexport as namespace ts;")) + .pipe(rename("tsserverlibrary.d.ts")) + .pipe(dest("built/local")); + + return series( + buildServerLibraryOut, + createServerLibraryJs, + createServerLibraryDts, + ); +})(); +task("lssl", series(preBuild, buildLssl)); +task("lssl").description = "Builds language service server library"; +task("lssl").flags = { + " --built": "Compile using the built version of the compiler." +} + +const cleanLssl = async () => { + if (fs.existsSync("built/local/tsserverlibrary.tsconfig.json")) { + await cleanProject("built/local/tsserverlibrary.tsconfig.json"); + } + await del([ + "built/local/tsserverlibrary.out.js", + "built/local/tsserverlibrary.out.d.ts", + "built/local/tsserverlibrary.out.tsbuildinfo", + "built/local/tsserverlibrary.js", + "built/local/tsserverlibrary.d.ts", + ]); +}; +cleanTasks.push(cleanLssl); +task("clean-lssl", cleanLssl); +task("clean-lssl").description = "Clean outputs for the language service server library"; + +const watchLssl = () => watch([ + "src/compiler/tsconfig.json", + "src/compiler/**/*.ts", + "src/jsTyping/tsconfig.json", + "src/jsTyping/**/*.ts", + "src/services/tsconfig.json", + "src/services/**/*.ts", + "src/server/tsconfig.json", + "src/server/**/*.ts", + "src/tsserver/tsconfig.json", + "src/tsserver/**/*.ts", +], buildLssl); +task("watch-lssl", series(preBuild, parallel(watchLib, watchDiagnostics, watchLssl))); +task("watch-lssl").description = "Watch for changes and rebuild tsserverlibrary only"; +task("watch-lssl").flags = { + " --built": "Compile using the built version of the compiler." +} + +const buildTests = () => buildProject("src/testRunner"); +task("tests", series(preBuild, parallel(buildLssl, buildTests))); +task("tests").description = "Builds the test infrastructure"; +task("tests").flags = { + " --built": "Compile using the built version of the compiler." +} + +const cleanTests = () => cleanProject("src/testRunner"); +cleanTasks.push(cleanTests); +task("clean-tests", cleanTests); +task("clean-tests").description = "Cleans the outputs for the test infrastructure"; + +const watchTests = () => watchProject("src/testRunner", cmdLineOptions); + +const buildRules = () => buildProject("scripts/tslint"); +task("build-rules", buildRules); +task("build-rules").description = "Compiles tslint rules to js"; + +const cleanRules = () => cleanProject("scripts/tslint"); +cleanTasks.push(cleanRules); +task("clean-rules", cleanRules); +task("clean-rules").description = "Cleans the outputs for the lint rules"; + +const lintFoldStart = async () => { if (fold.isTravis()) console.log(fold.start("lint")); }; +const lintFoldEnd = async () => { if (fold.isTravis()) console.log(fold.end("lint")); }; +const lint = series([ + lintFoldStart, + ...["scripts/tslint/tsconfig.json", "src/tsconfig-base.json"].map(project => { + const lintOne = () => { + const args = ["node_modules/tslint/bin/tslint", "--project", project, "--formatters-dir", "./built/local/tslint/formatters", "--format", "autolinkableStylish"]; + if (cmdLineOptions.fix) args.push("--fix"); + log(`Linting: node ${args.join(" ")}`); + return exec(process.execPath, args); + }; + lintOne.dispayName = `lint(${project})`; + return lintOne; + }), + lintFoldEnd +]); +lint.displayName = "lint"; +task("lint", series(buildRules, lint)); +task("lint").description = "Runs tslint on the compiler sources."; +task("lint").flags = { + " --f[iles]=": "pattern to match files to lint", +}; + +const buildCancellationToken = () => buildProject("src/cancellationToken"); +const cleanCancellationToken = () => cleanProject("src/cancellationToken"); +cleanTasks.push(cleanCancellationToken); + +const buildTypingsInstaller = () => buildProject("src/typingsInstaller"); +const cleanTypingsInstaller = () => cleanProject("src/typingsInstaller"); +cleanTasks.push(cleanTypingsInstaller); + +const buildWatchGuard = () => buildProject("src/watchGuard"); +const cleanWatchGuard = () => cleanProject("src/watchGuard"); +cleanTasks.push(cleanWatchGuard); + +const generateTypesMap = () => src("src/server/typesMap.json") + .pipe(newer("built/local/typesMap.json")) + .pipe(transform(contents => (JSON.parse(contents), contents))) // validates typesMap.json is valid JSON + .pipe(dest("built/local")); +task("generate-types-map", generateTypesMap); + +const cleanTypesMap = () => del("built/local/typesMap.json"); +cleanTasks.push(cleanTypesMap); + +const buildOtherOutputs = parallel(buildCancellationToken, buildTypingsInstaller, buildWatchGuard, generateTypesMap); +task("other-outputs", series(preBuild, buildOtherOutputs)); +task("other-outputs").description = "Builds miscelaneous scripts and documents distributed with the LKG"; + +const buildFoldStart = async () => { if (fold.isTravis()) console.log(fold.start("build")); }; +const buildFoldEnd = async () => { if (fold.isTravis()) console.log(fold.end("build")); }; +task("local", series(buildFoldStart, preBuild, parallel(localize, buildTsc, buildServer, buildServices, buildLssl, buildOtherOutputs), buildFoldEnd)); +task("local").description = "Builds the full compiler and services"; +task("local").flags = { + " --built": "Compile using the built version of the compiler." +} + +task("watch-local", series(preBuild, parallel(watchLib, watchDiagnostics, watchTsc, watchServices, watchServer, watchLssl))); +task("watch-local").description = "Watches for changes to projects in src/ (but does not execute tests)."; +task("watch-local").flags = { + " --built": "Compile using the built version of the compiler." +} + +const generateCodeCoverage = () => exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", "" + cmdLineOptions.testTimeout, "built/local/run.js"]); +task("generate-code-coverage", series(preBuild, buildTests, generateCodeCoverage)); +task("generate-code-coverage").description = "Generates code coverage data via istanbul"; + +const preTest = parallel(buildRules, buildTests, buildServices, buildLssl); +preTest.displayName = "preTest"; + +const postTest = (done) => cmdLineOptions.lint ? lint(done) : done(); + +const runTests = () => runConsoleTests("built/local/run.js", "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ false); +task("runtests", series(preBuild, preTest, runTests, postTest)); +task("runtests").description = "Runs the tests using the built run.js file."; +task("runtests").flags = { + "-t --tests=": "Pattern for tests to run.", + " --failed": "Runs tests listed in '.failed-tests'.", + "-r --reporter=": "The mocha reporter to use.", + "-d --debug": "Runs tests in debug mode (NodeJS 6 and earlier)", + "-i --inspect": "Runs tests in inspector mode (NodeJS 8 and later)", + " --keepFailed": "Keep tests in .failed-tests even if they pass", + " --light": "Run tests in light mode (fewer verifications, but tests run faster)", + " --dirty": "Run tests without first cleaning test output directories", + " --stackTraceLimit=": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.", + " --no-color": "Disables color", + " --no-lint": "Disables lint", + " --timeout=": "Overrides the default test timeout.", + " --built": "Compile using the built version of the compiler.", +} + +const runTestsParallel = () => runConsoleTests("built/local/run.js", "min", /*runInParallel*/ true, /*watchMode*/ false); +task("runtests-parallel", series(preBuild, preTest, runTestsParallel, postTest)); +task("runtests-parallel").description = "Runs all the tests in parallel using the built run.js file."; +task("runtests-parallel").flags = { + " --no-lint": "disables lint.", + " --light": "Run tests in light mode (fewer verifications, but tests run faster).", + " --keepFailed": "Keep tests in .failed-tests even if they pass.", + " --dirty": "Run tests without first cleaning test output directories.", + " --stackTraceLimit=": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.", + " --workers=": "The number of parallel workers to use.", + " --timeout=": "Overrides the default test timeout.", + " --built": "Compile using the built version of the compiler.", +}; + +task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true })); +task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable"; + +task("diff-rwc", () => exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], { ignoreExitCode: true })); +task("diff-rwc").description = "Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable"; -const tsserverlibraryJs = "built/local/tsserverlibrary.js"; -const tsserverlibraryDts = "built/local/tsserverlibrary.d.ts"; -gulp.task(tsserverlibraryJs, /*help*/ false, useCompilerDeps.concat([tsserverlibraryProject]), () => - project.compile(tsserverlibraryProject, { - js: files => files - .pipe(prepend.file(copyright)) - .pipe(rename("tsserverlibrary.js")), - dts: files => files - .pipe(removeSourceMaps()) - .pipe(prepend.file(copyright)) - .pipe(convertConstEnums()) - .pipe(append("\nexport = ts;\nexport as namespace ts;")) - .pipe(rename("tsserverlibrary.d.ts")), - typescript: useCompiler - }), { aliases: [tsserverlibraryDts] }); - -gulp.task( - "lssl", - "Builds language service server library", - [tsserverlibraryDts]); - -gulp.task( - "local", - "Builds the full compiler and services", - [tscJs, "services", tsserverJs, builtGeneratedDiagnosticMessagesJson, tsserverlibraryDts, "localize"]); - -gulp.task( - "tsc", - "Builds only the compiler", - [tscJs]); - -// Generate Markdown spec -const specMd = "doc/spec.md"; -gulp.task(specMd, /*help*/ false, [word2mdJs], () => - exec("cscript", ["//nologo", word2mdJs, path.resolve(specMd), path.resolve("doc/TypeScript Language Specification.docx")])); - -gulp.task( - "generate-spec", - "Generates a Markdown version of the Language Specification", - [specMd]); - -gulp.task("produce-LKG", /*help*/ false, ["scripts", "local", cancellationTokenJs, typingsInstallerJs, watchGuardJs, tscReleaseJs], () => { +/** + * @param {string} localBaseline Path to the local copy of the baselines + * @param {string} refBaseline Path to the reference copy of the baselines + */ +const baselineAccept = (localBaseline, refBaseline) => merge2( + src([`${localBaseline}/**`, `!${localBaseline}/**/*.delete`], { base: localBaseline }) + .pipe(dest(refBaseline)), + src([`${localBaseline}/**/*.delete`], { base: localBaseline, read: false }) + .pipe(rm()) + .pipe(rename({ extname: "" })) + .pipe(rm(refBaseline))); +task("baseline-accept", () => baselineAccept(localBaseline, refBaseline)); +task("baseline-accept").description = "Makes the most recent test results the new baseline, overwriting the old baseline"; + +task("baseline-accept-rwc", () => baselineAccept(localRwcBaseline, refRwcBaseline)); +task("baseline-accept-rwc").description = "Makes the most recent rwc test results the new baseline, overwriting the old baseline"; + +const buildLoggedIO = async () => { + mkdirp.sync("built/local/temp"); + await exec(process.execPath, ["lib/tsc", "--types", "--target", "es5", "--lib", "es5", "--outdir", "built/local/temp", "src/harness/loggedIO.ts"]); + fs.renameSync("built/local/temp/harness/loggedIO.js", "built/local/loggedIO.js"); + await del("built/local/temp"); +}; + +const cleanLoggedIO = () => del("built/local/temp/loggedIO.js"); +cleanTasks.push(cleanLoggedIO); + +const buildInstrumenter = () => buildProject("src/instrumenter"); +const cleanInstrumenter = () => cleanProject("src/instrumenter"); +cleanTasks.push(cleanInstrumenter); + +const tscInstrumented = () => exec(process.execPath, ["built/local/instrumenter.js", "record", cmdLineOptions.tests || "iocapture", "built/local"]); +task("tsc-instrumented", series(lkgPreBuild, parallel(localize, buildTsc, buildServer, buildServices, buildLssl, buildLoggedIO, buildInstrumenter), tscInstrumented)); +task("tsc-instrumented").description = "Builds an instrumented tsc.js"; +task("tsc-instrumented").flags = { + "-t --tests=": "The test to run." +} + +// TODO(rbuckton): Determine if we still need this task. Depending on a relative +// path here seems like a bad idea. +const updateSublime = () => src(["built/local/tsserver.js", "built/local/tsserver.js.map"]) + .pipe(dest("../TypeScript-Sublime-Plugin/tsserver/")); +task("update-sublime", updateSublime); +task("update-sublime").description = "Updates the sublime plugin's tsserver"; + +const buildImportDefinitelyTypedTests = () => buildProject("scripts/importDefinitelyTypedTests"); +const cleanImportDefinitelyTypedTests = () => cleanProject("scripts/importDefinitelyTypedTests"); +cleanTasks.push(cleanImportDefinitelyTypedTests); + +// TODO(rbuckton): Should the path to DefinitelyTyped be configurable via an environment variable? +const importDefinitelyTypedTests = () => exec(process.execPath, ["scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js", "./", "../DefinitelyTyped"]); +task("importDefinitelyTypedTests", series(buildImportDefinitelyTypedTests, importDefinitelyTypedTests)); +task("importDefinitelyTypedTests").description = "Runs the importDefinitelyTypedTests script to copy DT's tests to the TS-internal RWC tests"; + +const buildReleaseTsc = () => buildProject("src/tsc/tsconfig.release.json"); +const cleanReleaseTsc = () => cleanProject("src/tsc/tsconfig.release.json"); +cleanTasks.push(cleanReleaseTsc); + +const cleanBuilt = () => del("built"); + +const produceLKG = async () => { const expectedFiles = [ - tscReleaseJs, - typescriptServicesJs, - tsserverJs, - typescriptJs, - typescriptDts, - typescriptServicesDts, - tsserverlibraryDts, - tsserverlibraryDts, - typingsInstallerJs, - cancellationTokenJs - ].concat(libraryTargets); + "built/local/tsc.release.js", + "built/local/typescriptServices.js", + "built/local/typescriptServices.d.ts", + "built/local/tsserver.js", + "built/local/typescript.js", + "built/local/typescript.d.ts", + "built/local/tsserverlibrary.js", + "built/local/tsserverlibrary.d.ts", + "built/local/typingsInstaller.js", + "built/local/cancellationToken.js" + ].concat(libs.map(lib => lib.target)); const missingFiles = expectedFiles .concat(localizationTargets) .filter(f => !fs.existsSync(f)); @@ -301,335 +517,70 @@ gulp.task("produce-LKG", /*help*/ false, ["scripts", "local", cancellationTokenJ throw new Error("Cannot replace the LKG unless all built targets are present in directory 'built/local/'. The following files are missing:\n" + missingFiles.join("\n")); } const sizeBefore = getDirSize("lib"); - return exec(host, [produceLKGJs]).then(() => { - const sizeAfter = getDirSize("lib"); - if (sizeAfter > (sizeBefore * 1.10)) { - throw new Error("The lib folder increased by 10% or more. This likely indicates a bug."); - } - }); -}); - -gulp.task( - "LKG", - "Makes a new LKG out of the built js files", - () => runSequence("clean-built", "produce-LKG")); - -// Task to build the tests infrastructure using the built compiler -const testRunnerProject = "src/testRunner/tsconfig.json"; -const runJs = "built/local/run.js"; -gulp.task(runJs, /*help*/ false, useCompilerDeps, () => project.compile(testRunnerProject, { typescript: useCompiler })); - -gulp.task( - "tests", - "Builds the test infrastructure using the built compiler", - [runJs, tsserverlibraryDts]); - -gulp.task( - "runtests-parallel", - "Runs all the tests in parallel using the built run.js file. Optional arguments are: --t[ests]=category1|category2|... --d[ebug]=true.", - ["build-rules", "tests", "services", tsserverlibraryDts], - () => runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ false)); - -gulp.task( - "runtests", - "Runs the tests using the built run.js file. Optional arguments are: --t[ests]=regex --r[eporter]=[list|spec|json|] --d[ebug]=true --color[s]=false --lint=true.", - ["build-rules", "tests", "services", tsserverlibraryDts], - () => runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ false)); - -const webTestServerProject = "tests/webTestServer.tsconfig.json"; -const webTestServerJs = "tests/webTestServer.js"; -gulp.task(webTestServerJs, /*help*/ false, useCompilerDeps, () => project.compile(webTestServerProject, { typescript: useCompiler })); -gulp.task(`clean:${webTestServerJs}`, /*help*/ false, () => project.clean(webTestServerProject)); - -const bundlePath = path.resolve("built/local/bundle.js"); - -gulp.task( - "browserify", - "Runs browserify on run.js to produce a file suitable for running tests in the browser", - [runJs], - () => gulp.src([runJs], { base: "built/local" }) - .pipe(newer(bundlePath)) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(browserify()) - .pipe(rename("bundle.js")) - .pipe(sourcemaps.write(".", /**@type {*}*/({ includeContent: false, destPath: "built/local" }))) - .pipe(gulp.dest("built/local"))); - -gulp.task( - "runtests-browser", - "Runs the tests using the built run.js file like 'gulp runtests'. Syntax is gulp runtests-browser. Additional optional parameters --tests=[regex], --browser=[chrome|IE]", - ["browserify", webTestServerJs], - () => cleanTestDirs().then(() => { - const tests = cmdLineOptions.tests; - const runners = cmdLineOptions.runners; - const light = cmdLineOptions.light; - const testConfigFile = "test.config"; - if (fs.existsSync(testConfigFile)) { - fs.unlinkSync(testConfigFile); - } - if (tests || runners || light) { - writeTestConfigFile(tests, runners, light); - } - const args = [webTestServerJs]; - if (cmdLineOptions.browser) { - args.push(cmdLineOptions.browser); - } - if (tests) { - args.push(JSON.stringify(tests)); - } - return exec("node", args); - })); - -gulp.task( - "generate-code-coverage", - "Generates code coverage data via istanbul", - ["tests"], - () => exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", "" + cmdLineOptions.testTimeout, runJs])); - - -gulp.task( - "diff", - "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable", - () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true })); - -gulp.task( - "diff-rwc", - "Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable", - () => exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], { ignoreExitCode: true })); - -gulp.task( - "baseline-accept", - "Makes the most recent test results the new baseline, overwriting the old baseline", - () => baselineAccept()); - -gulp.task( - "baseline-accept-rwc", - "Makes the most recent rwc test results the new baseline, overwriting the old baseline", - () => baselineAccept("rwc")); - -gulp.task( - "baseline-accept-test262", - "Makes the most recent test262 test results the new baseline, overwriting the old baseline", - () => baselineAccept("test262")); - -// Webhost -const webtscProject = "tests/webhost/webtsc.tsconfig.json"; -const webtscJs = "tests/webhost/webtsc.js"; -gulp.task(webtscJs, /*help*/ false, useCompilerDeps, () => project.compile(webtscProject, { typescript: useCompiler })); -gulp.task(`clean:${webtscJs}`, /*help*/ false, () => project.clean(webtscProject)); - -gulp.task("webhost", "Builds the tsc web host", [webtscJs], () => - gulp.src("built/local/lib.d.ts") - .pipe(gulp.dest("tests/webhost/"))); - -// Perf compiler -const perftscProject = "tests/perftsc.tsconfig.json"; -const perftscJs = "built/local/perftsc.js"; -gulp.task(perftscJs, /*help*/ false, useCompilerDeps, () => project.compile(perftscProject, { typescript: useCompiler })); -gulp.task(`clean:${perftscJs}`, /*help*/ false, () => project.clean(perftscProject)); - -gulp.task( - "perftsc", - "Builds augmented version of the compiler for perf tests", - [perftscJs]); - -// Instrumented compiler -const loggedIOTs = "src/harness/loggedIO.ts"; -const loggedIOJs = "built/local/loggedIO.js"; -gulp.task(loggedIOJs, /*help*/ false, [], (done) => { - return mkdirp("built/local/temp") - .then(() => exec(host, ["lib/tsc.js", "--types", "--target es5", "--lib es5", "--outdir", "built/local/temp", loggedIOTs])) - .then(() => { fs.renameSync(path.join("built/local/temp", "/harness/loggedIO.js"), loggedIOJs); }) - .then(() => del("built/local/temp")); + await exec(process.execPath, ["scripts/produceLKG.js"]); + const sizeAfter = getDirSize("lib"); + if (sizeAfter > (sizeBefore * 1.10)) { + throw new Error("The lib folder increased by 10% or more. This likely indicates a bug."); + } +}; + +task("LKG", series(lkgPreBuild, parallel(localize, buildTsc, buildServer, buildServices, buildLssl, buildOtherOutputs, buildReleaseTsc), produceLKG)); +task("LKG").description = "Makes a new LKG out of the built js files"; +task("LKG").flags = { + " --built": "Compile using the built version of the compiler.", +} + +const generateSpec = () => exec("cscript", ["//nologo", "scripts/word2md.js", path.resolve("doc/TypeScript Language Specification.docx"), path.resolve("doc/spec.md")]); +task("generate-spec", series(buildScripts, generateSpec)); +task("generate-spec").description = "Generates a Markdown version of the Language Specification"; + +task("clean", series(parallel(cleanTasks), cleanBuilt)); +task("clean").description = "Cleans build outputs"; + +const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/core.ts"]) +task("configure-nightly", series(buildScripts, configureNightly)); +task("configure-nightly").description = "Runs scripts/configurePrerelease.ts to prepare a build for nightly publishing"; + +const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/core.ts"]) +task("configure-insiders", series(buildScripts, configureInsiders)); +task("configure-insiders").description = "Runs scripts/configurePrerelease.ts to prepare a build for insiders publishing"; + +const publishNightly = () => exec("npm", ["publish", "--tag", "next"]); +task("publish-nightly", series(task("clean"), task("LKG"), task("clean"), task("runtests-parallel"), publishNightly)); +task("publish-nightly").description = "Runs `npm publish --tag next` to create a new nightly build on npm"; + +// TODO(rbuckton): The problem with watching in this way is that a change in compiler/ will result +// in cascading changes in other projects that may take differing amounts of times to complete. As +// a result, the watch may accidentally trigger early, so we have to set a significant delay. An +// alternative approach would be to leverage a builder API, or to have 'tsc -b' have an option to +// write some kind of trigger file that indicates build completion that we could listen for instead. +const watchRuntests = () => watch(["built/local/*.js", "tests/cases/**/*.ts", "tests/cases/**/tsconfig.json"], { delay: 5000 }, async () => { + if (cmdLineOptions.tests || cmdLineOptions.failed) { + await runConsoleTests("built/local/run.js", "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true); + } + else { + await runConsoleTests("built/local/run.js", "min", /*runInParallel*/ true, /*watchMode*/ true); + } }); - -const instrumenterProject = "src/instrumenter/tsconfig.json"; -const instrumenterJs = "built/local/instrumenter.js"; -gulp.task(instrumenterJs, /*help*/ false, () => project.compile(instrumenterProject)); -gulp.task(`clean:${instrumenterJs}`, /*help*/ false, () => project.clean(instrumenterProject)); - -gulp.task( - "tsc-instrumented", - "Builds an instrumented tsc.js - run with --test=[testname]", - ["local", loggedIOJs, instrumenterJs, typescriptServicesJs], - () => exec(host, [instrumenterJs, "record", cmdLineOptions.tests || "iocapture", "built/local"])); - -gulp.task( - "update-sublime", - "Updates the sublime plugin's tsserver", - ["local", tsserverJs], - () => - gulp.src([tsserverJs, tsserverJs + ".map"]) - .pipe(gulp.dest("../TypeScript-Sublime-Plugin/tsserver/"))); - -gulp.task( - "build-rules", - "Compiles tslint rules to js", - () => project.compile("scripts/tslint/tsconfig.json")); - -gulp.task("clean-rules", /*help*/ false, () => project.clean("scripts/tslint/tsconfig.json")); - -gulp.task( - "lint", - "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", - ["build-rules"], - () => { - if (fold.isTravis()) console.log(fold.start("lint")); - for (const project of ["scripts/tslint/tsconfig.json", "src/tsconfig-base.json"]) { - const cmd = `node node_modules/tslint/bin/tslint --project ${project} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish${cmdLineOptions.fix ? " --fix" : ""}`; - log("Linting: " + cmd); - child_process.execSync(cmd, { stdio: [0, 1, 2] }); - } - if (fold.isTravis()) console.log(fold.end("lint")); - }); - -gulp.task( - "default", - "Runs 'local'", - ["local"]); - -gulp.task( - "watch-lib", - /*help*/ false, - () => gulp.watch(["src/lib/**/*"], ["lib"])); - -const watchTscPatterns = [ - "src/tsconfig-base.json", - "src/lib/**/*", - "src/compiler/**/*", - "src/tsc/**/*", -]; -gulp.task( - "watch-tsc", - /*help*/ false, - useCompilerDeps, - () => gulp.watch(watchTscPatterns, ["tsc"])); - -const watchServicesPatterns = [ - "src/compiler/**/*", - "src/jsTypings/**/*", - "src/services/**/*" -]; -gulp.task( - "watch-services", - /*help*/ false, - ["watch-diagnostics", "watch-lib"], - () => gulp.watch(watchServicesPatterns, ["services"])); - -const watchLsslPatterns = [ - ...watchServicesPatterns, - "src/server/**/*", - "src/tsserver/tsconfig.json" -]; -gulp.task( - "watch-lssl", - /*help*/ false, - () => gulp.watch(watchLsslPatterns, ["lssl"])); - -const watchLocalPatterns = [ - "src/tsconfig-base.json", - "src/lib/**/*", - "src/compiler/**/*", - "src/tsc/**/*", - "src/services/**/*", - "src/jsTyping/**/*", - "src/server/**/*", - "src/tsserver/**/*", - "src/typingsInstallerCore/**/*", - "src/harness/**/*", - "src/testRunner/**/*", -]; -gulp.task( - "watch-local", - "Watches for changes to projects in src/ (but does not execute tests).", - () => gulp.watch(watchLocalPatterns, "local")); - -const watchPatterns = [ - "src/tsconfig-base.json", - "src/lib/**/*", - "src/compiler/**/*", - "src/services/**/*", - "src/jsTyping/**/*", - "src/server/**/*", - "src/tsserver/**/*", - "src/typingsInstallerCore/**/*", - "src/harness/**/*", - "src/testRunner/**/*", -]; -gulp.task( - "watch", - "Watches for changes to the build inputs for built/local/run.js, then runs tests.", - ["build-rules"], - () => { - const sem = new Semaphore(1); - - gulp.watch(watchPatterns, () => { runTests(); }); - - // NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file - const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/; - fs.watch("tests/cases", { recursive: true }, (_, file) => { - if (testFilePattern.test(file)) runTests(); - }); - - async function runTests() { - try { - // Ensure only one instance of the test runner is running at any given time. - if (sem.count > 0) { - await sem.wait(); - try { - // Wait for any concurrent recompilations to complete... - try { - await delay(100); - while (project.hasRemainingWork()) { - await project.waitForWorkToComplete(); - await delay(500); - } - } - catch (e) { - if (e instanceof CancelError) return; - throw e; - } - - // cancel any pending or active test run if a new recompilation is triggered - const source = new CancellationTokenSource(); - project.waitForWorkToStart().then(() => { - source.cancel(); - }); - - if (cmdLineOptions.tests || cmdLineOptions.failed) { - await runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, source.token); - } - else { - await runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, source.token); - } - } - finally { - sem.release(); - } - } - } - catch (e) { - if (e instanceof CancelError) { - log.warn("Operation was canceled"); - } - else { - log.error(e); - } - } - }; - }); - -gulp.task("clean-built", /*help*/ false, [`clean:${diagnosticInformationMapTs}`], () => del(["built"])); -gulp.task( - "clean", - "Cleans the compiler output, declare files, and tests", - [ - `clean:${importDefinitelyTypedTestsJs}`, - `clean:${webtscJs}`, - `clean:${perftscJs}`, - `clean:${instrumenterJs}`, - `clean:${webTestServerJs}`, - "clean:scripts", - "clean-rules", - "clean-built" - ]); \ No newline at end of file +task("watch", series(preBuild, preTest, parallel(watchLib, watchDiagnostics, watchServices, watchLssl, watchTests, watchRuntests))); +task("watch").description = "Watches for changes and rebuilds and runs tests in parallel."; +task("watch").flags = { + "-t --tests=": "Pattern for tests to run. Forces tests to be run in a single worker.", + " --failed": "Runs tests listed in '.failed-tests'. Forces tests to be run in a single worker.", + "-r --reporter=": "The mocha reporter to use.", + " --keepFailed": "Keep tests in .failed-tests even if they pass", + " --light": "Run tests in light mode (fewer verifications, but tests run faster)", + " --dirty": "Run tests without first cleaning test output directories", + " --stackTraceLimit=": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.", + " --no-color": "Disables color", + " --no-lint": "Disables lint", + " --timeout=": "Overrides the default test timeout.", + " --workers=": "The number of parallel workers to use.", + " --built": "Compile using the built version of the compiler.", +}; + +task("default", series("local")); +task("default").description = "Runs 'local'"; + +task("help", () => exec("gulp", ["--tasks", "--depth", "1", "--sort-tasks"], { hidePrompt: true })); +task("help").description = "Prints the top-level tasks."; diff --git a/Jakefile.js b/Jakefile.js deleted file mode 100644 index 1413230c07961..0000000000000 --- a/Jakefile.js +++ /dev/null @@ -1,858 +0,0 @@ -// This file contains the build logic for the public repo -// @ts-check -/// - -const fs = require("fs"); -const os = require("os"); -const path = require("path"); -const fold = require("travis-fold"); -const ts = require("./lib/typescript"); -const del = require("del"); -const getDirSize = require("./scripts/build/getDirSize"); -const { base64VLQFormatEncode } = require("./scripts/build/sourcemaps"); -const needsUpdate = require("./scripts/build/needsUpdate"); -const { flatten } = require("./scripts/build/project"); - -// 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; -} - -const host = process.env.TYPESCRIPT_HOST || process.env.host || "node"; - -const defaultTestTimeout = 40000; - -let useDebugMode = true; - -const TaskNames = { - local: "local", - runtests: "runtests", - runtestsParallel: "runtests-parallel", - buildRules: "build-rules", - clean: "clean", - lib: "lib", - buildFoldStart: "build-fold-start", - buildFoldEnd: "build-fold-end", - generateDiagnostics: "generate-diagnostics", - coreBuild: "core-build", - tsc: "tsc", - lkg: "LKG", - release: "release", - lssl: "lssl", - lint: "lint", - scripts: "scripts", - localize: "localize", - configureInsiders: "configure-insiders", - publishInsiders: "publish-insiders", - configureNightly: "configure-nightly", - publishNightly: "publish-nightly", - help: "help" -}; - -const Paths = {}; -Paths.lkg = "lib"; -Paths.lkgCompiler = "lib/tsc.js"; -Paths.built = "built"; -Paths.builtLocal = "built/local"; -Paths.builtLocalCompiler = "built/local/tsc.js"; -Paths.builtLocalTSServer = "built/local/tsserver.js"; -Paths.builtLocalRun = "built/local/run.js"; -Paths.releaseCompiler = "built/local/tsc.release.js"; -Paths.typesMapOutput = "built/local/typesMap.json"; -Paths.typescriptFile = "built/local/typescript.js"; -Paths.servicesFile = "built/local/typescriptServices.js"; -Paths.servicesDefinitionFile = "built/local/typescriptServices.d.ts"; -Paths.servicesOutFile = "built/local/typescriptServices.out.js"; -Paths.servicesDefinitionOutFile = "built/local/typescriptServices.out.d.ts"; -Paths.typescriptDefinitionFile = "built/local/typescript.d.ts"; -Paths.typescriptStandaloneDefinitionFile = "built/local/typescript_standalone.d.ts"; -Paths.tsserverLibraryFile = "built/local/tsserverlibrary.js"; -Paths.tsserverLibraryDefinitionFile = "built/local/tsserverlibrary.d.ts"; -Paths.tsserverLibraryOutFile = "built/local/tsserverlibrary.out.js"; -Paths.tsserverLibraryDefinitionOutFile = "built/local/tsserverlibrary.out.d.ts"; -Paths.baselines = {}; -Paths.baselines.local = "tests/baselines/local"; -Paths.baselines.localTest262 = "tests/baselines/test262/local"; -Paths.baselines.localRwc = "internal/baselines/rwc/local"; -Paths.baselines.reference = "tests/baselines/reference"; -Paths.baselines.referenceTest262 = "tests/baselines/test262/reference"; -Paths.baselines.referenceRwc = "internal/baselines/rwc/reference"; -Paths.copyright = "CopyrightNotice.txt"; -Paths.thirdParty = "ThirdPartyNoticeText.txt"; -Paths.processDiagnosticMessagesJs = "scripts/processDiagnosticMessages.js"; -Paths.diagnosticInformationMap = "src/compiler/diagnosticInformationMap.generated.ts"; -Paths.diagnosticMessagesJson = "src/compiler/diagnosticMessages.json"; -Paths.diagnosticGeneratedJson = "src/compiler/diagnosticMessages.generated.json"; -Paths.builtDiagnosticGeneratedJson = "built/local/diagnosticMessages.generated.json"; -Paths.lcl = "src/loc/lcl" -Paths.locLcg = "built/local/enu/diagnosticMessages.generated.json.lcg"; -Paths.generatedLCGFile = path.join(Paths.builtLocal, "enu", "diagnosticMessages.generated.json.lcg"); -Paths.library = "src/lib"; -Paths.srcServer = "src/server"; -Paths.scripts = {}; -Paths.scripts.generateLocalizedDiagnosticMessages = "scripts/generateLocalizedDiagnosticMessages.js"; -Paths.scripts.processDiagnosticMessages = "scripts/processDiagnosticMessages.js"; -Paths.scripts.produceLKG = "scripts/produceLKG.js"; -Paths.scripts.configurePrerelease = "scripts/configurePrerelease.js"; -Paths.packageJson = "package.json"; -Paths.versionFile = "src/compiler/core.ts"; - -const ConfigFileFor = { - tsc: "src/tsc", - tscRelease: "src/tsc/tsconfig.release.json", - tsserver: "src/tsserver", - runjs: "src/testRunner", - lint: "scripts/tslint", - scripts: "scripts", - all: "src", - typescriptServices: "built/local/typescriptServices.tsconfig.json", - tsserverLibrary: "built/local/tsserverlibrary.tsconfig.json", -}; - -const ExpectedLKGFiles = [ - "tsc.js", - "tsserver.js", - "typescriptServices.js", - "typescriptServices.d.ts", - "typescript.js", - "typescript.d.ts", - "cancellationToken.js", - "typingsInstaller.js", - "protocol.d.ts", - "watchGuard.js" -]; - -directory(Paths.builtLocal); - -// Local target to build the compiler and services -desc("Builds the full compiler and services"); -task(TaskNames.local, [ - TaskNames.buildFoldStart, - TaskNames.coreBuild, - Paths.servicesDefinitionFile, - Paths.typescriptFile, - Paths.typescriptDefinitionFile, - Paths.typescriptStandaloneDefinitionFile, - Paths.tsserverLibraryDefinitionFile, - TaskNames.localize, - TaskNames.buildFoldEnd -]); - -task("default", [TaskNames.local]); - -const RunTestsPrereqs = [TaskNames.lib, Paths.servicesDefinitionFile, Paths.typescriptDefinitionFile, Paths.tsserverLibraryDefinitionFile]; -desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... i[nspect]=true."); -task(TaskNames.runtestsParallel, RunTestsPrereqs, function () { - tsbuild([ConfigFileFor.runjs], true, () => { - runConsoleTests("min", /*parallel*/ true); - }); -}, { async: true }); - -desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... i[nspect]=true."); -task(TaskNames.runtests, RunTestsPrereqs, function () { - tsbuild([ConfigFileFor.runjs], true, () => { - runConsoleTests('mocha-fivemat-progress-reporter', /*runInParallel*/ false); - }); -}, { async: true }); - -desc("Generates a diagnostic file in TypeScript based on an input JSON file"); -task(TaskNames.generateDiagnostics, [Paths.diagnosticInformationMap]); - -const libraryTargets = getLibraryTargets(); -desc("Builds the library targets"); -task(TaskNames.lib, libraryTargets); - -desc("Builds internal scripts"); -task(TaskNames.scripts, [TaskNames.coreBuild], function() { - tsbuild([ConfigFileFor.scripts], true, () => { - complete(); - }); -}, { async: true }); - -task(Paths.releaseCompiler, function () { - tsbuild([ConfigFileFor.tscRelease], true, () => { - complete(); - }); -}, { async: true }); - -// 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(TaskNames.lkg, [ - TaskNames.scripts, - TaskNames.release, - TaskNames.local, - Paths.servicesDefinitionFile, - Paths.typescriptFile, - Paths.typescriptDefinitionFile, - Paths.typescriptStandaloneDefinitionFile, - Paths.tsserverLibraryDefinitionFile, - Paths.releaseCompiler, - ...libraryTargets -], () => { - const sizeBefore = getDirSize(Paths.lkg); - - exec(`${host} ${Paths.scripts.produceLKG}`, () => { - const sizeAfter = getDirSize(Paths.lkg); - if (sizeAfter > (sizeBefore * 1.10)) { - throw new Error("The lib folder increased by 10% or more. This likely indicates a bug."); - } - - complete(); - }); -}, { async: true }); - -desc("Makes the most recent test results the new baseline, overwriting the old baseline"); -task("baseline-accept", function () { - acceptBaseline(Paths.baselines.local, Paths.baselines.reference); -}); - -desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline"); -task("baseline-accept-rwc", function () { - acceptBaseline(Paths.baselines.localRwc, Paths.baselines.referenceRwc); -}); - -desc("Makes the most recent test262 test results the new baseline, overwriting the old baseline"); -task("baseline-accept-test262", function () { - acceptBaseline(Paths.baselines.localTest262, Paths.baselines.referenceTest262); -}); - -desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex"); -task(TaskNames.lint, [TaskNames.buildRules], () => { - 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" : ""}`; - exec(cmd, cb); - } - lint("scripts/tslint/tsconfig.json", () => lint("src/tsconfig-base.json", () => { - if (fold.isTravis()) console.log(fold.end("lint")); - complete(); - })); -}, { async: true }); - -desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable"); -task('diff', function () { - var cmd = `"${getDiffTool()}" ${Paths.baselines.reference} ${Paths.baselines.local}`; - exec(cmd); -}, { async: true }); - -desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable"); -task('diff-rwc', function () { - var cmd = `"${getDiffTool()}" ${Paths.baselines.referenceRwc} ${Paths.baselines.localRwc}`; - exec(cmd); -}, { async: true }); - -task(TaskNames.configureNightly, [TaskNames.scripts], function () { - const cmd = `${host} ${Paths.scripts.configurePrerelease} dev ${Paths.packageJson} ${Paths.versionFile}`; - exec(cmd, () => complete()); -}, { async: true }); - -desc("Configure, build, test, and publish the nightly release."); -task(TaskNames.publishNightly, [TaskNames.coreBuild, TaskNames.configureNightly, TaskNames.lkg, "setDebugMode", "runtests-parallel"], function () { - var cmd = "npm publish --tag next"; - exec(cmd, () => complete()); -}, { async: true }); - -task(TaskNames.help, function() { - var cmd = "jake --tasks"; - exec(cmd, () => complete()); -}) - -task(TaskNames.configureInsiders, [TaskNames.scripts], function () { - const cmd = `${host} ${Paths.scripts.configurePrerelease} insiders ${Paths.packageJson} ${Paths.versionFile}`; - exec(cmd, () => complete()); -}, { async: true }); - -desc("Configure, build, test, and publish the insiders release."); -task(TaskNames.publishInsiders, [TaskNames.coreBuild, TaskNames.configureInsiders, TaskNames.lkg, "setDebugMode", "runtests-parallel"], function () { - var cmd = "npm publish --tag insiders"; - exec(cmd, () => complete()); -}, { async: true }); - -desc("Sets the release mode flag"); -task("release", function () { - useDebugMode = false; -}); - -desc("Clears the release mode flag"); -task("setDebugMode", function () { - useDebugMode = true; -}); - -desc("Generates localized diagnostic messages"); -task(TaskNames.localize, [Paths.generatedLCGFile]); - -desc("Emit the start of the build fold"); -task(TaskNames.buildFoldStart, [], function () { - if (fold.isTravis()) console.log(fold.start("build")); -}); - -desc("Emit the end of the build fold"); -task(TaskNames.buildFoldEnd, [], function () { - if (fold.isTravis()) console.log(fold.end("build")); -}); - -desc("Compiles tslint rules to js"); -task(TaskNames.buildRules, [], function () { - tsbuild(ConfigFileFor.lint, false, () => complete()); -}, { async: true }); - -desc("Cleans the compiler output, declare files, and tests"); -task(TaskNames.clean, function () { - jake.rmRf(Paths.built); -}); - -desc("Generates the LCG file for localization"); -task("localize", [Paths.generatedLCGFile]); - -task(TaskNames.tsc, [Paths.diagnosticInformationMap, TaskNames.lib], function () { - tsbuild(ConfigFileFor.tsc, true, () => { - complete(); - }); -}, { async: true }); - -task(TaskNames.coreBuild, [Paths.diagnosticInformationMap, TaskNames.lib], function () { - tsbuild(ConfigFileFor.all, true, () => { - complete(); - }); -}, { async: true }); - -file(Paths.diagnosticMessagesJson); - -file(Paths.typesMapOutput, /** @type {*} */(function () { - var content = readFileSync(path.join(Paths.srcServer, 'typesMap.json')); - // Validate that it's valid JSON - try { - JSON.parse(content); - } catch (e) { - console.log("Parse error in typesMap.json: " + e); - } - fs.writeFileSync(Paths.typesMapOutput, content); -})); - -file(Paths.builtDiagnosticGeneratedJson, [Paths.diagnosticGeneratedJson], function () { - if (fs.existsSync(Paths.builtLocal)) { - jake.cpR(Paths.diagnosticGeneratedJson, Paths.builtDiagnosticGeneratedJson); - } -}); - -// Localized diagnostics -file(Paths.generatedLCGFile, [TaskNames.scripts, Paths.diagnosticInformationMap, Paths.diagnosticGeneratedJson], function () { - const cmd = `${host} ${Paths.scripts.generateLocalizedDiagnosticMessages} ${Paths.lcl} ${Paths.builtLocal} ${Paths.diagnosticGeneratedJson}` - exec(cmd, complete); -}, { async: true }); - - -// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task -file(Paths.diagnosticInformationMap, [Paths.diagnosticMessagesJson], function () { - tsbuild(ConfigFileFor.scripts, true, () => { - const cmd = `${host} ${Paths.scripts.processDiagnosticMessages} ${Paths.diagnosticMessagesJson}`; - exec(cmd, complete); - }); -}, { async: true }); - -file(ConfigFileFor.tsserverLibrary, [], function () { - flatten("src/tsserver/tsconfig.json", ConfigFileFor.tsserverLibrary, { - exclude: ["src/tsserver/server.ts"], - compilerOptions: { - "removeComments": false, - "stripInternal": true, - "declarationMap": false, - "outFile": "tsserverlibrary.out.js" - } - }) -}); - -// tsserverlibrary.js -// tsserverlibrary.d.ts -file(Paths.tsserverLibraryFile, [TaskNames.coreBuild, ConfigFileFor.tsserverLibrary], function() { - tsbuild(ConfigFileFor.tsserverLibrary, false, () => { - if (needsUpdate([Paths.tsserverLibraryOutFile, Paths.tsserverLibraryDefinitionOutFile], [Paths.tsserverLibraryFile, Paths.tsserverLibraryDefinitionFile])) { - const copyright = readFileSync(Paths.copyright); - - let libraryDefinitionContent = readFileSync(Paths.tsserverLibraryDefinitionOutFile); - libraryDefinitionContent = copyright + removeConstModifierFromEnumDeclarations(libraryDefinitionContent); - libraryDefinitionContent += "\nexport = ts;\nexport as namespace ts;"; - fs.writeFileSync(Paths.tsserverLibraryDefinitionFile, libraryDefinitionContent, "utf8"); - - let libraryContent = readFileSync(Paths.tsserverLibraryOutFile); - libraryContent = copyright + libraryContent; - fs.writeFileSync(Paths.tsserverLibraryFile, libraryContent, "utf8"); - - // adjust source map for tsserverlibrary.js - let libraryMapContent = readFileSync(Paths.tsserverLibraryOutFile + ".map"); - const map = JSON.parse(libraryMapContent); - const lineStarts = /**@type {*}*/(ts).computeLineStarts(copyright); - let prependMappings = ""; - for (let i = 1; i < lineStarts.length; i++) { - prependMappings += ";"; - } - - const offset = copyright.length - lineStarts[lineStarts.length - 1]; - if (offset > 0) { - prependMappings += base64VLQFormatEncode(offset) + ","; - } - - const outputMap = { - version: map.version, - file: map.file, - sources: map.sources, - sourceRoot: map.sourceRoot, - mappings: prependMappings + map.mappings, - names: map.names, - sourcesContent: map.sourcesContent - }; - - libraryMapContent = JSON.stringify(outputMap); - fs.writeFileSync(Paths.tsserverLibraryFile + ".map", libraryMapContent); - } - complete(); - }); -}, { async: true }); -task(Paths.tsserverLibraryDefinitionFile, [Paths.tsserverLibraryFile]); - -file(ConfigFileFor.typescriptServices, [], function () { - flatten("src/services/tsconfig.json", ConfigFileFor.typescriptServices, { - compilerOptions: { - "removeComments": false, - "stripInternal": true, - "declarationMap": false, - "outFile": "typescriptServices.out.js" - } - }); -}); - -// typescriptServices.js -// typescriptServices.d.ts -file(Paths.servicesFile, [TaskNames.coreBuild, ConfigFileFor.typescriptServices], function() { - tsbuild(ConfigFileFor.typescriptServices, false, () => { - if (needsUpdate([Paths.servicesOutFile, Paths.servicesDefinitionOutFile], [Paths.servicesFile, Paths.servicesDefinitionFile])) { - const copyright = readFileSync(Paths.copyright); - - let servicesDefinitionContent = readFileSync(Paths.servicesDefinitionOutFile); - servicesDefinitionContent = copyright + removeConstModifierFromEnumDeclarations(servicesDefinitionContent); - fs.writeFileSync(Paths.servicesDefinitionFile, servicesDefinitionContent, "utf8"); - - let servicesContent = readFileSync(Paths.servicesOutFile); - servicesContent = copyright + servicesContent; - fs.writeFileSync(Paths.servicesFile, servicesContent, "utf8"); - - // adjust source map for typescriptServices.js - let servicesMapContent = readFileSync(Paths.servicesOutFile + ".map"); - const map = JSON.parse(servicesMapContent); - const lineStarts = /**@type {*}*/(ts).computeLineStarts(copyright); - let prependMappings = ""; - for (let i = 1; i < lineStarts.length; i++) { - prependMappings += ";"; - } - - const offset = copyright.length - lineStarts[lineStarts.length - 1]; - if (offset > 0) { - prependMappings += base64VLQFormatEncode(offset) + ","; - } - - const outputMap = { - version: map.version, - file: map.file, - sources: map.sources, - sourceRoot: map.sourceRoot, - mappings: prependMappings + map.mappings, - names: map.names, - sourcesContent: map.sourcesContent - }; - - servicesMapContent = JSON.stringify(outputMap); - fs.writeFileSync(Paths.servicesFile + ".map", servicesMapContent); - } - - complete(); - }); -}, { async: true }); -task(Paths.servicesDefinitionFile, [Paths.servicesFile]); - -// typescript.js -// typescript.d.ts -file(Paths.typescriptFile, [Paths.servicesFile], function() { - if (needsUpdate([Paths.servicesFile, Paths.servicesDefinitionFile], [Paths.typescriptFile, Paths.typescriptDefinitionFile])) { - jake.cpR(Paths.servicesFile, Paths.typescriptFile); - if (fs.existsSync(Paths.servicesFile + ".map")) { - jake.cpR(Paths.servicesFile + ".map", Paths.typescriptFile + ".map"); - } - const content = readFileSync(Paths.servicesDefinitionFile); - fs.writeFileSync(Paths.typescriptDefinitionFile, content + "\r\nexport = ts;", { encoding: "utf-8" }); - } -}); -task(Paths.typescriptDefinitionFile, [Paths.typescriptFile]); - -// typescript_standalone.d.ts -file(Paths.typescriptStandaloneDefinitionFile, [Paths.servicesDefinitionFile], function() { - if (needsUpdate(Paths.servicesDefinitionFile, Paths.typescriptStandaloneDefinitionFile)) { - const content = readFileSync(Paths.servicesDefinitionFile); - fs.writeFileSync(Paths.typescriptStandaloneDefinitionFile, content.replace(/declare (namespace|module) ts(\..+)? \{/g, 'declare module "typescript" {'), { encoding: "utf-8"}); - } -}); - -function getLibraryTargets() { - /** @type {{ libs: string[], paths?: Record, sources?: Record }} */ - const libraries = readJson("./src/lib/libs.json"); - return libraries.libs.map(function (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 = [Paths.copyright].concat(relativeSources.map(s => path.join(Paths.library, s))); - const target = path.join(Paths.builtLocal, relativeTarget); - file(target, [Paths.builtLocal].concat(sources), function () { - concatenateFiles(target, sources); - }); - return target; - }); -} - -function runConsoleTests(defaultReporter, runInParallel) { - var dirty = process.env.dirty; - if (!dirty) { - cleanTestDirs(); - } - - let testTimeout = process.env.timeout || defaultTestTimeout; - const inspect = process.env.inspect || process.env["inspect-brk"] || process.env.i; - const runners = process.env.runners || process.env.runner || process.env.ru; - const tests = process.env.test || process.env.tests || process.env.t; - const light = process.env.light === undefined || process.env.light !== "false"; - const failed = process.env.failed; - const keepFailed = process.env.keepFailed || failed; - const stackTraceLimit = process.env.stackTraceLimit; - const colorsFlag = process.env.color || process.env.colors; - const colors = colorsFlag !== "false" && colorsFlag !== "0"; - const reporter = process.env.reporter || process.env.r || defaultReporter; - const bail = process.env.bail || process.env.b; - const lintFlag = process.env.lint !== 'false'; - const testConfigFile = 'test.config'; - - if (fs.existsSync(testConfigFile)) { - fs.unlinkSync(testConfigFile); - } - - let workerCount, taskConfigsFolder; - if (runInParallel) { - // generate name to store task configuration files - const prefix = os.tmpdir() + "/ts-tests"; - let i = 1; - do { - taskConfigsFolder = prefix + i; - i++; - } while (fs.existsSync(taskConfigsFolder)); - fs.mkdirSync(taskConfigsFolder); - - workerCount = process.env.workerCount || process.env.p || os.cpus().length; - } - - if (tests && tests.toLocaleLowerCase() === "rwc") { - testTimeout = 800000; - } - - if (tests || runners || light || testTimeout || taskConfigsFolder || keepFailed) { - writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors, testTimeout, keepFailed); - } - - // 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 - if (!runInParallel) { - var startTime = Travis.mark(); - var args = []; - args.push("-R", "scripts/failed-tests"); - args.push("-O", '"reporter=' + reporter + (keepFailed ? ",keepFailed=true" : "") + '"'); - if (tests) args.push("-g", `"${tests}"`); - args.push(colors ? "--colors" : "--no-colors"); - if (bail) args.push("--bail"); - if (inspect) { - args.unshift("--inspect-brk"); - } else { - args.push("-t", testTimeout); - } - args.push(Paths.builtLocalRun); - - var cmd; - if (failed) { - args.unshift("scripts/run-failed-tests.js"); - cmd = host + " " + args.join(" "); - } - else { - cmd = "mocha " + args.join(" "); - } - var savedNodeEnv = process.env.NODE_ENV; - process.env.NODE_ENV = "development"; - exec(cmd, function () { - process.env.NODE_ENV = savedNodeEnv; - Travis.measure(startTime); - runLinterAndComplete(); - }, function (e, status) { - process.env.NODE_ENV = savedNodeEnv; - Travis.measure(startTime); - finish(status); - }); - } - else { - var savedNodeEnv = process.env.NODE_ENV; - process.env.NODE_ENV = "development"; - var startTime = Travis.mark(); - const cmd = `${host} ${Paths.builtLocalRun}`; - exec(cmd, function () { - // Tests succeeded; run 'lint' task - process.env.NODE_ENV = savedNodeEnv; - Travis.measure(startTime); - runLinterAndComplete(); - }, function (e, status) { - // Tests failed - process.env.NODE_ENV = savedNodeEnv; - Travis.measure(startTime); - finish(status); - }); - } - - function finish(errorStatus) { - deleteTemporaryProjectOutput(); - if (errorStatus !== undefined) { - fail("Process exited with code " + errorStatus); - } - else { - complete(); - } - } - - function runLinterAndComplete() { - if (!lintFlag || dirty) { - return finish(); - } - var lint = jake.Task['lint']; - lint.once('complete', function () { - finish(); - }); - lint.invoke(); - } - - function deleteTemporaryProjectOutput() { - if (fs.existsSync(path.join(Paths.baselines.local, "projectOutput/"))) { - jake.rmRf(path.join(Paths.baselines.local, "projectOutput/")); - } - } -} - -// used to pass data from jake command line directly to run.js -function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors, testTimeout, keepFailed) { - 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, - keepFailed: keepFailed - }); - fs.writeFileSync('test.config', testConfigContents, { encoding: "utf-8" }); -} - -function cleanTestDirs() { - // Clean the local baselines directory - if (fs.existsSync(Paths.baselines.local)) { - del.sync(Paths.baselines.local); - } - - // Clean the local Rwc baselines directory - if (fs.existsSync(Paths.baselines.localRwc)) { - del.sync(Paths.baselines.localRwc); - } - - jake.mkdirP(Paths.baselines.local); - jake.mkdirP(Paths.baselines.localTest262); -} - -function tsbuild(tsconfigPath, useLkg = true, done = undefined) { - const startCompileTime = Travis.mark(); - const compilerPath = useLkg ? Paths.lkgCompiler : Paths.builtLocalCompiler; - const cmd = `${host} ${compilerPath} -b ${Array.isArray(tsconfigPath) ? tsconfigPath.join(" ") : tsconfigPath}`; - - exec(cmd, () => { - // Success - Travis.measure(startCompileTime); - done ? done() : complete(); - }, () => { - // Fail - Travis.measure(startCompileTime); - fail(`Compilation of ${tsconfigPath} unsuccessful`); - }); -} - -const Travis = { - 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 - }; - }, - 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"); - } -}; - -function toNs(diff) { - return diff[0] * 1e9 + diff[1]; -} - -function exec(cmd, successHandler, 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 (successHandler) { - successHandler(); - } - }); - ex.addListener("error", function (e, status) { - if (errorHandler) { - errorHandler(e, status); - } - else { - fail("Process exited with code " + status); - } - }); - - console.log(cmd); - ex.run(); -} - -function acceptBaseline(sourceFolder, targetFolder) { - console.log('Accept baselines from ' + sourceFolder + ' to ' + targetFolder); - var deleteEnding = '.delete'; - - jake.mkdirP(targetFolder); - 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)); - } - } - } -} - -/** @param jsonPath {string} */ -function readJson(jsonPath) { - const jsonText = readFileSync(jsonPath); - const result = ts.parseConfigFileTextToJson(jsonPath, jsonText); - if (result.error) { - reportDiagnostics([result.error]); - throw new Error("An error occurred during parse."); - } - return result.config; -} - -/** @param diagnostics {ts.Diagnostic[]} */ -function reportDiagnostics(diagnostics) { - console.log(diagnosticsToString(diagnostics, process.stdout.isTTY)); -} - -/** - * @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); -} - -/** - * Concatenate a list of sourceFiles to a destinationFile - * @param {string} destinationFile - * @param {string[]} sourceFiles - * @param {string=} extraContent - */ -function concatenateFiles(destinationFile, sourceFiles, extraContent) { - 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 += readFileSync(sourceFiles[i]).replace(/\r?\n/g, "\n"); - } - if (extraContent) { - text += extraContent; - } - fs.writeFileSync(temp, text); - // Move the file to the final destination - fs.renameSync(temp, destinationFile); -} - -function appendToFile(path, content) { - fs.writeFileSync(path, readFileSync(path) + "\r\n" + content); -} - -/** - * - * @param {string} path - * @returns string - */ -function readFileSync(path) { - return fs.readFileSync(path, { encoding: "utf-8" }); -} - -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; -} - -/** - * Replaces const enum declarations with non-const enums - * @param {string} text - */ -function removeConstModifierFromEnumDeclarations(text) { - return text.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4'); -} \ No newline at end of file diff --git a/README.md b/README.md index a7222668ada59..3b20af2d39848 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://travis-ci.org/Microsoft/TypeScript.svg?branch=master)](https://travis-ci.org/Microsoft/TypeScript) -[![VSTS Build Status](https://typescript.visualstudio.com/_apis/public/build/definitions/cf7ac146-d525-443c-b23c-0d58337efebc/4/badge)](https://typescript.visualstudio.com/TypeScript/_build/latest?definitionId=4&view=logs) +[![VSTS Build Status](https://dev.azure.com/typescript/TypeScript/_apis/build/status/Typescript/node10)](https://dev.azure.com/typescript/TypeScript/_build/latest?definitionId=4&view=logs) [![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript) [![Downloads](https://img.shields.io/npm/dm/typescript.svg)](https://www.npmjs.com/package/typescript) @@ -61,29 +61,29 @@ Change to the TypeScript directory: cd TypeScript ``` -Install [Jake](http://jakejs.com/) tools and dev dependencies: +Install [Gulp](https://gulpjs.com/) tools and dev dependencies: ```bash -npm install -g jake +npm install -g gulp npm install ``` Use one of the following to build and test: ``` -jake local # Build the compiler into built/local -jake clean # Delete the built compiler -jake LKG # Replace the last known good with the built one. +gulp local # Build the compiler into built/local +gulp clean # Delete the built compiler +gulp LKG # Replace the last known good with the built one. # Bootstrapping step to be executed when the built compiler reaches a stable state. -jake tests # Build the test infrastructure using the built compiler. -jake runtests # Run tests using the built compiler and test infrastructure. +gulp tests # Build the test infrastructure using the built compiler. +gulp runtests # Run tests using the built compiler and test infrastructure. # You can override the host or specify a test for this command. - # Use host= or tests=. -jake runtests-browser # Runs the tests using the built run.js file. Syntax is jake runtests. Optional - parameters 'host=', 'tests=[regex], reporter=[list|spec|json|]'. -jake baseline-accept # This replaces the baseline test results with the results obtained from jake runtests. -jake lint # Runs tslint on the TypeScript source. -jake help # List the above commands. + # Use --host= or --tests=. +gulp runtests-browser # Runs the tests using the built run.js file. Syntax is gulp runtests. Optional + parameters '--host=', '--tests=[regex], --reporter=[list|spec|json|]'. +gulp baseline-accept # This replaces the baseline test results with the results obtained from gulp runtests. +gulp lint # Runs tslint on the TypeScript source. +gulp help # List the above commands. ``` diff --git a/doc/spec.md b/doc/spec.md index c6dd8cb4d065f..741d4f29ceceb 100644 --- a/doc/spec.md +++ b/doc/spec.md @@ -239,7 +239,7 @@ TypeScript is a trademark of Microsoft Corporation. # 1 Introduction -JavaScript applications such as web e-mail, maps, document editing, and collaboration tools are becoming an increasingly important part of the everyday computing. We designed TypeScript to meet the needs of the JavaScript programming teams that build and maintain large JavaScript programs. TypeScript helps programming teams to define interfaces between software components and to gain insight into the behavior of existing JavaScript libraries. TypeScript also enables teams to reduce naming conflicts by organizing their code into dynamically-loadable modules. TypeScript's optional type system enables JavaScript programmers to use highly-productive development tools and practices: static checking, symbol-based navigation, statement completion, and code re-factoring. +JavaScript applications such as web e-mail, maps, document editing, and collaboration tools are becoming an increasingly important part of the everyday computing. We designed TypeScript to meet the needs of the JavaScript programming teams that build and maintain large JavaScript programs. TypeScript helps programming teams to define interfaces between software components and to gain insight into the behavior of existing JavaScript libraries. TypeScript also enables teams to reduce naming conflicts by organizing their code into dynamically-loadable modules. TypeScript's optional type system enables JavaScript programmers to use highly-productive development tools and practices: static checking, symbol-based navigation, statement completion, and code refactoring. TypeScript is a syntactic sugar for JavaScript. TypeScript syntax is a superset of ECMAScript 2015 (ES2015) syntax. Every JavaScript program is also a TypeScript program. The TypeScript compiler performs only file-local transformations on TypeScript programs and does not re-order variables declared in TypeScript. This leads to JavaScript output that closely matches the TypeScript input. TypeScript does not transform variable names, making tractable the direct debugging of emitted JavaScript. TypeScript optionally provides source maps, enabling source-level debugging. TypeScript tools typically emit JavaScript upon file save, preserving the test, edit, refresh cycle commonly used in JavaScript development. @@ -263,7 +263,7 @@ function f() { } ``` -To benefit from this inference, a programmer can use the TypeScript language service. For example, a code editor can incorporate the TypeScript language service and use the service to find the members of a string object as in the following screen shot. +To benefit from this inference, a programmer can use the TypeScript language service. For example, a code editor can incorporate the TypeScript language service and use the service to find the members of a string object as in the following screenshot.   ![](images/image1.png) @@ -411,7 +411,7 @@ We mentioned above that the '$' function behaves differently depending on the ty This signature denotes that a function may be passed as the parameter of the '$' function. When a function is passed to '$', the jQuery library will invoke that function when a DOM document is ready. Because TypeScript supports overloading, tools can use TypeScript to show all available function signatures with their documentation tips and to give the correct documentation once a function has been called with a particular signature. -A typical client would not need to add any additional typing but could just use a community-supplied typing to discover (through statement completion with documentation tips) and verify (through static checking) correct use of the library, as in the following screen shot. +A typical client would not need to add any additional typing but could just use a community-supplied typing to discover (through statement completion with documentation tips) and verify (through static checking) correct use of the library, as in the following screenshot.   ![](images/image2.png) @@ -628,7 +628,7 @@ JavaScript implementations can use these explicit constants to generate efficien An important goal of TypeScript is to provide accurate and straightforward types for existing JavaScript programming patterns. To that end, TypeScript includes generic types, discussed in the next section, and *overloading on string parameters*, the topic of this section. -JavaScript programming interfaces often include functions whose behavior is discriminated by a string constant passed to the function. The Document Object Model makes heavy use of this pattern. For example, the following screen shot shows that the 'createElement' method of the 'document' object has multiple signatures, some of which identify the types returned when specific strings are passed into the method. +JavaScript programming interfaces often include functions whose behavior is discriminated by a string constant passed to the function. The Document Object Model makes heavy use of this pattern. For example, the following screenshot shows that the 'createElement' method of the 'document' object has multiple signatures, some of which identify the types returned when specific strings are passed into the method.   ![](images/image3.png) @@ -639,7 +639,7 @@ var span = document.createElement("span"); span.isMultiLine = false; // OK: HTMLSpanElement has isMultiline property ``` -In the following screen shot, a programming tool combines information from overloading on string parameters with contextual typing to infer that the type of the variable 'e' is 'MouseEvent' and that therefore 'e' has a 'clientX' property. +In the following screenshot, a programming tool combines information from overloading on string parameters with contextual typing to infer that the type of the variable 'e' is 'MouseEvent' and that therefore 'e' has a 'clientX' property.   ![](images/image4.png) @@ -3715,7 +3715,7 @@ the array literal initializer expression is contextually typed by the implied ty ## 5.3 Let and Const Declarations -Let and const declarations are exended to include optional type annotations. +Let and const declarations are extended to include optional type annotations.   *LexicalBinding:* *( Modified )*    *SimpleLexicalBinding* diff --git a/lib/README.md b/lib/README.md index 0a85a9e7b5c80..ce0455fa40d3c 100644 --- a/lib/README.md +++ b/lib/README.md @@ -2,4 +2,4 @@ **These files are not meant to be edited by hand.** If you need to make modifications, the respective files should be changed within the repository's top-level `src` directory. -Running `jake LKG` will then appropriately update the files in this directory. +Running `gulp LKG` will then appropriately update the files in this directory. diff --git a/lib/enu/diagnosticMessages.generated.json.lcg b/lib/enu/diagnosticMessages.generated.json.lcg index 61eb41991c457..0b66fd7760cc0 100644 --- a/lib/enu/diagnosticMessages.generated.json.lcg +++ b/lib/enu/diagnosticMessages.generated.json.lcg @@ -27,6 +27,18 @@ + + + + + + + + + + + + @@ -129,6 +141,12 @@ + + + + + + @@ -321,6 +339,18 @@ + + + + + + + + + + + + @@ -849,12 +879,6 @@ - - - - - - @@ -1005,6 +1029,12 @@ + + + + + + @@ -1329,6 +1359,12 @@ + + + + + + @@ -1487,17 +1523,35 @@ - + + + + + + + - + + + + + + + - + + + + + + + @@ -1599,6 +1653,12 @@ + + + + + + @@ -1629,6 +1689,12 @@ + + + + + + @@ -1707,6 +1773,12 @@ + + + + + + @@ -1821,6 +1893,12 @@ + + + + + + @@ -1983,6 +2061,12 @@ + + + + + + @@ -2235,12 +2319,6 @@ - - - - - - @@ -2307,6 +2385,12 @@ + + + + + + @@ -2373,6 +2457,12 @@ + + + + + + @@ -2403,6 +2493,12 @@ + + + + + + @@ -2655,6 +2751,12 @@ + + + + + + @@ -3189,12 +3291,6 @@ - - - - - - @@ -3741,12 +3837,6 @@ - - - - - - @@ -3867,6 +3957,12 @@ + + + + + + @@ -4137,12 +4233,6 @@ - - - - - - @@ -4437,6 +4527,18 @@ + + + + + + + + + + + + @@ -4671,6 +4773,12 @@ + + + + + + @@ -4773,6 +4881,12 @@ + + + + + + @@ -5271,9 +5385,9 @@ - + - + @@ -5283,6 +5397,12 @@ + + + + + + @@ -5511,9 +5631,9 @@ - + - + @@ -5571,6 +5691,12 @@ + + + + + + @@ -5805,6 +5931,18 @@ + + + + + + + + + + + + @@ -5823,6 +5961,18 @@ + + + + + + + + + + + + @@ -5871,9 +6021,9 @@ - + - + @@ -5907,18 +6057,6 @@ - - - - - - - - - - - - @@ -5949,12 +6087,6 @@ - - - - - - @@ -6081,6 +6213,12 @@ + + + + + + @@ -6159,6 +6297,12 @@ + + + + + + @@ -6189,6 +6333,12 @@ + + + + + + @@ -6381,12 +6531,24 @@ + + + + + + + + + + + + @@ -6519,6 +6681,12 @@ + + + + + + @@ -6693,6 +6861,12 @@ + + + + + + @@ -6789,6 +6963,12 @@ + + + + + + @@ -6999,6 +7179,12 @@ + + + + + + diff --git a/lib/lib.dom.d.ts b/lib/lib.dom.d.ts index 464dea83926b4..7817a0e426704 100644 --- a/lib/lib.dom.d.ts +++ b/lib/lib.dom.d.ts @@ -203,6 +203,10 @@ interface ClientQueryOptions { type?: ClientTypes; } +interface ClipboardEventInit extends EventInit { + clipboardData?: DataTransfer | null; +} + interface CloseEventInit extends EventInit { code?: number; reason?: string; @@ -448,6 +452,10 @@ interface EventModifierInit extends UIEventInit { shiftKey?: boolean; } +interface EventSourceInit { + withCredentials?: boolean; +} + interface ExceptionInformation { domain?: string | null; } @@ -479,12 +487,16 @@ interface FocusOptions { preventScroll?: boolean; } +interface FullscreenOptions { + navigationUI?: FullscreenNavigationUI; +} + interface GainOptions extends AudioNodeOptions { gain?: number; } interface GamepadEventInit extends EventInit { - gamepad?: Gamepad; + gamepad: Gamepad; } interface GetNotificationOptions { @@ -619,15 +631,17 @@ interface MediaEncryptedEventInit extends EventInit { } interface MediaKeyMessageEventInit extends EventInit { - message?: ArrayBuffer | null; - messageType?: MediaKeyMessageType; + message: ArrayBuffer; + messageType: MediaKeyMessageType; } interface MediaKeySystemConfiguration { audioCapabilities?: MediaKeySystemMediaCapability[]; distinctiveIdentifier?: MediaKeysRequirement; initDataTypes?: string[]; + label?: string; persistentState?: MediaKeysRequirement; + sessionTypes?: string[]; videoCapabilities?: MediaKeySystemMediaCapability[]; } @@ -744,6 +758,8 @@ interface MouseEventInit extends EventModifierInit { buttons?: number; clientX?: number; clientY?: number; + movementX?: number; + movementY?: number; relatedTarget?: EventTarget | null; screenX?: number; screenY?: number; @@ -1462,6 +1478,11 @@ interface ServiceWorkerMessageEventInit extends EventInit { source?: ServiceWorker | MessagePort | null; } +interface ShadowRootInit { + delegatesFocus?: boolean; + mode: ShadowRootMode; +} + interface StereoPannerOptions extends AudioNodeOptions { pan?: number; } @@ -1629,6 +1650,7 @@ interface EventListener { (evt: Event): void; } +/** The ANGLE_instanced_arrays extension is part of the WebGL API and allows to draw the same object, or groups of similar objects multiple times, if they share the same vertex data, primitive count and type. */ interface ANGLE_instanced_arrays { drawArraysInstancedANGLE(mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei): void; drawElementsInstancedANGLE(mode: GLenum, count: GLsizei, type: GLenum, offset: GLintptr, primcount: GLsizei): void; @@ -1636,6 +1658,7 @@ interface ANGLE_instanced_arrays { readonly VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: GLenum; } +/** The AbortController interface represents a controller object that allows you to abort one or more DOM requests as and when desired. */ interface AbortController { /** * Returns the AbortSignal object associated with this object. @@ -1654,16 +1677,17 @@ declare var AbortController: { }; interface AbortSignalEventMap { - "abort": ProgressEvent; + "abort": Event; } +/** The AbortSignal interface represents a signal object that allows you to communicate with a DOM request (such as a Fetch) and abort it if required via an AbortController object. */ interface AbortSignal extends EventTarget { /** * Returns true if this AbortSignal's AbortController has signaled to abort, and false * otherwise. */ readonly aborted: boolean; - onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null; + onabort: ((this: AbortSignal, ev: Event) => any) | null; addEventListener(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -1708,6 +1732,7 @@ interface AesCmacParams extends Algorithm { length: number; } +/** The AnalyserNode interface represents a node able to provide real-time frequency and time-domain analysis information. It is an AudioNode that passes the audio stream unchanged from the input to the output, but allows you to take the generated data, process it, and create audio visualizations. */ interface AnalyserNode extends AudioNode { fftSize: number; readonly frequencyBinCount: number; @@ -1776,6 +1801,7 @@ declare var AnimationEffect: { new(): AnimationEffect; }; +/** The AnimationEvent interface represents events providing information related to animations. */ interface AnimationEvent extends Event { readonly animationName: string; readonly elapsedTime: number; @@ -1865,6 +1891,7 @@ declare var ApplicationCache: { readonly UPDATEREADY: number; }; +/** This type represents a DOM element's attribute as an object. In most DOM methods, you will probably directly retrieve the attribute as a string (e.g., Element.getAttribute(), but certain functions (e.g., Element.getAttributeNode()) or means of iterating give Attr types. */ interface Attr extends Node { readonly localName: string; readonly name: string; @@ -1880,6 +1907,7 @@ declare var Attr: { new(): Attr; }; +/** Objects of these types are designed to hold small audio snippets, typically less than 45 s. For longer sounds, objects implementing the MediaElementAudioSourceNode are more suitable. The buffer contains data in the following format:  non-interleaved IEEE754 32-bit linear PCM with a nominal range between -1 and +1, that is, 32bits floating point buffer, with each samples between -1.0 and 1.0. If the AudioBuffer has multiple channels, they are stored in separate buffer. */ interface AudioBuffer { readonly duration: number; readonly length: number; @@ -1895,6 +1923,7 @@ declare var AudioBuffer: { new(options: AudioBufferOptions): AudioBuffer; }; +/** The AudioBufferSourceNode interface is an AudioScheduledSourceNode which represents an audio source consisting of in-memory audio data, stored in an AudioBuffer. It's especially useful for playing back audio which has particularly stringent timing accuracy requirements, such as for sounds that must match a specific rhythm and can be kept in memory rather than being played from disk or the network. */ interface AudioBufferSourceNode extends AudioScheduledSourceNode { buffer: AudioBuffer | null; readonly detune: AudioParam; @@ -1914,6 +1943,7 @@ declare var AudioBufferSourceNode: { new(context: BaseAudioContext, options?: AudioBufferSourceOptions): AudioBufferSourceNode; }; +/** The AudioContext interface represents an audio-processing graph built from audio modules linked together, each represented by an AudioNode. */ interface AudioContext extends BaseAudioContext { readonly baseLatency: number; readonly outputLatency: number; @@ -1935,6 +1965,7 @@ declare var AudioContext: { new(contextOptions?: AudioContextOptions): AudioContext; }; +/** AudioDestinationNode has no output (as it is the output, no more AudioNode can be linked after it in the audio graph) and one input. The number of channels in the input must be between 0 and the maxChannelCount value or an exception is raised. */ interface AudioDestinationNode extends AudioNode { readonly maxChannelCount: number; } @@ -1944,6 +1975,7 @@ declare var AudioDestinationNode: { new(): AudioDestinationNode; }; +/** The AudioListener interface represents the position and orientation of the unique person listening to the audio scene, and is used in audio spatialization. All PannerNodes spatialize in relation to the AudioListener stored in the BaseAudioContext.listener attribute. */ interface AudioListener { readonly forwardX: AudioParam; readonly forwardY: AudioParam; @@ -1965,6 +1997,7 @@ declare var AudioListener: { new(): AudioListener; }; +/** The AudioNode interface is a generic interface for representing an audio processing module. Examples include: */ interface AudioNode extends EventTarget { channelCount: number; channelCountMode: ChannelCountMode; @@ -1988,6 +2021,7 @@ declare var AudioNode: { new(): AudioNode; }; +/** The Web Audio API's AudioParam interface represents an audio-related parameter, usually a parameter of an AudioNode (such as GainNode.gain). */ interface AudioParam { automationRate: AutomationRate; readonly defaultValue: number; @@ -2017,6 +2051,7 @@ declare var AudioParamMap: { new(): AudioParamMap; }; +/** The Web Audio API AudioProcessingEvent represents events that occur when a ScriptProcessorNode input buffer is ready to be processed. */ interface AudioProcessingEvent extends Event { readonly inputBuffer: AudioBuffer; readonly outputBuffer: AudioBuffer; @@ -2047,13 +2082,14 @@ declare var AudioScheduledSourceNode: { new(): AudioScheduledSourceNode; }; +/** The AudioTrack interface represents a single audio track from one of the HTML media elements,