Merge remote-tracking branch 'origin/master' into enforce-const-enum-access-for-isolatedmodules

This commit is contained in:
Alan Pierce 2019-02-01 16:56:44 -08:00
commit 942b020081
224 changed files with 72677 additions and 4114 deletions

View file

@ -16,7 +16,7 @@ Please fill in the *entire* template below.
-->
<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:** 3.3.0-dev.201xxxxx
**TypeScript Version:** 3.4.0-dev.201xxxxx
<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**

File diff suppressed because it is too large Load diff

View file

@ -8,10 +8,8 @@ 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 { getDirSize, needsUpdate, flatten } = require("./scripts/build/utils");
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;
@ -361,7 +359,7 @@ file(ConfigFileFor.tsserverLibrary, [], function () {
compilerOptions: {
"removeComments": false,
"stripInternal": true,
"declarationMap": false,
"declaration": true,
"outFile": "tsserverlibrary.out.js"
}
})

View file

@ -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://dev.azure.com/typescript/TypeScript/_apis/build/status/Typescript/node10)](https://https://dev.azure.com/typescript/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)

View file

@ -3715,7 +3715,7 @@ the array literal initializer expression is contextually typed by the implied ty
## <a name="5.3"/>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.
&emsp;&emsp;*LexicalBinding:* *( Modified )*
&emsp;&emsp;&emsp;*SimpleLexicalBinding*

View file

@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "https://www.typescriptlang.org/",
"version": "3.3.0",
"version": "3.4.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
@ -35,10 +35,8 @@
"@types/convert-source-map": "latest",
"@types/del": "latest",
"@types/glob": "latest",
"@types/gulp": "3.X",
"@types/gulp": "^4.0.5",
"@types/gulp-concat": "latest",
"@types/gulp-help": "latest",
"@types/gulp-if": "0.0.33",
"@types/gulp-newer": "latest",
"@types/gulp-rename": "0.0.33",
"@types/gulp-sourcemaps": "0.0.32",
@ -50,7 +48,6 @@
"@types/mocha": "latest",
"@types/node": "8.5.5",
"@types/q": "latest",
"@types/run-sequence": "latest",
"@types/source-map-support": "latest",
"@types/through2": "latest",
"@types/travis-fold": "latest",
@ -63,16 +60,12 @@
"del": "latest",
"fancy-log": "latest",
"fs-extra": "^6.0.1",
"gulp": "3.X",
"gulp-clone": "latest",
"gulp": "^4.0.0",
"gulp-concat": "latest",
"gulp-help": "latest",
"gulp-if": "latest",
"gulp-insert": "latest",
"gulp-newer": "latest",
"gulp-rename": "latest",
"gulp-sourcemaps": "latest",
"gulp-typescript": "latest",
"istanbul": "latest",
"jake": "latest",
"lodash": "4.17.10",
@ -86,7 +79,6 @@
"prex": "^0.4.3",
"q": "latest",
"remove-internal": "^2.9.2",
"run-sequence": "latest",
"source-map-support": "latest",
"through2": "latest",
"travis-fold": "latest",

View file

@ -1,24 +0,0 @@
// @ts-check
const merge2 = require("merge2");
const gulp = require("./gulp");
const rename = require("gulp-rename");
const rm = require("./rm");
const { localBaseline, refBaseline } = require("./tests");
module.exports = baselineAccept;
function baselineAccept(subfolder = "") {
return merge2(baselineCopy(subfolder), baselineDelete(subfolder));
}
function baselineCopy(subfolder = "") {
return gulp.src([`${localBaseline}${subfolder ? `${subfolder}/` : ``}**`, `!${localBaseline}${subfolder}/**/*.delete`], { base: localBaseline })
.pipe(gulp.dest(refBaseline));
}
function baselineDelete(subfolder = "") {
return gulp.src([`${localBaseline}${subfolder ? `${subfolder}/` : ``}**/*.delete`], { base: localBaseline, read: false })
.pipe(rm())
.pipe(rename({ extname: "" }))
.pipe(rm(refBaseline));
}

View file

@ -1,12 +1,10 @@
// @ts-check
const browserify = require("browserify");
const Vinyl = require("./vinyl");
const Vinyl = require("vinyl");
const { Transform } = require("stream");
const { streamFromFile } = require("./utils");
const { replaceContents } = require("./sourcemaps");
module.exports = browserifyFile;
/**
* @param {import("browserify").Options} [opts]
*/
@ -31,4 +29,5 @@ function browserifyFile(opts) {
}
}
});
}
}
exports.browserify = browserifyFile;

View file

@ -1,5 +0,0 @@
// @ts-check
// this just fixes the incorrect types for chalk :/
const chalk = /**@type {import("chalk").Chalk}*/(require("chalk").default || require("chalk"));
module.exports = chalk;

View file

@ -1,19 +0,0 @@
// @ts-check
const replace = require("./replace");
module.exports = exports = convertConstEnum;
/**
* This regexp exists to capture our const enums and replace them with normal enums in our public API
* - this is fine since we compile with preserveConstEnums, and ensures our consumers are not locked
* to the TS version they compile with.
*/
const constEnumCaptureRegexp = /^(\s*)(export )?const enum (\S+) {(\s*)$/gm;
const constEnumReplacement = "$1$2enum $3 {$4";
/**
* Converts `const enum` declarations in a .d.ts file into non-const `enum` declarations.
*/
function convertConstEnum() {
return replace(constEnumCaptureRegexp, constEnumReplacement);
}

View file

@ -1,31 +0,0 @@
// @ts-check
module.exports = debounce;
/**
* @param {() => void} cb
* @param {number} timeout
* @param {DebounceOptions} [opts]
*
* @typedef DebounceOptions
* @property {number} [max]
*/
function debounce(cb, timeout, opts = {}) {
if (timeout < 10) timeout = 10;
let max = opts.max || 10;
if (max < timeout) max = timeout;
let minTimer;
let maxTimer;
return trigger;
function trigger() {
if (max > timeout && !maxTimer) maxTimer = setTimeout(done, max);
if (minTimer) clearTimeout(minTimer);
minTimer = setTimeout(done, timeout);
}
function done() {
if (maxTimer) maxTimer = void clearTimeout(maxTimer);
if (minTimer) minTimer = void clearTimeout(minTimer);
cb();
}
}

View file

@ -1,49 +0,0 @@
// @ts-check
const ts = require("../../lib/typescript");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
/** @type {FormatDiagnosticsHost} */
const formatDiagnosticsHost = exports.formatDiagnosticsHost = {
getCanonicalFileName: fileName => fileName,
getCurrentDirectory: () => process.cwd(),
getNewLine: () => ts.sys.newLine
};
/**
* @param {Diagnostic[]} diagnostics
* @param {{ cwd?: string, pretty?: boolean }} [options]
*/
function formatDiagnostics(diagnostics, options) {
return options && options.pretty
? ts.formatDiagnosticsWithColorAndContext(diagnostics, getFormatDiagnosticsHost(options && options.cwd))
: ts.formatDiagnostics(diagnostics, getFormatDiagnosticsHost(options && options.cwd));
}
exports.formatDiagnostics = formatDiagnostics;
/**
* @param {Diagnostic[]} diagnostics
* @param {{ cwd?: string }} [options]
*/
function reportDiagnostics(diagnostics, options) {
log(formatDiagnostics(diagnostics, { cwd: options && options.cwd, pretty: process.stdout.isTTY }));
}
exports.reportDiagnostics = reportDiagnostics;
/**
* @param {string | undefined} cwd
* @returns {FormatDiagnosticsHost}
*/
function getFormatDiagnosticsHost(cwd) {
if (!cwd || cwd === process.cwd()) return formatDiagnosticsHost;
return {
getCanonicalFileName: formatDiagnosticsHost.getCanonicalFileName,
getCurrentDirectory: () => cwd,
getNewLine: formatDiagnosticsHost.getNewLine
};
}
/**
* @typedef {import("../../lib/typescript").FormatDiagnosticsHost} FormatDiagnosticsHost
* @typedef {import("../../lib/typescript").Diagnostic} Diagnostic
*/
void 0;

View file

@ -1,58 +0,0 @@
// @ts-check
const cp = require("child_process");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const isWin = /^win/.test(process.platform);
const chalk = require("./chalk");
const { CancellationToken, CancelError } = require("prex");
module.exports = exec;
/**
* Executes the provided command once with the supplied arguments.
* @param {string} cmd
* @param {string[]} args
* @param {ExecOptions} [options]
*
* @typedef ExecOptions
* @property {boolean} [ignoreExitCode]
* @property {import("prex").CancellationToken} [cancelToken]
*/
function exec(cmd, args, options = {}) {
return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => {
const { ignoreExitCode, cancelToken = CancellationToken.none } = options;
cancelToken.throwIfCancellationRequested();
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
const subshellFlag = isWin ? "/c" : "-c";
const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
log(`> ${chalk.green(cmd)} ${args.join(" ")}`);
const proc = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true });
const registration = cancelToken.register(() => {
log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`);
proc.kill("SIGINT");
proc.kill("SIGTERM");
reject(new CancelError());
});
proc.on("exit", exitCode => {
registration.unregister();
if (exitCode === 0 || ignoreExitCode) {
resolve({ exitCode });
}
else {
reject(new Error(`Process exited with code: ${exitCode}`));
}
});
proc.on("error", error => {
registration.unregister();
reject(error);
});
}));
}
/**
* @param {string} cmd
*/
function possiblyQuote(cmd) {
return cmd.indexOf(" ") >= 0 ? `"${cmd}"` : cmd;
}

View file

@ -1,46 +0,0 @@
// @ts-check
module.exports = finished;
/**
* @param {NodeJS.ReadableStream | NodeJS.WritableStream} stream
* @returns {Promise<void>}
*/
function finished(stream) {
return new Promise((resolve, reject) => {
const readable = "readable" in stream && stream.readable;
const writable = "writable" in stream && stream.writable;
let countdown = 0;
const cleanup = () => {
if (readable) stream.removeListener("end", signal);
if (writable) stream.removeListener("finish", signal);
stream.removeListener("error", onerror);
};
const signal = () => {
if (countdown > 0) {
countdown--;
if (countdown === 0) {
cleanup();
resolve();
}
}
};
const onerror = (error) => {
if (countdown > 0) {
countdown = 0;
cleanup();
reject(error);
}
};
stream.once("error", onerror);
if (readable) {
countdown++;
stream.once("end", signal);
}
if (writable) {
countdown++;
stream.once("finish", signal);
}
if (countdown === 0) signal();
});
}

View file

@ -1,12 +0,0 @@
// @ts-check
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
module.exports = getDiffTool;
function getDiffTool() {
const program = process.env.DIFF;
if (!program) {
log.warn("Add the 'DIFF' environment variable to the path of the program you want to use.");
process.exit(1);
}
return program;
}

View file

@ -1,23 +0,0 @@
// @ts-check
const { lstatSync, readdirSync } = require("fs");
const { join } = require("path");
/**
* Find the size of a directory recursively.
* Symbolic links can cause a loop.
* @param {string} root
* @returns {number} bytes
*/
function getDirSize(root) {
const stats = lstatSync(root);
if (!stats.isDirectory()) {
return stats.size;
}
return readdirSync(root)
.map(file => getDirSize(join(root, file)))
.reduce((acc, num) => acc + num, 0);
}
module.exports = getDirSize;

View file

@ -1,149 +0,0 @@
// @ts-check
const path = require("path");
const child_process = require("child_process");
const fs = require("fs");
const tsc = require("gulp-typescript");
const Vinyl = require("vinyl");
const { Duplex, Readable } = require("stream");
const protocol = require("./protocol");
/**
* @param {string | undefined} tsConfigFileName
* @param {tsc.Settings} settings
* @param {CreateProjectOptions} options
*
* @typedef CreateProjectOptions
* @property {string} [typescript]
* @property {boolean} [parse]
*/
function createProject(tsConfigFileName, settings, options) {
settings = Object.assign({}, settings);
options = Object.assign({}, options);
if (settings.typescript) throw new Error();
const localSettings = Object.assign({}, settings);
if (options.typescript) {
options.typescript = path.resolve(options.typescript);
localSettings.typescript = require(options.typescript);
}
const project = tsConfigFileName === undefined ? tsc.createProject(localSettings) : tsc.createProject(tsConfigFileName, localSettings);
const wrappedProject = /** @type {tsc.Project} */((reporter = tsc.reporter.defaultReporter()) => {
const ts = project.typescript;
const proc = child_process.fork(require.resolve("./worker.js"), [], {
// Prevent errors when debugging gulpfile due to the same debug port being passed to forked children.
execArgv: []
});
/** @type {Map<string, import("vinyl")>} */
const inputs = new Map();
/** @type {Map<string, *>} */
const sourceFiles = new Map();
/** @type {protocol.SourceFileHost & protocol.VinylHost} */
const host = {
getVinyl(path) { return inputs.get(path); },
getSourceFile(fileName) { return sourceFiles.get(fileName); },
createSourceFile(fileName, text, languageVersion) {
if (text === undefined) {
text = fs.readFileSync(fileName, "utf8");
}
/** @type {protocol.SourceFile} */
let file;
if (options.parse) {
file = ts.createSourceFile(fileName, text, languageVersion, /*setParentNodes*/ true);
}
else {
// NOTE: the built-in reporters in gulp-typescript don't actually need a full
// source file, so save time by faking one unless requested.
file = /**@type {protocol.SourceFile}*/({
pos: 0,
end: text.length,
kind: ts.SyntaxKind.SourceFile,
fileName,
text,
languageVersion,
statements: /**@type {*} */([]),
endOfFileToken: { pos: text.length, end: text.length, kind: ts.SyntaxKind.EndOfFileToken },
amdDependencies: /**@type {*} */([]),
referencedFiles: /**@type {*} */([]),
typeReferenceDirectives: /**@type {*} */([]),
libReferenceDirectives: /**@type {*} */([]),
languageVariant: ts.LanguageVariant.Standard,
isDeclarationFile: /\.d\.ts$/.test(fileName),
hasNoDefaultLib: /[\\/]lib\.[^\\/]+\.d\.ts$/.test(fileName)
});
}
sourceFiles.set(fileName, file);
return file;
}
};
/** @type {Duplex & { js?: Readable, dts?: Readable }} */
const compileStream = new Duplex({
objectMode: true,
read() {},
/** @param {*} file */
write(file, _encoding, callback) {
inputs.set(file.path, file);
proc.send(protocol.message.write(file));
callback();
},
final(callback) {
proc.send(protocol.message.final());
callback();
}
});
const jsStream = compileStream.js = new Readable({
objectMode: true,
read() {}
});
const dtsStream = compileStream.dts = new Readable({
objectMode: true,
read() {}
});
proc.send(protocol.message.createProject(tsConfigFileName, settings, options));
proc.on("message", (/**@type {protocol.WorkerMessage}*/ message) => {
switch (message.method) {
case "write": {
const file = protocol.vinylFromJson(message.params);
compileStream.push(file);
if (file.path.endsWith(".d.ts")) {
dtsStream.push(file);
}
else {
jsStream.push(file);
}
break;
}
case "final": {
compileStream.push(null);
jsStream.push(null);
dtsStream.push(null);
proc.kill(); // TODO(rbuckton): pool workers? may not be feasible due to gulp-typescript holding onto memory
break;
}
case "error": {
const error = protocol.errorFromJson(message.params);
compileStream.emit("error", error);
proc.kill(); // TODO(rbuckton): pool workers? may not be feasible due to gulp-typescript holding onto memory
break;
}
case "reporter.error": {
if (reporter.error) {
const error = protocol.typeScriptErrorFromJson(message.params, host);
reporter.error(error, project.typescript);
}
break;
}
case "reporter.finish": {
if (reporter.finish) {
reporter.finish(message.params);
}
}
}
});
return /** @type {*} */(compileStream);
});
return Object.assign(wrappedProject, project);
}
exports.createProject = createProject;

View file

@ -1,281 +0,0 @@
// @ts-check
const Vinyl = require("vinyl");
/**
* @param {File} file
* @returns {*}
*/
function vinylToJson(file) {
if (file.isStream()) throw new TypeError("Streams not supported.");
return {
path: file.path,
cwd: file.cwd,
base: file.base,
contents: file.isBuffer() ? file.contents.toString("utf8") : undefined,
sourceMap: file.sourceMap
};
}
exports.vinylToJson = vinylToJson;
/**
* @param {*} json
* @returns {File}
*/
function vinylFromJson(json) {
return new Vinyl({
path: json.path,
cwd: json.cwd,
base: json.base,
contents: typeof json.contents === "string" ? Buffer.from(json.contents, "utf8") : undefined,
sourceMap: json.sourceMap
});
}
exports.vinylFromJson = vinylFromJson;
/**
* @param {Error} error
* @returns {*}
*/
function errorToJson(error) {
return {
name: error.name,
message: error.message,
stack: error.stack
};
}
exports.errorToJson = errorToJson;
/**
* @param {*} json
* @returns {Error}
*/
function errorFromJson(json) {
const error = new Error();
error.name = json.name;
error.message = json.message;
error.stack = json.stack;
return error;
}
exports.errorFromJson = errorFromJson;
/**
* @param {TypeScriptError} error
* @returns {*}
*/
function typeScriptErrorToJson(error) {
return Object.assign({}, errorToJson(error), {
fullFilename: error.fullFilename,
relativeFilename: error.relativeFilename,
file: error.file && { path: error.file.path },
tsFile: error.tsFile && sourceFileToJson(error.tsFile),
diagnostic: diagnosticToJson(error.diagnostic),
startPosition: error.startPosition,
endPosition: error.endPosition
});
}
exports.typeScriptErrorToJson = typeScriptErrorToJson;
/**
* @param {*} json
* @param {SourceFileHost & VinylHost} host
* @returns {TypeScriptError}
*/
function typeScriptErrorFromJson(json, host) {
const error = /**@type {TypeScriptError}*/(errorFromJson(json));
error.fullFilename = json.fullFilename;
error.relativeFilename = json.relativeFilename;
error.file = json.file && host.getVinyl(json.file.path);
error.tsFile = json.tsFile && sourceFileFromJson(json.tsFile, host);
error.diagnostic = diagnosticFromJson(json.diagnostic, host);
error.startPosition = json.startPosition;
error.endPosition = json.endPosition;
return error;
}
exports.typeScriptErrorFromJson = typeScriptErrorFromJson;
/**
* @param {SourceFile} file
* @returns {*}
*/
function sourceFileToJson(file) {
return {
fileName: file.fileName,
text: file.text,
languageVersion: file.languageVersion
};
}
exports.sourceFileToJson = sourceFileToJson;
/**
* @param {*} json
* @param {SourceFileHost} host
*/
function sourceFileFromJson(json, host) {
return host.getSourceFile(json.fileName)
|| host.createSourceFile(json.fileName, json.text, json.languageVersion);
}
exports.sourceFileFromJson = sourceFileFromJson;
/**
* @param {Diagnostic} diagnostic
* @returns {*}
*/
function diagnosticToJson(diagnostic) {
return Object.assign({}, diagnosticRelatedInformationToJson(diagnostic), {
category: diagnostic.category,
code: diagnostic.code,
source: diagnostic.source,
relatedInformation: diagnostic.relatedInformation && diagnostic.relatedInformation.map(diagnosticRelatedInformationToJson)
});
}
exports.diagnosticToJson = diagnosticToJson;
/**
* @param {*} json
* @param {SourceFileHost} host
* @returns {Diagnostic}
*/
function diagnosticFromJson(json, host) {
return Object.assign({}, diagnosticRelatedInformationFromJson(json, host), {
category: json.category,
code: json.code,
source: json.source,
relatedInformation: json.relatedInformation && json.relatedInformation.map(json => diagnosticRelatedInformationFromJson(json, host))
});
}
exports.diagnosticFromJson = diagnosticFromJson;
/**
* @param {DiagnosticRelatedInformation} diagnostic
* @returns {*}
*/
function diagnosticRelatedInformationToJson(diagnostic) {
return {
file: diagnostic.file && { fileName: diagnostic.file.fileName },
start: diagnostic.start,
length: diagnostic.length,
messageText: diagnostic.messageText
};
}
exports.diagnosticRelatedInformationToJson = diagnosticRelatedInformationToJson;
/**
* @param {*} json
* @param {SourceFileHost} host
* @returns {DiagnosticRelatedInformation}
*/
function diagnosticRelatedInformationFromJson(json, host) {
return {
file: json.file && sourceFileFromJson(json.file, host),
start: json.start,
length: json.length,
messageText: json.messageText,
category: json.category,
code: json.code
};
}
exports.diagnosticRelatedInformationFromJson = diagnosticRelatedInformationFromJson;
exports.message = {};
/**
* @param {string | undefined} tsConfigFileName
* @param {import("gulp-typescript").Settings} settings
* @param {Object} options
* @param {string} [options.typescript]
* @returns {CreateProjectMessage}
*
* @typedef CreateProjectMessage
* @property {"createProject"} method
* @property {CreateProjectParams} params
*
* @typedef CreateProjectParams
* @property {string | undefined} tsConfigFileName
* @property {import("gulp-typescript").Settings} settings
* @property {CreateProjectOptions} options
*
* @typedef CreateProjectOptions
* @property {string} [typescript]
*/
exports.message.createProject = function(tsConfigFileName, settings, options) {
return { method: "createProject", params: { tsConfigFileName, settings, options } };
};
/**
* @param {File} file
* @returns {WriteMessage}
*
* @typedef WriteMessage
* @property {"write"} method
* @property {*} params
*/
exports.message.write = function(file) {
return { method: "write", params: vinylToJson(file) };
};
/**
* @returns {FinalMessage}
*
* @typedef FinalMessage
* @property {"final"} method
*/
exports.message.final = function() {
return { method: "final" };
};
/**
* @param {Error} error
* @returns {ErrorMessage}
*
* @typedef ErrorMessage
* @property {"error"} method
* @property {*} params
*/
exports.message.error = function(error) {
return { method: "error", params: errorToJson(error) };
};
exports.message.reporter = {};
/**
* @param {TypeScriptError} error
* @returns {reporter.ErrorMessage}
*
* @typedef reporter.ErrorMessage
* @property {"reporter.error"} method
* @property {*} params
*/
exports.message.reporter.error = function(error) {
return { method: "reporter.error", params: typeScriptErrorToJson(error) };
};
/**
* @param {*} results
* @returns {reporter.FinishMessage}
*
* @typedef reporter.FinishMessage
* @property {"reporter.finish"} method
* @property {*} params
*/
exports.message.reporter.finish = function(results) {
return { method: "reporter.finish", params: results };
};
/**
* @typedef {import("vinyl")} File
* @typedef {typeof import("typescript")} TypeScriptModule
* @typedef {import("typescript").SourceFile} SourceFile
* @typedef {import("typescript").Diagnostic} Diagnostic
* @typedef {import("typescript").DiagnosticRelatedInformation} DiagnosticRelatedInformation
* @typedef {import("gulp-typescript").reporter.TypeScriptError} TypeScriptError
* @typedef {WriteMessage | FinalMessage | CreateProjectMessage} HostMessage
* @typedef {WriteMessage | FinalMessage | ErrorMessage | reporter.ErrorMessage | reporter.FinishMessage} WorkerMessage
*
* @typedef SourceFileHost
* @property {(fileName: string) => SourceFile | undefined} getSourceFile
* @property {(fileName: string, text: string, languageVersion: number) => SourceFile} createSourceFile
*
* @typedef VinylHost
* @property {(path: string) => File | undefined} getVinyl
*/
void 0;

View file

@ -1,79 +0,0 @@
// @ts-check
const fs = require("fs");
const tsc = require("gulp-typescript");
const { Readable, Writable } = require("stream");
const protocol = require("./protocol");
/** @type {tsc.Project} */
let project;
/** @type {Readable} */
let inputStream;
/** @type {Writable} */
let outputStream;
/** @type {tsc.CompileStream} */
let compileStream;
process.on("message", (/**@type {protocol.HostMessage}*/ message) => {
try {
switch (message.method) {
case "createProject": {
const { tsConfigFileName, settings, options } = message.params;
if (options.typescript) {
settings.typescript = require(options.typescript);
}
project = tsConfigFileName === undefined
? tsc.createProject(settings)
: tsc.createProject(tsConfigFileName, settings);
inputStream = new Readable({
objectMode: true,
read() {}
});
outputStream = new Writable({
objectMode: true,
/**
* @param {*} file
*/
write(file, _, callback) {
process.send(protocol.message.write(file));
callback();
},
final(callback) {
process.send(protocol.message.final());
callback();
}
});
compileStream = project({
error(error) { process.send(protocol.message.reporter.error(error)); },
finish(results) { process.send(protocol.message.reporter.finish(results)); }
});
compileStream.on("error", error => {
process.send(protocol.message.error(error));
});
outputStream.on("error", () => {
/* do nothing */
});
inputStream.pipe(compileStream).pipe(outputStream);
break;
}
case "write": {
const file = protocol.vinylFromJson(message.params);
if (!file.isBuffer()) file.contents = fs.readFileSync(file.path);
inputStream.push(file);
break;
}
case "final": {
inputStream.push(null);
break;
}
}
}
catch (e) {
process.send(protocol.message.error(e));
}
});

View file

@ -1,8 +0,0 @@
// @ts-check
/**
* @typedef {import("gulp").Gulp} Gulp
* @typedef {import("gulp-help").GulpHelp} GulpHelp
* @typedef {GulpHelp & { Gulp: new () => Gulp }} DotGulpModule
* @type {DotGulpModule}
*/
module.exports = require("gulp-help")(require("gulp"));

View file

@ -1,30 +0,0 @@
// @ts-check
const readJson = require("./readJson");
const path = require("path");
const gulp = require("./gulp");
const newer = require("gulp-newer");
const concat = require("gulp-concat");
const merge2 = require("merge2");
/** @type {{ libs: string[], paths?: Record<string, string>, sources?: Record<string, string[]> }} */
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 };
});
exports.libraryTargets = libs.map(lib => lib.target);
/**
* @param {string[]} prepends
*/
function generateLibs(prepends) {
return merge2(libs.map(({ sources, target, relativeTarget }) =>
gulp.src(prepends.concat(sources))
.pipe(newer(target))
.pipe(concat(relativeTarget, { newLine: "\n\n" }))
.pipe(gulp.dest("built/local"))));
}
exports.generateLibs = generateLibs;

View file

@ -1,14 +0,0 @@
// @ts-check
const mkdirp = require("mkdirp");
module.exports = exports = mkdirpAsync;
/**
* @param {string} dir
* @param {mkdirp.Mode | mkdirp.Options} [opts]
*/
function mkdirpAsync(dir, opts) {
return new Promise((resolve, reject) => mkdirp(dir, opts, (err, made) => err ? reject(err) : resolve(made)));
}
exports.sync = mkdirp.sync;

View file

@ -1,72 +0,0 @@
// @ts-check
const fs = require("fs");
module.exports = needsUpdate;
/**
* @param {string | string[]} source
* @param {string | string[]} dest
* @returns {boolean}
*/
function needsUpdate(source, dest) {
if (typeof source === "string" && typeof dest === "string") {
if (fs.existsSync(dest)) {
const {mtime: outTime} = fs.statSync(dest);
const {mtime: inTime} = fs.statSync(source);
if (+inTime <= +outTime) {
return false;
}
}
}
else if (typeof source === "string" && typeof dest !== "string") {
const {mtime: inTime} = fs.statSync(source);
for (const filepath of dest) {
if (fs.existsSync(filepath)) {
const {mtime: outTime} = fs.statSync(filepath);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
else if (typeof source !== "string" && typeof dest === "string") {
if (fs.existsSync(dest)) {
const {mtime: outTime} = fs.statSync(dest);
for (const filepath of source) {
if (fs.existsSync(filepath)) {
const {mtime: inTime} = fs.statSync(filepath);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
}
else if (typeof source !== "string" && typeof dest !== "string") {
for (let i = 0; i < source.length; i++) {
if (!dest[i]) {
continue;
}
if (fs.existsSync(dest[i])) {
const {mtime: outTime} = fs.statSync(dest[i]);
const {mtime: inTime} = fs.statSync(source[i]);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
return true;
}

View file

@ -4,7 +4,7 @@ const os = require("os");
/** @type {CommandLineOptions} */
module.exports = minimist(process.argv.slice(2), {
boolean: ["debug", "dirty", "inspect", "light", "colors", "lint", "lkg", "soft", "fix", "failed", "keepFailed"],
boolean: ["debug", "dirty", "inspect", "light", "colors", "lint", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built"],
string: ["browser", "tests", "host", "reporter", "stackTraceLimit", "timeout"],
alias: {
"b": "browser",
@ -15,7 +15,7 @@ module.exports = minimist(process.argv.slice(2), {
"r": "reporter",
"c": "colors", "color": "colors",
"w": "workers",
"f": "fix",
"f": "fix"
},
default: {
soft: false,
@ -35,10 +35,15 @@ module.exports = minimist(process.argv.slice(2), {
failed: false,
keepFailed: false,
lkg: true,
dirty: false
dirty: false,
built: false
}
});
if (module.exports.built) {
module.exports.lkg = false;
}
/**
* @typedef TypedOptions
* @property {boolean} debug
@ -48,6 +53,7 @@ module.exports = minimist(process.argv.slice(2), {
* @property {boolean} colors
* @property {boolean} lint
* @property {boolean} lkg
* @property {boolean} built
* @property {boolean} soft
* @property {boolean} fix
* @property {string} browser

View file

@ -1,20 +1,18 @@
// @ts-check
const stream = require("stream");
const Vinyl = require("./vinyl");
const Vinyl = require("vinyl");
const ts = require("../../lib/typescript");
const fs = require("fs");
const { base64VLQFormatEncode } = require("./sourcemaps");
module.exports = exports = prepend;
/**
* @param {string | ((file: Vinyl) => string)} data
* @param {string | ((file: import("vinyl")) => string)} data
*/
function prepend(data) {
return new stream.Transform({
objectMode: true,
/**
* @param {string | Buffer | Vinyl} input
* @param {string | Buffer | import("vinyl")} input
* @param {(error: Error, data?: any) => void} cb
*/
transform(input, _, cb) {
@ -56,11 +54,11 @@ function prepend(data) {
exports.prepend = prepend;
/**
* @param {string | ((file: Vinyl) => string)} file
* @param {string | ((file: import("vinyl")) => string)} file
*/
function prependFile(file) {
const data = typeof file === "string" ? fs.readFileSync(file, "utf8") :
vinyl => fs.readFileSync(file(vinyl), "utf8");
return prepend(data)
}
exports.file = prependFile;
exports.prependFile = prependFile;

File diff suppressed because it is too large Load diff

60
scripts/build/projects.js Normal file
View file

@ -0,0 +1,60 @@
// @ts-check
const { exec, Debouncer } = require("./utils");
class ProjectQueue {
/**
* @param {(projects: string[], lkg: boolean, force: boolean) => Promise<any>} action
*/
constructor(action) {
/** @type {{ lkg: boolean, force: boolean, projects?: string[], debouncer: Debouncer }[]} */
this._debouncers = [];
this._action = action;
}
/**
* @param {string} project
* @param {object} options
*/
enqueue(project, { lkg = true, force = false } = {}) {
let entry = this._debouncers.find(entry => entry.lkg === lkg && entry.force === force);
if (!entry) {
const debouncer = new Debouncer(100, async () => {
const projects = entry.projects;
if (projects) {
entry.projects = undefined;
await this._action(projects, lkg, force);
}
});
this._debouncers.push(entry = { lkg, force, debouncer });
}
if (!entry.projects) entry.projects = [];
entry.projects.push(project);
return entry.debouncer.enqueue();
}
}
const projectBuilder = new ProjectQueue((projects, lkg, force) => exec(process.execPath, [lkg ? "./lib/tsc" : "./built/local/tsc", "-b", ...(force ? ["--force"] : []), ...projects], { hidePrompt: true }));
/**
* @param {string} project
* @param {object} [options]
* @param {boolean} [options.lkg=true]
* @param {boolean} [options.force=false]
*/
exports.buildProject = (project, { lkg, force } = {}) => projectBuilder.enqueue(project, { lkg, force });
const projectCleaner = new ProjectQueue((projects, lkg) => exec(process.execPath, [lkg ? "./lib/tsc" : "./built/local/tsc", "-b", "--clean", ...projects], { hidePrompt: true }));
/**
* @param {string} project
*/
exports.cleanProject = (project) => projectCleaner.enqueue(project);
const projectWatcher = new ProjectQueue((projects) => exec(process.execPath, ["./lib/tsc", "-b", "--watch", ...projects], { hidePrompt: true }));
/**
* @param {string} project
* @param {object} [options]
* @param {boolean} [options.lkg=true]
*/
exports.watchProject = (project, { lkg } = {}) => projectWatcher.enqueue(project, { lkg });

View file

@ -1,17 +0,0 @@
// @ts-check
const ts = require("../../lib/typescript");
const fs = require("fs");
const { reportDiagnostics } = require("./diagnostics");
module.exports = exports = readJson;
/** @param {string} jsonPath */
function readJson(jsonPath) {
const jsonText = fs.readFileSync(jsonPath, "utf8");
const result = ts.parseConfigFileTextToJson(jsonPath, jsonText);
if (result.error) {
reportDiagnostics([result.error]);
throw new Error("An error occurred during parse.");
}
return result.config;
}

View file

@ -1,12 +0,0 @@
// @ts-check
const insert = require("gulp-insert");
/**
* @param {string | RegExp} searchValue
* @param {string | ((...args: string[]) => string)} replacer
*/
function replace(searchValue, replacer) {
return insert.transform(content => content.replace(searchValue, /**@type {string}*/(replacer)));
}
module.exports = replace;

View file

@ -1,84 +0,0 @@
// @ts-check
const { Duplex } = require("stream");
const path = require("path");
const Vinyl = require("vinyl");
const del = require("del");
module.exports = rm;
/**
* @param {string | ((file: File) => string) | Options} [dest]
* @param {Options} [opts]
*/
function rm(dest, opts) {
if (dest && typeof dest === "object") opts = dest, dest = undefined;
let failed = false;
const cwd = path.resolve(opts && opts.cwd || process.cwd());
/** @type {{ file: File, deleted: boolean, promise: Promise<any>, cb: Function }[]} */
const pending = [];
const processDeleted = () => {
if (failed) return;
while (pending.length && pending[0].deleted) {
const { file, cb } = pending.shift();
duplex.push(file);
cb();
}
};
const duplex = new Duplex({
objectMode: true,
/**
* @param {string|Buffer|File} file
*/
write(file, _, cb) {
if (failed) return;
if (typeof file === "string" || Buffer.isBuffer(file)) return cb(new Error("Only Vinyl files are supported."));
const basePath = typeof dest === "string" ? path.resolve(cwd, dest) :
typeof dest === "function" ? path.resolve(cwd, dest(file)) :
file.base;
const filePath = path.resolve(basePath, file.relative);
file.cwd = cwd;
file.base = basePath;
file.path = filePath;
const entry = {
file,
deleted: false,
cb,
promise: del(file.path).then(() => {
entry.deleted = true;
processDeleted();
}, err => {
failed = true;
pending.length = 0;
cb(err);
})
};
pending.push(entry);
},
final(cb) {
processDeleted();
if (pending.length) {
Promise
.all(pending.map(entry => entry.promise))
.then(() => processDeleted())
.then(() => cb(), cb);
return;
}
cb();
},
read() {
}
});
return duplex;
}
/**
* @typedef {import("vinyl")} File
*
* @typedef Options
* @property {string} [cwd]
*/
void 0;

View file

@ -1,12 +1,13 @@
// @ts-check
/// <reference path="../types/ambient.d.ts" />
const path = require("path");
const Vinyl = require("./vinyl");
const convertMap = require("convert-source-map");
const applySourceMap = require("vinyl-sourcemaps-apply");
const through2 = require("through2");
/**
* @param {Vinyl} input
* @param {import("vinyl")} input
* @param {string | Buffer} contents
* @param {string | RawSourceMap} [sourceMap]
*/
@ -16,13 +17,13 @@ function replaceContents(input, contents, sourceMap) {
if (input.sourceMap) {
output.sourceMap = typeof input.sourceMap === "string" ? /**@type {RawSourceMap}*/(JSON.parse(input.sourceMap)) : input.sourceMap;
if (typeof sourceMap === "string") {
sourceMap = /**@type {RawSourceMap}*/(JSON.parse(sourceMap));
sourceMap = /** @type {RawSourceMap} */(JSON.parse(sourceMap));
}
else if (sourceMap === undefined) {
const stringContents = typeof contents === "string" ? contents : contents.toString("utf8");
const newSourceMapConverter = convertMap.fromSource(stringContents);
if (newSourceMapConverter) {
sourceMap = /**@type {RawSourceMap}*/(newSourceMapConverter.toObject());
sourceMap = /** @type {RawSourceMap} */(newSourceMapConverter.toObject());
output.contents = new Buffer(convertMap.removeMapFileComments(stringContents), "utf8");
}
}
@ -31,7 +32,7 @@ function replaceContents(input, contents, sourceMap) {
const base = input.base || cwd;
const sourceRoot = output.sourceMap.sourceRoot;
makeAbsoluteSourceMap(cwd, base, output.sourceMap);
makeAbsoluteSourceMap(cwd, base, sourceMap);
makeAbsoluteSourceMap(cwd, base, /** @type {RawSourceMap} */(sourceMap));
applySourceMap(output, sourceMap);
makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap);
}
@ -44,10 +45,12 @@ function replaceContents(input, contents, sourceMap) {
exports.replaceContents = replaceContents;
function removeSourceMaps() {
return through2.obj((/**@type {Vinyl}*/file, _, cb) => {
if (file.sourceMap && file.isBuffer()) {
return through2.obj((/**@type {import("vinyl")}*/file, _, cb) => {
if (file.isBuffer()) {
file.contents = Buffer.from(convertMap.removeMapFileComments(file.contents.toString("utf8")), "utf8");
file.sourceMap = undefined;
if (file.sourceMap) {
file.sourceMap = undefined;
}
}
cb(null, file);
});
@ -59,7 +62,7 @@ exports.removeSourceMaps = removeSourceMaps;
* @param {string | undefined} base
* @param {RawSourceMap} sourceMap
*
* @typedef RawSourceMap
* @typedef {object} RawSourceMap
* @property {string} version
* @property {string} file
* @property {string} [sourceRoot]

View file

@ -1,16 +1,16 @@
// @ts-check
const gulp = require("./gulp");
const gulp = require("gulp");
const del = require("del");
const fs = require("fs");
const os = require("os");
const path = require("path");
const mkdirP = require("./mkdirp");
const mkdirP = require("mkdirp");
const log = require("fancy-log");
const cmdLineOptions = require("./options");
const exec = require("./exec");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const { CancellationToken } = require("prex");
const mochaJs = require.resolve("mocha/bin/_mocha");
const { exec } = require("./utils");
const mochaJs = require.resolve("mocha/bin/_mocha");
exports.localBaseline = "tests/baselines/local/";
exports.refBaseline = "tests/baselines/reference/";
exports.localRwcBaseline = "internal/baselines/rwc/local";
@ -27,7 +27,6 @@ exports.localTest262Baseline = "internal/baselines/test262/local";
async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, cancelToken = CancellationToken.none) {
let testTimeout = cmdLineOptions.timeout;
let tests = cmdLineOptions.tests;
const lintFlag = cmdLineOptions.lint;
const debug = cmdLineOptions.debug;
const inspect = cmdLineOptions.inspect;
const runners = cmdLineOptions.runners;
@ -117,9 +116,6 @@ async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode,
errorStatus = exitCode;
error = new Error(`Process exited with status code ${errorStatus}.`);
}
else if (lintFlag) {
await new Promise((resolve, reject) => gulp.start(["lint"], error => error ? reject(error) : resolve()));
}
}
catch (e) {
errorStatus = undefined;
@ -144,10 +140,10 @@ async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode,
}
exports.runConsoleTests = runConsoleTests;
function cleanTestDirs() {
return del([exports.localBaseline, exports.localRwcBaseline])
.then(() => mkdirP(exports.localRwcBaseline))
.then(() => mkdirP(exports.localBaseline));
async function cleanTestDirs() {
await del([exports.localBaseline, exports.localRwcBaseline])
mkdirP.sync(exports.localRwcBaseline);
mkdirP.sync(exports.localBaseline);
}
exports.cleanTestDirs = cleanTestDirs;

View file

@ -1,435 +0,0 @@
// @ts-check
const path = require("path");
const fs = require("fs");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const ts = require("../../lib/typescript");
const { Duplex } = require("stream");
const chalk = /**@type {*} */(require("chalk"));
const Vinyl = require("vinyl");
/**
* Creates a stream that passes through its inputs only if the project outputs are not up to date
* with respect to the inputs.
* @param {ParsedCommandLine} parsedProject
* @param {UpToDateOptions} [options]
*
* @typedef UpToDateOptions
* @property {boolean | "minimal"} [verbose]
* @property {(configFilePath: string) => ParsedCommandLine | undefined} [parseProject]
*/
function upToDate(parsedProject, options) {
/** @type {File[]} */
const inputs = [];
/** @type {Map<string, File>} */
const inputMap = new Map();
/** @type {Map<string, fs.Stats>} */
const statCache = new Map();
/** @type {UpToDateHost} */
const upToDateHost = {
fileExists(fileName) {
const stats = getStat(fileName);
return stats ? stats.isFile() : false;
},
getModifiedTime(fileName) {
return getStat(fileName).mtime;
},
parseConfigFile: options && options.parseProject
};
const duplex = new Duplex({
objectMode: true,
/**
* @param {string|Buffer|File} file
*/
write(file, _, cb) {
if (typeof file === "string" || Buffer.isBuffer(file)) return cb(new Error("Only Vinyl files are supported."));
inputs.push(file);
inputMap.set(path.resolve(file.path), file);
cb();
},
final(cb) {
const status = getUpToDateStatus(upToDateHost, parsedProject);
reportStatus(parsedProject, status, options);
if (status.type !== UpToDateStatusType.UpToDate) {
for (const input of inputs) duplex.push(input);
}
duplex.push(null);
inputMap.clear();
statCache.clear();
cb();
},
read() {
}
});
return duplex;
function getStat(fileName) {
fileName = path.resolve(fileName);
const inputFile = inputMap.get(fileName);
if (inputFile && inputFile.stat) return inputFile.stat;
let stats = statCache.get(fileName);
if (!stats && fs.existsSync(fileName)) {
stats = fs.statSync(fileName);
statCache.set(fileName, stats);
}
return stats;
}
}
module.exports = exports = upToDate;
/**
* @param {DiagnosticMessage} message
* @param {...string} args
*/
function formatMessage(message, ...args) {
log.info(formatStringFromArgs(message.message, args));
}
/**
* @param {ParsedCommandLine} project
* @param {UpToDateStatus} status
* @param {{verbose?: boolean | "minimal"}} options
*/
function reportStatus(project, status, options) {
switch (options.verbose) {
case "minimal":
switch (status.type) {
case UpToDateStatusType.UpToDate:
log.info(`Project '${fileName(project.options.configFilePath)}' is up to date.`);
break;
default:
log.info(`Project '${fileName(project.options.configFilePath)}' is out of date, rebuilding...`);
break;
}
break;
case true:
/**@type {*}*/(ts).formatUpToDateStatus(project.options.configFilePath, status, fileName, formatMessage);
break;
}
if (!options.verbose) return;
}
/**
* @param {string} file
* @private
*/
function normalizeSlashes(file) {
return file.replace(/\\/g, "/");
}
/**
* @param {string} file
* @private
*/
function fileName(file) {
return chalk.cyan(normalizeSlashes(path.relative(process.cwd(), path.resolve(file))));
}
/**
* @param {string} text
* @param {string[]} args
* @param {number} [baseIndex]
*/
function formatStringFromArgs(text, args, baseIndex = 0) {
return text.replace(/{(\d+)}/g, (_match, index) => args[+index + baseIndex]);
}
const minimumDate = new Date(-8640000000000000);
const maximumDate = new Date(8640000000000000);
const missingFileModifiedTime = new Date(0);
/**
* @typedef {0} UpToDateStatusType.Unbuildable
* @typedef {1} UpToDateStatusType.UpToDate
* @typedef {2} UpToDateStatusType.UpToDateWithUpstreamTypes
* @typedef {3} UpToDateStatusType.OutputMissing
* @typedef {4} UpToDateStatusType.OutOfDateWithSelf
* @typedef {5} UpToDateStatusType.OutOfDateWithUpstream
* @typedef {6} UpToDateStatusType.UpstreamOutOfDate
* @typedef {7} UpToDateStatusType.UpstreamBlocked
* @typedef {8} UpToDateStatusType.ComputingUpstream
* @typedef {9} UpToDateStatusType.ContainerOnly
* @enum {UpToDateStatusType.Unbuildable | UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes | UpToDateStatusType.OutputMissing | UpToDateStatusType.OutOfDateWithSelf | UpToDateStatusType.OutOfDateWithUpstream | UpToDateStatusType.UpstreamOutOfDate | UpToDateStatusType.UpstreamBlocked | UpToDateStatusType.ComputingUpstream | UpToDateStatusType.ContainerOnly}
*/
const UpToDateStatusType = {
Unbuildable: /** @type {0} */(0),
UpToDate: /** @type {1} */(1),
UpToDateWithUpstreamTypes: /** @type {2} */(2),
OutputMissing: /** @type {3} */(3),
OutOfDateWithSelf: /** @type {4} */(4),
OutOfDateWithUpstream: /** @type {5} */(5),
UpstreamOutOfDate: /** @type {6} */(6),
UpstreamBlocked: /** @type {7} */(7),
ComputingUpstream: /** @type {8} */(8),
ContainerOnly: /** @type {9} */(9),
};
/**
* @param {Date} date1
* @param {Date} date2
* @returns {Date}
*/
function newer(date1, date2) {
return date2 > date1 ? date2 : date1;
}
/**
* @param {UpToDateHost} host
* @param {ParsedCommandLine | undefined} project
* @returns {UpToDateStatus}
*/
function getUpToDateStatus(host, project) {
if (project === undefined) return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
const prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
if (prior !== undefined) {
return prior;
}
const actual = getUpToDateStatusWorker(host, project);
if (host.setLastStatus) {
host.setLastStatus(project.options.configFilePath, actual);
}
return actual;
}
/**
* @param {UpToDateHost} host
* @param {ParsedCommandLine | undefined} project
* @returns {UpToDateStatus}
*/
function getUpToDateStatusWorker(host, project) {
/** @type {string} */
let newestInputFileName = undefined;
let newestInputFileTime = minimumDate;
// Get timestamps of input files
for (const inputFile of project.fileNames) {
if (!host.fileExists(inputFile)) {
return {
type: UpToDateStatusType.Unbuildable,
reason: `${inputFile} does not exist`
};
}
const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime;
if (inputTime > newestInputFileTime) {
newestInputFileName = inputFile;
newestInputFileTime = inputTime;
}
}
// Collect the expected outputs of this project
const outputs = /**@type {string[]}*/(/**@type {*}*/(ts).getAllProjectOutputs(project));
if (outputs.length === 0) {
return {
type: UpToDateStatusType.ContainerOnly
};
}
// Now see if all outputs are newer than the newest input
let oldestOutputFileName = "(none)";
let oldestOutputFileTime = maximumDate;
let newestOutputFileName = "(none)";
let newestOutputFileTime = minimumDate;
/** @type {string | undefined} */
let missingOutputFileName;
let newestDeclarationFileContentChangedTime = minimumDate;
let isOutOfDateWithInputs = false;
for (const output of outputs) {
// Output is missing; can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
if (!host.fileExists(output)) {
missingOutputFileName = output;
break;
}
const outputTime = host.getModifiedTime(output) || missingFileModifiedTime;
if (outputTime < oldestOutputFileTime) {
oldestOutputFileTime = outputTime;
oldestOutputFileName = output;
}
// If an output is older than the newest input, we can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
if (outputTime < newestInputFileTime) {
isOutOfDateWithInputs = true;
break;
}
if (outputTime > newestOutputFileTime) {
newestOutputFileTime = outputTime;
newestOutputFileName = output;
}
// Keep track of when the most recent time a .d.ts file was changed.
// In addition to file timestamps, we also keep track of when a .d.ts file
// had its file touched but not had its contents changed - this allows us
// to skip a downstream typecheck
if (path.extname(output) === ".d.ts") {
const unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
if (unchangedTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
}
else {
const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime;
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
}
}
}
let pseudoUpToDate = false;
let usesPrepend = false;
/** @type {string | undefined} */
let upstreamChangedProject;
if (project.projectReferences) {
if (host.setLastStatus) host.setLastStatus(project.options.configFilePath, { type: UpToDateStatusType.ComputingUpstream });
for (const ref of project.projectReferences) {
usesPrepend = usesPrepend || !!(ref.prepend);
const resolvedRef = ts.resolveProjectReferencePath(host, ref);
const parsedRef = host.parseConfigFile ? host.parseConfigFile(resolvedRef) : ts.getParsedCommandLineOfConfigFile(resolvedRef, {}, parseConfigHost);
const refStatus = getUpToDateStatus(host, parsedRef);
// Its a circular reference ignore the status of this project
if (refStatus.type === UpToDateStatusType.ComputingUpstream) {
continue;
}
// An upstream project is blocked
if (refStatus.type === UpToDateStatusType.Unbuildable) {
return {
type: UpToDateStatusType.UpstreamBlocked,
upstreamProjectName: ref.path
};
}
// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
if (refStatus.type !== UpToDateStatusType.UpToDate) {
return {
type: UpToDateStatusType.UpstreamOutOfDate,
upstreamProjectName: ref.path
};
}
// If the upstream project's newest file is older than our oldest output, we
// can't be out of date because of it
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
continue;
}
// If the upstream project has only change .d.ts files, and we've built
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
pseudoUpToDate = true;
upstreamChangedProject = ref.path;
continue;
}
// We have an output older than an upstream output - we are out of date
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: ref.path
};
}
}
if (missingOutputFileName !== undefined) {
return {
type: UpToDateStatusType.OutputMissing,
missingOutputFileName
};
}
if (isOutOfDateWithInputs) {
return {
type: UpToDateStatusType.OutOfDateWithSelf,
outOfDateOutputFileName: oldestOutputFileName,
newerInputFileName: newestInputFileName
};
}
if (usesPrepend && pseudoUpToDate) {
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: upstreamChangedProject
};
}
// Up to date
return {
type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime,
newestInputFileTime,
newestOutputFileTime,
newestInputFileName,
newestOutputFileName,
oldestOutputFileName
};
}
const parseConfigHost = {
useCaseSensitiveFileNames: true,
getCurrentDirectory: () => process.cwd(),
readDirectory: (file) => fs.readdirSync(file),
fileExists: file => fs.existsSync(file) && fs.statSync(file).isFile(),
readFile: file => fs.readFileSync(file, "utf8"),
onUnRecoverableConfigFileDiagnostic: () => undefined
};
/**
* @typedef {import("vinyl")} File
* @typedef {import("../../lib/typescript").ParsedCommandLine & { options: CompilerOptions }} ParsedCommandLine
* @typedef {import("../../lib/typescript").CompilerOptions & { configFilePath?: string }} CompilerOptions
* @typedef {import("../../lib/typescript").DiagnosticMessage} DiagnosticMessage
* @typedef UpToDateHost
* @property {(fileName: string) => boolean} fileExists
* @property {(fileName: string) => Date} getModifiedTime
* @property {(fileName: string) => Date} [getUnchangedTime]
* @property {(configFilePath: string) => ParsedCommandLine | undefined} parseConfigFile
* @property {(configFilePath: string) => UpToDateStatus} [getLastStatus]
* @property {(configFilePath: string, status: UpToDateStatus) => void} [setLastStatus]
*
* @typedef Status.Unbuildable
* @property {UpToDateStatusType.Unbuildable} type
* @property {string} reason
*
* @typedef Status.ContainerOnly
* @property {UpToDateStatusType.ContainerOnly} type
*
* @typedef Status.UpToDate
* @property {UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes} type
* @property {Date} [newestInputFileTime]
* @property {string} [newestInputFileName]
* @property {Date} [newestDeclarationFileContentChangedTime]
* @property {Date} [newestOutputFileTime]
* @property {string} [newestOutputFileName]
* @property {string} [oldestOutputFileName]
*
* @typedef Status.OutputMissing
* @property {UpToDateStatusType.OutputMissing} type
* @property {string} missingOutputFileName
*
* @typedef Status.OutOfDateWithSelf
* @property {UpToDateStatusType.OutOfDateWithSelf} type
* @property {string} outOfDateOutputFileName
* @property {string} newerInputFileName
*
* @typedef Status.UpstreamOutOfDate
* @property {UpToDateStatusType.UpstreamOutOfDate} type
* @property {string} upstreamProjectName
*
* @typedef Status.UpstreamBlocked
* @property {UpToDateStatusType.UpstreamBlocked} type
* @property {string} upstreamProjectName
*
* @typedef Status.ComputingUpstream
* @property {UpToDateStatusType.ComputingUpstream} type
*
* @typedef Status.OutOfDateWithUpstream
* @property {UpToDateStatusType.OutOfDateWithUpstream} type
* @property {string} outOfDateOutputFileName
* @property {string} newerProjectName
* @typedef {Status.Unbuildable | Status.ContainerOnly | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ComputingUpstream | Status.OutOfDateWithUpstream} UpToDateStatus
*/
void 0;

View file

@ -1,7 +1,119 @@
// @ts-check
/// <reference path="../types/ambient.d.ts" />
const fs = require("fs");
const File = require("./vinyl");
const { Readable } = require("stream");
const path = require("path");
const log = require("fancy-log");
const mkdirp = require("mkdirp");
const del = require("del");
const File = require("vinyl");
const ts = require("../../lib/typescript");
const { default: chalk } = require("chalk");
const { spawn } = require("child_process");
const { CancellationToken, CancelError, Deferred } = require("prex");
const { Readable, Duplex } = require("stream");
const isWindows = /^win/.test(process.platform);
/**
* Executes the provided command once with the supplied arguments.
* @param {string} cmd
* @param {string[]} args
* @param {ExecOptions} [options]
*
* @typedef ExecOptions
* @property {boolean} [ignoreExitCode]
* @property {import("prex").CancellationToken} [cancelToken]
* @property {boolean} [hidePrompt]
*/
function exec(cmd, args, options = {}) {
return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => {
const { ignoreExitCode, cancelToken = CancellationToken.none } = options;
cancelToken.throwIfCancellationRequested();
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
const subshellFlag = isWindows ? "/c" : "-c";
const command = isWindows ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
if (!options.hidePrompt) log(`> ${chalk.green(cmd)} ${args.join(" ")}`);
const proc = spawn(isWindows ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true });
const registration = cancelToken.register(() => {
log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`);
proc.kill("SIGINT");
proc.kill("SIGTERM");
reject(new CancelError());
});
proc.on("exit", exitCode => {
registration.unregister();
if (exitCode === 0 || ignoreExitCode) {
resolve({ exitCode });
}
else {
reject(new Error(`Process exited with code: ${exitCode}`));
}
});
proc.on("error", error => {
registration.unregister();
reject(error);
});
}));
}
exports.exec = exec;
/**
* @param {string} cmd
*/
function possiblyQuote(cmd) {
return cmd.indexOf(" ") >= 0 ? `"${cmd}"` : cmd;
}
/**
* @param {ts.Diagnostic[]} diagnostics
* @param {{ cwd?: string, pretty?: boolean }} [options]
*/
function formatDiagnostics(diagnostics, options) {
return options && options.pretty
? ts.formatDiagnosticsWithColorAndContext(diagnostics, getFormatDiagnosticsHost(options && options.cwd))
: ts.formatDiagnostics(diagnostics, getFormatDiagnosticsHost(options && options.cwd));
}
exports.formatDiagnostics = formatDiagnostics;
/**
* @param {ts.Diagnostic[]} diagnostics
* @param {{ cwd?: string }} [options]
*/
function reportDiagnostics(diagnostics, options) {
log(formatDiagnostics(diagnostics, { cwd: options && options.cwd, pretty: process.stdout.isTTY }));
}
exports.reportDiagnostics = reportDiagnostics;
/**
* @param {string | undefined} cwd
* @returns {ts.FormatDiagnosticsHost}
*/
function getFormatDiagnosticsHost(cwd) {
return {
getCanonicalFileName: fileName => fileName,
getCurrentDirectory: () => cwd,
getNewLine: () => ts.sys.newLine,
};
}
exports.getFormatDiagnosticsHost = getFormatDiagnosticsHost;
/**
* Reads JSON data with optional comments using the LKG TypeScript compiler
* @param {string} jsonPath
*/
function readJson(jsonPath) {
const jsonText = fs.readFileSync(jsonPath, "utf8");
const result = ts.parseConfigFileTextToJson(jsonPath, jsonText);
if (result.error) {
reportDiagnostics([result.error]);
throw new Error("An error occurred during parse.");
}
return result.config;
}
exports.readJson = readJson;
/**
* @param {File} file
@ -24,4 +136,299 @@ function streamFromBuffer(buffer) {
}
});
}
exports.streamFromBuffer = streamFromBuffer;
exports.streamFromBuffer = streamFromBuffer;
/**
* @param {string | string[]} source
* @param {string | string[]} dest
* @returns {boolean}
*/
function needsUpdate(source, dest) {
if (typeof source === "string" && typeof dest === "string") {
if (fs.existsSync(dest)) {
const {mtime: outTime} = fs.statSync(dest);
const {mtime: inTime} = fs.statSync(source);
if (+inTime <= +outTime) {
return false;
}
}
}
else if (typeof source === "string" && typeof dest !== "string") {
const {mtime: inTime} = fs.statSync(source);
for (const filepath of dest) {
if (fs.existsSync(filepath)) {
const {mtime: outTime} = fs.statSync(filepath);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
else if (typeof source !== "string" && typeof dest === "string") {
if (fs.existsSync(dest)) {
const {mtime: outTime} = fs.statSync(dest);
for (const filepath of source) {
if (fs.existsSync(filepath)) {
const {mtime: inTime} = fs.statSync(filepath);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
}
else if (typeof source !== "string" && typeof dest !== "string") {
for (let i = 0; i < source.length; i++) {
if (!dest[i]) {
continue;
}
if (fs.existsSync(dest[i])) {
const {mtime: outTime} = fs.statSync(dest[i]);
const {mtime: inTime} = fs.statSync(source[i]);
if (+inTime > +outTime) {
return true;
}
}
else {
return true;
}
}
return false;
}
return true;
}
exports.needsUpdate = needsUpdate;
function getDiffTool() {
const program = process.env.DIFF;
if (!program) {
log.warn("Add the 'DIFF' environment variable to the path of the program you want to use.");
process.exit(1);
}
return program;
}
exports.getDiffTool = getDiffTool;
/**
* Find the size of a directory recursively.
* Symbolic links can cause a loop.
* @param {string} root
* @returns {number} bytes
*/
function getDirSize(root) {
const stats = fs.lstatSync(root);
if (!stats.isDirectory()) {
return stats.size;
}
return fs.readdirSync(root)
.map(file => getDirSize(path.join(root, file)))
.reduce((acc, num) => acc + num, 0);
}
exports.getDirSize = getDirSize;
/**
* Flattens a project with project references into a single project.
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
* @param {string} flattenedProjectSpec The output path for the flattened tsconfig.json file.
* @param {FlattenOptions} [options] Options used to flatten a project hierarchy.
*
* @typedef FlattenOptions
* @property {string} [cwd] The path to use for the current working directory. Defaults to `process.cwd()`.
* @property {import("../../lib/typescript").CompilerOptions} [compilerOptions] Compiler option overrides.
* @property {boolean} [force] Forces creation of the output project.
* @property {string[]} [exclude] Files to exclude (relative to `cwd`)
*/
function flatten(projectSpec, flattenedProjectSpec, options = {}) {
const cwd = normalizeSlashes(options.cwd ? path.resolve(options.cwd) : process.cwd());
const files = [];
const resolvedOutputSpec = path.resolve(cwd, flattenedProjectSpec);
const resolvedOutputDirectory = path.dirname(resolvedOutputSpec);
const resolvedProjectSpec = resolveProjectSpec(projectSpec, cwd, undefined);
const project = readJson(resolvedProjectSpec);
const skipProjects = /**@type {Set<string>}*/(new Set());
const skipFiles = new Set(options && options.exclude && options.exclude.map(file => normalizeSlashes(path.resolve(cwd, file))));
recur(resolvedProjectSpec, project);
if (options.force || needsUpdate(files, resolvedOutputSpec)) {
const config = {
extends: normalizeSlashes(path.relative(resolvedOutputDirectory, resolvedProjectSpec)),
compilerOptions: options.compilerOptions || {},
files: files.map(file => normalizeSlashes(path.relative(resolvedOutputDirectory, file)))
};
mkdirp.sync(resolvedOutputDirectory);
fs.writeFileSync(resolvedOutputSpec, JSON.stringify(config, undefined, 2), "utf8");
}
/**
* @param {string} projectSpec
* @param {object} project
*/
function recur(projectSpec, project) {
if (skipProjects.has(projectSpec)) return;
skipProjects.add(project);
if (project.references) {
for (const ref of project.references) {
const referencedSpec = resolveProjectSpec(ref.path, cwd, projectSpec);
const referencedProject = readJson(referencedSpec);
recur(referencedSpec, referencedProject);
}
}
if (project.include) {
throw new Error("Flattened project may not have an 'include' list.");
}
if (!project.files) {
throw new Error("Flattened project must have an explicit 'files' list.");
}
const projectDirectory = path.dirname(projectSpec);
for (let file of project.files) {
file = normalizeSlashes(path.resolve(projectDirectory, file));
if (skipFiles.has(file)) continue;
skipFiles.add(file);
files.push(file);
}
}
}
exports.flatten = flatten;
/**
* @param {string} file
*/
function normalizeSlashes(file) {
return file.replace(/\\/g, "/");
}
/**
* @param {string} projectSpec
* @param {string} cwd
* @param {string | undefined} referrer
* @returns {string}
*/
function resolveProjectSpec(projectSpec, cwd, referrer) {
let projectPath = normalizeSlashes(path.resolve(cwd, referrer ? path.dirname(referrer) : "", projectSpec));
const stats = fs.statSync(projectPath);
if (stats.isFile()) return normalizeSlashes(projectPath);
return normalizeSlashes(path.resolve(cwd, projectPath, "tsconfig.json"));
}
/**
* @param {string | ((file: File) => string) | { cwd?: string }} [dest]
* @param {{ cwd?: string }} [opts]
*/
function rm(dest, opts) {
if (dest && typeof dest === "object") opts = dest, dest = undefined;
let failed = false;
const cwd = path.resolve(opts && opts.cwd || process.cwd());
/** @type {{ file: File, deleted: boolean, promise: Promise<any>, cb: Function }[]} */
const pending = [];
const processDeleted = () => {
if (failed) return;
while (pending.length && pending[0].deleted) {
const { file, cb } = pending.shift();
duplex.push(file);
cb();
}
};
const duplex = new Duplex({
objectMode: true,
/**
* @param {string|Buffer|File} file
*/
write(file, _, cb) {
if (failed) return;
if (typeof file === "string" || Buffer.isBuffer(file)) return cb(new Error("Only Vinyl files are supported."));
const basePath = typeof dest === "string" ? path.resolve(cwd, dest) :
typeof dest === "function" ? path.resolve(cwd, dest(file)) :
file.base;
const filePath = path.resolve(basePath, file.relative);
file.cwd = cwd;
file.base = basePath;
file.path = filePath;
const entry = {
file,
deleted: false,
cb,
promise: del(file.path).then(() => {
entry.deleted = true;
processDeleted();
}, err => {
failed = true;
pending.length = 0;
cb(err);
})
};
pending.push(entry);
},
final(cb) {
processDeleted();
if (pending.length) {
Promise
.all(pending.map(entry => entry.promise))
.then(() => processDeleted())
.then(() => cb(), cb);
return;
}
cb();
},
read() {
}
});
return duplex;
}
exports.rm = rm;
class Debouncer {
/**
* @param {number} timeout
* @param {() => Promise<any>} action
*/
constructor(timeout, action) {
this._timeout = timeout;
this._action = action;
}
enqueue() {
if (this._timer) {
clearTimeout(this._timer);
this._timer = undefined;
}
if (!this._deferred) {
this._deferred = new Deferred();
}
this._timer = setTimeout(() => this.run(), 100);
return this._deferred.promise;
}
run() {
if (this._timer) {
clearTimeout(this._timer);
this._timer = undefined;
}
const deferred = this._deferred;
this._deferred = undefined;
this._projects = undefined;
try {
deferred.resolve(this._action());
}
catch (e) {
deferred.reject(e);
}
}
}
exports.Debouncer = Debouncer;

View file

@ -1,60 +0,0 @@
// NOTE: This makes it possible to correctly type vinyl Files under @ts-check.
export = File;
declare class File<T extends File.Contents = File.Contents> {
constructor(options?: File.VinylOptions<T>);
cwd: string;
base: string;
path: string;
readonly history: ReadonlyArray<string>;
contents: T;
relative: string;
dirname: string;
basename: string;
stem: string;
extname: string;
symlink: string | null;
stat: import("fs").Stats | null;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
isBuffer(): this is T extends Buffer ? File<Buffer> : never;
isStream(): this is T extends NodeJS.ReadableStream ? File<NodeJS.ReadableStream> : never;
isNull(): this is T extends null ? File<null> : never;
isDirectory(): this is T extends null ? File.Directory : never;
isSymbolic(): this is T extends null ? File.Symbolic : never;
clone(opts?: { contents?: boolean, deep?: boolean }): this;
}
namespace File {
export interface VinylOptions<T extends Contents = Contents> {
cwd?: string;
base?: string;
path?: string;
history?: ReadonlyArray<string>;
stat?: import("fs").Stats;
contents?: T;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
}
export type Contents = Buffer | NodeJS.ReadableStream | null;
export type File = import("./vinyl");
export type NullFile = File<null>;
export type BufferFile = File<Buffer>;
export type StreamFile = File<NodeJS.ReadableStream>;
export interface Directory extends NullFile {
isNull(): true;
isDirectory(): true;
isSymbolic(): this is never;
}
export interface Symbolic extends NullFile {
isNull(): true;
isDirectory(): this is never;
isSymbolic(): true;
}
}

View file

@ -1 +0,0 @@
module.exports = require("vinyl");

View file

@ -1,3 +1,5 @@
/// <reference lib="esnext.asynciterable" />
// Must reference esnext.asynciterable lib, since octokit uses AsyncIterable internally
import cp = require("child_process");
import Octokit = require("@octokit/rest");
@ -35,7 +37,7 @@ gh.authenticate({
type: "token",
token: process.argv[2]
});
gh.pullRequests.create({
gh.pulls.create({
owner: process.env.TARGET_FORK,
repo: "TypeScript",
maintainer_can_modify: true,
@ -50,7 +52,7 @@ cc ${reviewers.map(r => "@" + r).join(" ")}`,
}).then(r => {
const num = r.data.number;
console.log(`Pull request ${num} created.`);
return gh.pullRequests.createReviewRequest({
return gh.pulls.createReviewRequest({
owner: process.env.TARGET_FORK,
repo: "TypeScript",
number: num,

View file

@ -1,3 +1,5 @@
import { TaskFunction } from "gulp";
declare module "gulp-clone" {
function Clone(): NodeJS.ReadWriteStream;
namespace Clone {
@ -14,3 +16,78 @@ declare module "gulp-insert" {
}
declare module "sorcery";
declare module "vinyl" {
// NOTE: This makes it possible to correctly type vinyl Files under @ts-check.
export = File;
declare class File<T extends File.Contents = File.Contents> {
constructor(options?: File.VinylOptions<T>);
cwd: string;
base: string;
path: string;
readonly history: ReadonlyArray<string>;
contents: T;
relative: string;
dirname: string;
basename: string;
stem: string;
extname: string;
symlink: string | null;
stat: import("fs").Stats | null;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
isBuffer(): this is T extends Buffer ? File<Buffer> : never;
isStream(): this is T extends NodeJS.ReadableStream ? File<NodeJS.ReadableStream> : never;
isNull(): this is T extends null ? File<null> : never;
isDirectory(): this is T extends null ? File.Directory : never;
isSymbolic(): this is T extends null ? File.Symbolic : never;
clone(opts?: { contents?: boolean, deep?: boolean }): this;
}
namespace File {
export interface VinylOptions<T extends Contents = Contents> {
cwd?: string;
base?: string;
path?: string;
history?: ReadonlyArray<string>;
stat?: import("fs").Stats;
contents?: T;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
}
export type Contents = Buffer | NodeJS.ReadableStream | null;
export type File = import("./vinyl");
export type NullFile = File<null>;
export type BufferFile = File<Buffer>;
export type StreamFile = File<NodeJS.ReadableStream>;
export interface Directory extends NullFile {
isNull(): true;
isDirectory(): true;
isSymbolic(): this is never;
}
export interface Symbolic extends NullFile {
isNull(): true;
isDirectory(): this is never;
isSymbolic(): true;
}
}
}
declare module "undertaker" {
interface TaskFunctionParams {
flags?: Record<string, string>;
}
}
declare module "gulp-sourcemaps" {
interface WriteOptions {
destPath?: string;
}
}

View file

@ -35,8 +35,8 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
}
// cancellationPipeName is a string without '*' inside that can optionally end with '*'
// when client wants to signal cancellation it should create a named pipe with name=<cancellationPipeName>
// server will synchronously check the presence of the pipe and treat its existance as indicator that current request should be canceled.
// in case if client prefers to use more fine-grained schema than one name for all request it can add '*' to the end of cancelellationPipeName.
// server will synchronously check the presence of the pipe and treat its existence as indicator that current request should be canceled.
// in case if client prefers to use more fine-grained schema than one name for all request it can add '*' to the end of cancellationPipeName.
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
const namePrefix = cancellationPipeName.slice(0, -1);

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outDir": "../../built/local/",
"rootDir": ".",

View file

@ -550,7 +550,7 @@ namespace ts {
}
}
// We create a return control flow graph for IIFEs and constructors. For constructors
// we use the return control flow graph in strict property intialization checks.
// we use the return control flow graph in strict property initialization checks.
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
@ -3445,7 +3445,7 @@ namespace ts {
// If a FunctionDeclaration is generator function and is the body of a
// transformed async function, then this node can be transformed to a
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// Currently we do not support transforming any other generator functions
// down level.
if (node.asteriskToken) {
transformFlags |= TransformFlags.AssertGenerator;

View file

@ -27,7 +27,7 @@ namespace ts {
currentChangedFilePath: Path | undefined;
/**
* Map of file signatures, with key being file path, calculated while getting current changed file's affected files
* These will be commited whenever the iteration through affected files of current changed file is complete
* These will be committed whenever the iteration through affected files of current changed file is complete
*/
currentAffectedFilesSignatures: Map<string> | undefined;
/**

View file

@ -37,7 +37,7 @@ namespace ts {
*/
readonly referencedMap: ReadonlyMap<BuilderState.ReferencedSet> | undefined;
/**
* Contains the map of exported modules ReferencedSet=exorted module files from the file if module emit is enabled
* Contains the map of exported modules ReferencedSet=exported module files from the file if module emit is enabled
* Otherwise undefined
*/
readonly exportedModulesMap: Map<BuilderState.ReferencedSet> | undefined;
@ -268,9 +268,9 @@ namespace ts.BuilderState {
*/
export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: Map<string>, exportedModulesMapCache?: ComputingExportedModulesMap): ReadonlyArray<SourceFile> {
// Since the operation could be cancelled, the signatures are always stored in the cache
// They will be commited once it is safe to use them
// They will be committed once it is safe to use them
// eg when calling this api from tsserver, if there is no cancellation of the operation
// In the other cases the affected files signatures are commited only after the iteration through the result is complete
// In the other cases the affected files signatures are committed only after the iteration through the result is complete
const signatureCache = cacheToUpdateSignature || createMap();
const sourceFile = programOfThisState.getSourceFileByPath(path);
if (!sourceFile) {

File diff suppressed because it is too large Load diff

View file

@ -1935,7 +1935,7 @@ namespace ts {
function directoryOfCombinedPath(fileName: string, basePath: string) {
// Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical
// until consistient casing errors are reported
// until consistent casing errors are reported
return getDirectoryPath(getNormalizedAbsolutePath(fileName, basePath));
}

View file

@ -1,7 +1,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "3.3";
export const versionMajorMinor = "3.4";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}
@ -884,8 +884,11 @@ namespace ts {
/**
* Compacts an array, removing any falsey elements.
*/
export function compact<T>(array: T[]): T[];
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>;
export function compact<T>(array: (T | undefined | null | false | 0 | "")[]): T[];
export function compact<T>(array: ReadonlyArray<T | undefined | null | false | 0 | "">): ReadonlyArray<T>;
// TSLint thinks these can be combined with the above - they cannot; they'd produce higher-priority inferences and prevent the falsey types from being stripped
export function compact<T>(array: T[]): T[]; // tslint:disable-line unified-signatures
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>; // tslint:disable-line unified-signatures
export function compact<T>(array: T[]): T[] {
let result: T[] | undefined;
if (array) {

View file

@ -1019,6 +1019,14 @@
"category": "Error",
"code": 1353
},
"'readonly' type modifier is only permitted on array and tuple literal types.": {
"category": "Error",
"code": 1354
},
"A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": {
"category": "Error",
"code": 1355
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@ -2088,15 +2096,15 @@
"category": "Error",
"code": 2577
},
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.": {
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node`.": {
"category": "Error",
"code": 2580
},
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.": {
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`.": {
"category": "Error",
"code": 2581
},
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig.": {
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.": {
"category": "Error",
"code": 2582
},
@ -2124,6 +2132,26 @@
"category": "Error",
"code": 2588
},
"Type instantiation is excessively deep and possibly infinite.": {
"category": "Error",
"code": 2589
},
"Expression produces a union type that is too complex to represent.": {
"category": "Error",
"code": 2590
},
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.": {
"category": "Error",
"code": 2591
},
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.": {
"category": "Error",
"code": 2592
},
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig.": {
"category": "Error",
"code": 2593
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600

View file

@ -876,8 +876,8 @@ namespace ts {
}
export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | TypeNode, type?: TypeNode) {
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword;
node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType);
@ -2874,7 +2874,7 @@ namespace ts {
return node.emitNode = { annotatedNodes: [node] } as EmitNode;
}
const sourceFile = getSourceFileOfNode(node);
const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node)));
getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node);
}

View file

@ -2966,6 +2966,7 @@ namespace ts {
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.UniqueKeyword:
case SyntaxKind.VoidKeyword:
@ -3055,7 +3056,7 @@ namespace ts {
return finishNode(postfix);
}
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword) {
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
const node = <TypeOperatorNode>createNode(SyntaxKind.TypeOperator);
parseExpected(operator);
node.operator = operator;
@ -3077,6 +3078,7 @@ namespace ts {
switch (operator) {
case SyntaxKind.KeyOfKeyword:
case SyntaxKind.UniqueKeyword:
case SyntaxKind.ReadonlyKeyword:
return parseTypeOperator(operator);
case SyntaxKind.InferKeyword:
return parseInferType();

View file

@ -230,18 +230,18 @@ namespace ts {
const readFileWithCache = (fileName: string): string | undefined => {
const key = toPath(fileName);
const value = readFileCache.get(key);
if (value !== undefined) return value || undefined;
if (value !== undefined) return value !== false ? value : undefined;
return setReadFileCache(key, fileName);
};
const setReadFileCache = (key: Path, fileName: string) => {
const newValue = originalReadFile.call(host, fileName);
readFileCache.set(key, newValue || false);
readFileCache.set(key, newValue !== undefined ? newValue : false);
return newValue;
};
host.readFile = fileName => {
const key = toPath(fileName);
const value = readFileCache.get(key);
if (value !== undefined) return value; // could be .d.ts from output
if (value !== undefined) return value !== false ? value : undefined; // could be .d.ts from output
if (!fileExtensionIs(fileName, Extension.Json)) {
return originalReadFile.call(host, fileName);
}

View file

@ -661,8 +661,15 @@ namespace ts {
let pendingKind!: CommentKind;
let pendingHasTrailingNewLine!: boolean;
let hasPendingCommentRange = false;
let collecting = trailing || pos === 0;
let collecting = trailing;
let accumulator = initial;
if (pos === 0) {
collecting = true;
const shebang = getShebang(text);
if (shebang) {
pos = shebang.length;
}
}
scan: while (pos >= 0 && pos < text.length) {
const ch = text.charCodeAt(pos);
switch (ch) {

View file

@ -1934,8 +1934,13 @@ namespace ts {
case SyntaxKind.ConditionalType:
return serializeTypeList([(<ConditionalTypeNode>node).trueType, (<ConditionalTypeNode>node).falseType]);
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeOperator:
if ((<TypeOperatorNode>node).operator === SyntaxKind.ReadonlyKeyword) {
return serializeTypeNode((<TypeOperatorNode>node).type);
}
break;
case SyntaxKind.TypeQuery:
case SyntaxKind.IndexedAccessType:
case SyntaxKind.MappedType:
case SyntaxKind.TypeLiteral:

View file

@ -1233,7 +1233,7 @@ namespace ts {
export interface TypeOperatorNode extends TypeNode {
kind: SyntaxKind.TypeOperator;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
type: TypeNode;
}
@ -3955,6 +3955,7 @@ namespace ts {
// Unique symbol types (TypeFlags.UniqueESSymbol)
export interface UniqueESSymbolType extends Type {
symbol: Symbol;
escapedName: __String;
}
export interface StringLiteralType extends LiteralType {
@ -4062,6 +4063,7 @@ namespace ts {
export interface TupleType extends GenericType {
minLength: number;
hasRestElement: boolean;
readonly: boolean;
associatedNames?: __String[];
}
@ -4339,6 +4341,7 @@ namespace ts {
None = 0, // No special inference behaviors
NoDefault = 1 << 0, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
AnyDefault = 1 << 1, // Infer anyType for no inferences (otherwise emptyObjectType)
NoFixing = 1 << 2, // Disable type parameter fixing
}
/**
@ -4367,6 +4370,7 @@ namespace ts {
inferences: InferenceInfo[]; // Inferences made for each type parameter
flags: InferenceFlags; // Inference flags
compareTypes: TypeComparer; // Type comparer function
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
}
/* @internal */

View file

@ -778,7 +778,8 @@ namespace ts {
case SyntaxKind.NoSubstitutionTemplateLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteralLike(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
if (isStringOrNumericLiteralLike(name.expression)) return escapeLeadingUnderscores(name.expression.text);
return Debug.fail("Text of property name cannot be read from non-literal-valued ComputedPropertyNames");
default:
return Debug.assertNever(name);
}
@ -5606,6 +5607,11 @@ namespace ts {
return node.kind === SyntaxKind.TypeAssertionExpression;
}
export function isConstTypeReference(node: Node) {
return isTypeReferenceNode(node) && isIdentifier(node.typeName) &&
node.typeName.escapedText === "const" && !node.typeArguments;
}
export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
return node.kind === SyntaxKind.ParenthesizedExpression;
}

View file

@ -375,6 +375,15 @@ namespace fakes {
}
}
export type ExpectedDiagnostic = [ts.DiagnosticMessage, ...(string | number)[]];
function expectedDiagnosticToText([message, ...args]: ExpectedDiagnostic) {
let text = ts.getLocaleSpecificMessage(message);
if (args.length) {
text = ts.formatStringFromArgs(text, args);
}
return text;
}
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost<ts.BuilderProgram> {
createProgram = ts.createAbstractBuilder;
now() {
@ -395,16 +404,10 @@ namespace fakes {
this.diagnostics.length = 0;
}
assertDiagnosticMessages(...expected: ts.DiagnosticMessage[]) {
const actual = this.diagnostics.slice();
if (actual.length !== expected.length) {
assert.fail<any>(actual, expected, `Diagnostic arrays did not match - got\r\n${actual.map(a => " " + a.messageText).join("\r\n")}\r\nexpected\r\n${expected.map(e => " " + e.message).join("\r\n")}`);
}
for (let i = 0; i < actual.length; i++) {
if (actual[i].code !== expected[i].code) {
assert.fail(actual[i].messageText, expected[i].message, `Mismatched error code - expected diagnostic ${i} "${actual[i].messageText}" to match ${expected[i].message}`);
}
}
assertDiagnosticMessages(...expectedDiagnostics: ExpectedDiagnostic[]) {
const actual = this.diagnostics.slice().map(d => d.messageText as string);
const expected = expectedDiagnostics.map(expectedDiagnosticToText);
assert.deepEqual(actual, expected, "Diagnostic arrays did not match");
}
printDiagnostics(header = "== Diagnostics ==") {

View file

@ -103,7 +103,7 @@ interface Atomics {
* Wakes up sleeping agents that are waiting on the given index of the array, returning the
* number of agents that were awoken.
*/
wake(typedArray: Int32Array, index: number, count: number): number;
notify(typedArray: Int32Array, index: number, count: number): number;
/**
* Stores the bitwise XOR of a value with the value at the given position in the array,
@ -115,4 +115,4 @@ interface Atomics {
readonly [Symbol.toStringTag]: "Atomics";
}
declare var Atomics: Atomics;
declare var Atomics: Atomics;

View file

@ -904,7 +904,7 @@ namespace ts.server {
getPreferences(file: NormalizedPath): protocol.UserPreferences {
const info = this.getScriptInfoForNormalizedPath(file);
return info && info.getPreferences() || this.hostConfiguration.preferences;
return { ...this.hostConfiguration.preferences, ...info && info.getPreferences() };
}
getHostFormatCodeOptions(): FormatCodeSettings {

View file

@ -1178,8 +1178,7 @@ namespace ts.server {
private getRenameInfo(args: protocol.FileLocationRequestArgs): RenameInfo {
const { file, project } = this.getFileAndProject(args);
const position = this.getPositionInFile(args, file);
const preferences = this.getHostPreferences();
return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: preferences.allowRenameOfImportPath });
return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath });
}
private getProjects(args: protocol.FileRequestArgs, getScriptInfoEnsuringProjectsUptoDate?: boolean, ignoreNoProjectError?: boolean): Projects {
@ -1234,12 +1233,12 @@ namespace ts.server {
{ fileName: args.file, pos: position },
!!args.findInStrings,
!!args.findInComments,
this.getHostPreferences()
this.getPreferences(file)
);
if (!simplifiedResult) return locations;
const defaultProject = this.getDefaultProject(args);
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getHostPreferences().allowRenameOfImportPath }), Debug.assertDefined(this.projectService.getScriptInfo(file)));
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath }), Debug.assertDefined(this.projectService.getScriptInfo(file)));
return { info: renameInfo, locs: this.toSpanGroups(locations) };
}

View file

@ -274,7 +274,17 @@ namespace ts.codefix {
return !!merged;
}));
const tag = createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags]));
changes.insertJsdocCommentBefore(sourceFile, parent, tag);
const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent;
jsDocNode.jsDoc = parent.jsDoc;
jsDocNode.jsDocCache = parent.jsDocCache;
changes.insertJsdocCommentBefore(sourceFile, jsDocNode, tag);
}
function getJsDocNodeForArrowFunction(signature: ArrowFunction): HasJSDoc {
if (signature.parent.kind === SyntaxKind.PropertyDeclaration) {
return <HasJSDoc>signature.parent;
}
return <HasJSDoc>signature.parent.parent;
}
function tryMergeJsdocTags(oldTag: JSDocTag, newTag: JSDocTag): JSDocTag | undefined {

View file

@ -41,6 +41,7 @@ namespace ts.FindAllReferences {
readonly implementations?: boolean;
/**
* True to opt in for enhanced renaming of shorthand properties and import/export specifiers.
* The options controls the behavior for the whole rename operation; it cannot be changed on a per-file basis.
* Default is false for backwards compatibility.
*/
readonly providePrefixAndSuffixTextForRename?: boolean;

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/run.js",
"composite": false,
@ -43,6 +43,7 @@
"unittests/asserts.ts",
"unittests/base64.ts",
"unittests/builder.ts",
"unittests/comments.ts",
"unittests/compilerCore.ts",
"unittests/convertToBase64.ts",
"unittests/customTransforms.ts",

View file

@ -0,0 +1,32 @@
namespace ts {
describe("comment parsing", () => {
const withShebang = `#! node
/** comment */
// another one
;`;
const noShebang = `/** comment */
// another one
;`;
const withTrailing = `;/* comment */
// another one
`;
it("skips shebang", () => {
const result = getLeadingCommentRanges(withShebang, 0);
assert.isDefined(result);
assert.strictEqual(result!.length, 2);
});
it("treats all comments at start of file as leading comments", () => {
const result = getLeadingCommentRanges(noShebang, 0);
assert.isDefined(result);
assert.strictEqual(result!.length, 2);
});
it("returns leading comments if position is not 0", () => {
const result = getLeadingCommentRanges(withTrailing, 1);
assert.isDefined(result);
assert.strictEqual(result!.length, 1);
assert.strictEqual(result![0].kind, SyntaxKind.SingleLineCommentTrivia);
});
});
}

View file

@ -400,6 +400,46 @@ namespace Foo {
}
}).outputText;
});
// https://github.com/Microsoft/TypeScript/issues/24709
testBaseline("issue24709", () => {
const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true);
const transformed = transform(createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ScriptTarget.ES3), [transformSourceFile]);
const transformedSourceFile = transformed.transformed[0];
transformed.dispose();
const host = new fakes.CompilerHost(fs);
host.getSourceFile = () => transformedSourceFile;
const program = createProgram(["source.ts"], {
target: ScriptTarget.ES3,
module: ModuleKind.None,
noLib: true
}, host);
program.emit(transformedSourceFile, (_p, s, b) => host.writeFile("source.js", s, b));
return host.readFile("source.js")!.toString();
function transformSourceFile(context: TransformationContext) {
const visitor: Visitor = (node) => {
if (isMethodDeclaration(node)) {
return updateMethod(
node,
node.decorators,
node.modifiers,
node.asteriskToken,
createIdentifier("foobar"),
node.questionToken,
node.typeParameters,
node.parameters,
node.type,
node.body,
);
}
return visitEachChild(node, visitor, context);
};
return (node: SourceFile) => visitNode(node, visitor);
}
});
});
}

View file

@ -1,5 +1,10 @@
namespace ts {
let currentTime = 100;
function getExpectedDiagnosticForProjectsInBuild(...projects: string[]): fakes.ExpectedDiagnostic {
return [Diagnostics.Projects_in_this_build_Colon_0, projects.map(p => "\r\n * " + p).join("")];
}
export namespace Sample1 {
tick();
const projFs = loadProjectFromDisk("tests/projects/sample1");
@ -67,7 +72,11 @@ namespace ts {
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false });
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0, Diagnostics.A_non_dry_build_would_build_project_0);
host.assertDiagnosticMessages(
[Diagnostics.A_non_dry_build_would_build_project_0, "/src/core/tsconfig.json"],
[Diagnostics.A_non_dry_build_would_build_project_0, "/src/logic/tsconfig.json"],
[Diagnostics.A_non_dry_build_would_build_project_0, "/src/tests/tsconfig.json"]
);
// Check for outputs to not be written. Not an exhaustive list
for (const output of allExpectedOutputs) {
@ -86,7 +95,11 @@ namespace ts {
host.clearDiagnostics();
builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false });
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date, Diagnostics.Project_0_is_up_to_date);
host.assertDiagnosticMessages(
[Diagnostics.Project_0_is_up_to_date, "/src/core/tsconfig.json"],
[Diagnostics.Project_0_is_up_to_date, "/src/logic/tsconfig.json"],
[Diagnostics.Project_0_is_up_to_date, "/src/tests/tsconfig.json"]
);
});
});
@ -146,13 +159,15 @@ namespace ts {
host.clearDiagnostics();
builder.resetBuildContext();
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
Diagnostics.Building_project_0,
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
Diagnostics.Building_project_0,
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
Diagnostics.Building_project_0);
host.assertDiagnosticMessages(
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/logic/tsconfig.json", "src/logic/index.js"],
[Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tests/tsconfig.json", "src/tests/index.js"],
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
);
tick();
});
@ -161,10 +176,12 @@ namespace ts {
host.clearDiagnostics();
builder.resetBuildContext();
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2);
host.assertDiagnosticMessages(
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/logic/tsconfig.json", "src/logic/index.ts", "src/logic/index.js"],
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/tests/tsconfig.json", "src/tests/index.ts", "src/tests/index.js"]
);
tick();
});
@ -175,11 +192,13 @@ namespace ts {
builder.resetBuildContext();
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
Diagnostics.Building_project_0);
host.assertDiagnosticMessages(
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/logic/tsconfig.json", "src/logic/index.ts", "src/logic/index.js"],
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tests/tsconfig.json", "src/tests/index.js", "src/tests/index.ts"],
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
);
tick();
});
@ -190,13 +209,15 @@ namespace ts {
builder.resetBuildContext();
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.Projects_in_this_build_Colon_0,
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
Diagnostics.Building_project_0,
Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
Diagnostics.Updating_output_timestamps_of_project_0,
Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
Diagnostics.Updating_output_timestamps_of_project_0);
host.assertDiagnosticMessages(
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/core/tsconfig.json", "src/core/anotherModule.js", "src/core/index.ts"],
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
[Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, "src/logic/tsconfig.json"],
[Diagnostics.Updating_output_timestamps_of_project_0, "/src/logic/tsconfig.json"],
[Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, "src/tests/tsconfig.json"],
[Diagnostics.Updating_output_timestamps_of_project_0, "/src/tests/tsconfig.json"]
);
});
});
@ -210,14 +231,14 @@ namespace ts {
replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`);
builder.buildAllProjects();
host.assertDiagnosticMessages(
Diagnostics.Projects_in_this_build_Colon_0,
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
Diagnostics.Building_project_0,
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
Diagnostics.Building_project_0,
Diagnostics.Property_0_does_not_exist_on_type_1,
Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors,
Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/logic/tsconfig.json", "src/logic/index.js"],
[Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
[Diagnostics.Property_0_does_not_exist_on_type_1, "muitply", `typeof import("/src/core/index")`],
[Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, "src/tests/tsconfig.json", "src/logic"],
[Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, "/src/tests/tsconfig.json", "/src/logic"]
);
});
});
@ -281,12 +302,12 @@ export class cNew {}`);
const projFs = loadProjectFromDisk("tests/projects/resolveJsonModuleAndComposite");
const allExpectedOutputs = ["/src/tests/dist/src/index.js", "/src/tests/dist/src/index.d.ts", "/src/tests/dist/src/hello.json"];
function verifyProjectWithResolveJsonModule(configFile: string, ...expectedDiagnosticMessages: DiagnosticMessage[]) {
function verifyProjectWithResolveJsonModule(configFile: string, ...expectedDiagnosticMessages: fakes.ExpectedDiagnostic[]) {
const fs = projFs.shadow();
verifyProjectWithResolveJsonModuleWithFs(fs, configFile, allExpectedOutputs, ...expectedDiagnosticMessages);
}
function verifyProjectWithResolveJsonModuleWithFs(fs: vfs.FileSystem, configFile: string, allExpectedOutputs: ReadonlyArray<string>, ...expectedDiagnosticMessages: DiagnosticMessage[]) {
function verifyProjectWithResolveJsonModuleWithFs(fs: vfs.FileSystem, configFile: string, allExpectedOutputs: ReadonlyArray<string>, ...expectedDiagnosticMessages: fakes.ExpectedDiagnostic[]) {
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, [configFile], { dry: false, force: false, verbose: false });
builder.buildAllProjects();
@ -300,7 +321,10 @@ export class cNew {}`);
}
it("with resolveJsonModule and include only", () => {
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withInclude.json", Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern);
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withInclude.json", [
Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern,
"/src/tests/src/hello.json"
]);
});
it("with resolveJsonModule and include of *.json along with other include", () => {
@ -415,7 +439,7 @@ export default hello.hello`);
"/src/c.ts"
];
function verifyBuild(modifyDiskLayout: (fs: vfs.FileSystem) => void, allExpectedOutputs: ReadonlyArray<string>, expectedDiagnostics: DiagnosticMessage[], expectedFileTraces: ReadonlyArray<string>) {
function verifyBuild(modifyDiskLayout: (fs: vfs.FileSystem) => void, allExpectedOutputs: ReadonlyArray<string>, expectedFileTraces: ReadonlyArray<string>, ...expectedDiagnostics: fakes.ExpectedDiagnostic[]) {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
modifyDiskLayout(fs);
@ -442,11 +466,11 @@ export const b = new A();`);
}
it("verify that it builds correctly", () => {
verifyBuild(noop, allExpectedOutputs, emptyArray, expectedFileTraces);
verifyBuild(noop, allExpectedOutputs, expectedFileTraces);
});
it("verify that it builds correctly when the referenced project uses different module resolution", () => {
verifyBuild(fs => modifyFsBTsToNonRelativeImport(fs, "classic"), allExpectedOutputs, emptyArray, expectedFileTraces);
verifyBuild(fs => modifyFsBTsToNonRelativeImport(fs, "classic"), allExpectedOutputs, expectedFileTraces);
});
it("verify that it build reports error about module not found with node resolution with external module name", () => {
@ -458,10 +482,25 @@ export const b = new A();`);
];
verifyBuild(fs => modifyFsBTsToNonRelativeImport(fs, "node"),
allExpectedOutputs,
[Diagnostics.Cannot_find_module_0],
expectedFileTraces);
expectedFileTraces,
[Diagnostics.Cannot_find_module_0, "a"],
);
});
});
it("unittests:: tsbuild - when tsconfig extends the missing file", () => {
const projFs = loadProjectFromDisk("tests/projects/missingExtendedConfig");
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tsconfig.json"], {});
builder.buildAllProjects();
host.assertDiagnosticMessages(
[Diagnostics.The_specified_path_does_not_exist_Colon_0, "/src/foobar.json"],
[Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, "/src/tsconfig.first.json", "[\"**/*\"]", "[]"],
[Diagnostics.The_specified_path_does_not_exist_Colon_0, "/src/foobar.json"],
[Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, "/src/tsconfig.second.json", "[\"**/*\"]", "[]"]
);
});
}
export namespace OutFile {
@ -564,7 +603,7 @@ export const b = new A();`);
host.clearDiagnostics();
builder.buildAllProjects();
host.assertDiagnosticMessages(Diagnostics.The_files_list_in_config_file_0_is_empty);
host.assertDiagnosticMessages([Diagnostics.The_files_list_in_config_file_0_is_empty, "/src/no-references/tsconfig.json"]);
// Check for outputs to not be written.
for (const output of allExpectedOutputs) {

View file

@ -7,6 +7,7 @@ namespace ts.projectSystem {
const session = createSession(createServerHost([aTs, bTs]));
openFilesForSession([bTs], session);
// rename fails with allowRenameOfImportPath disabled
const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
info: {
@ -16,6 +17,7 @@ namespace ts.projectSystem {
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
});
// rename succeeds with allowRenameOfImportPath enabled in host
session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: true } });
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
@ -30,6 +32,23 @@ namespace ts.projectSystem {
},
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
});
// rename succeeds with allowRenameOfImportPath enabled in file
session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: false } });
session.getProjectService().setHostConfiguration({ file: "/b.ts", formatOptions: {}, preferences: { allowRenameOfImportPath: true } });
const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
info: {
canRename: true,
fileToRename: aTs.path,
displayName: aTs.path,
fullDisplayName: aTs.path,
kind: ScriptElementKind.moduleElement,
kindModifiers: "",
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
},
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
});
});
it("works with prefixText and suffixText when enabled", () => {
@ -61,7 +80,7 @@ namespace ts.projectSystem {
],
});
// rename with prefixText and suffixText enabled
// rename with prefixText and suffixText enabled in host
session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: true } });
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
@ -84,6 +103,93 @@ namespace ts.projectSystem {
},
],
});
// rename with prefixText and suffixText enabled for file
session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: false } });
session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
info: {
canRename: true,
fileToRename: undefined,
displayName: "x",
fullDisplayName: "x",
kind: ScriptElementKind.constElement,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
},
locs: [
{
file: aTs.path,
locs: [
protocolRenameSpanFromSubstring(aTs.content, "x"),
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }, { prefixText: "x: " }),
],
},
],
});
});
it("rename behavior is based on file of rename initiation", () => {
const aTs: File = { path: "/a.ts", content: "const x = 1; export { x };" };
const bTs: File = { path: "/b.ts", content: `import { x } from "./a"; const y = x + 1;` };
const host = createServerHost([aTs, bTs]);
const session = createSession(host);
openFilesForSession([aTs, bTs], session);
// rename from file with prefixText and suffixText enabled
session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
info: {
canRename: true,
fileToRename: undefined,
displayName: "x",
fullDisplayName: "x",
kind: ScriptElementKind.constElement,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
},
locs: [
{
file: aTs.path,
locs: [
protocolRenameSpanFromSubstring(aTs.content, "x"),
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }, { suffixText: " as x" }),
],
},
],
});
// rename from file with prefixText and suffixText disabled
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
info: {
canRename: true,
fileToRename: undefined,
displayName: "x",
fullDisplayName: "x",
kind: ScriptElementKind.alias,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "x"),
},
locs: [
{
file: bTs.path,
locs: [
protocolRenameSpanFromSubstring(bTs.content, "x"),
protocolRenameSpanFromSubstring(bTs.content, "x", { index: 1 })
]
},
{
file: aTs.path,
locs: [
protocolRenameSpanFromSubstring(aTs.content, "x"),
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }),
],
},
],
});
});
});
}

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/tsc.js"
},

View file

@ -0,0 +1,8 @@
{
"extends": "./tsconfig-base",
"compilerOptions": {
"declaration": false,
"declarationMap": false,
"composite": false
}
}

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/tsserver.js",

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../built/local/typingsInstaller.js",

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../built/local/watchGuard.js",
@ -13,4 +13,4 @@
"files": [
"watchGuard.ts"
]
}
}

View file

@ -1,22 +1,22 @@
tests/cases/compiler/anonymousModules.ts(1,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
tests/cases/compiler/anonymousModules.ts(1,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
tests/cases/compiler/anonymousModules.ts(1,8): error TS1005: ';' expected.
tests/cases/compiler/anonymousModules.ts(4,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
tests/cases/compiler/anonymousModules.ts(4,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
tests/cases/compiler/anonymousModules.ts(4,9): error TS1005: ';' expected.
tests/cases/compiler/anonymousModules.ts(10,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
tests/cases/compiler/anonymousModules.ts(10,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
tests/cases/compiler/anonymousModules.ts(10,9): error TS1005: ';' expected.
==== tests/cases/compiler/anonymousModules.ts (6 errors) ====
module {
~~~~~~
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
~
!!! error TS1005: ';' expected.
export var foo = 1;
module {
~~~~~~
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
~
!!! error TS1005: ';' expected.
export var bar = 1;
@ -26,7 +26,7 @@ tests/cases/compiler/anonymousModules.ts(10,9): error TS1005: ';' expected.
module {
~~~~~~
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
~
!!! error TS1005: ';' expected.
var x = bar;

View file

@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.3";
const versionMajorMinor = "3.4";
/** The version of the TypeScript compiler release */
const version: string;
}
@ -814,7 +814,7 @@ declare namespace ts {
}
interface TypeOperatorNode extends TypeNode {
kind: SyntaxKind.TypeOperator;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
type: TypeNode;
}
interface IndexedAccessTypeNode extends TypeNode {
@ -2217,6 +2217,7 @@ declare namespace ts {
}
interface UniqueESSymbolType extends Type {
symbol: Symbol;
escapedName: __String;
}
interface StringLiteralType extends LiteralType {
value: string;
@ -2285,6 +2286,7 @@ declare namespace ts {
interface TupleType extends GenericType {
minLength: number;
hasRestElement: boolean;
readonly: boolean;
associatedNames?: __String[];
}
interface TupleTypeReference extends TypeReference {
@ -3358,6 +3360,7 @@ declare namespace ts {
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
function isConstTypeReference(node: Node): boolean;
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
function skipPartiallyEmittedExpressions(node: Expression): Expression;
function skipPartiallyEmittedExpressions(node: Node): Node;
@ -3758,7 +3761,7 @@ declare namespace ts {
function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode;
function createThisTypeNode(): ThisTypeNode;
function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode;
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
@ -8343,7 +8346,7 @@ declare namespace ts.server {
excludedFiles: ReadonlyArray<NormalizedPath>;
private typeAcquisition;
updateGraph(): boolean;
getExcludedFiles(): ReadonlyArray<NormalizedPath>;
getExcludedFiles(): readonly NormalizedPath[];
getTypeAcquisition(): TypeAcquisition;
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void;
}

View file

@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.3";
const versionMajorMinor = "3.4";
/** The version of the TypeScript compiler release */
const version: string;
}
@ -814,7 +814,7 @@ declare namespace ts {
}
interface TypeOperatorNode extends TypeNode {
kind: SyntaxKind.TypeOperator;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
type: TypeNode;
}
interface IndexedAccessTypeNode extends TypeNode {
@ -2217,6 +2217,7 @@ declare namespace ts {
}
interface UniqueESSymbolType extends Type {
symbol: Symbol;
escapedName: __String;
}
interface StringLiteralType extends LiteralType {
value: string;
@ -2285,6 +2286,7 @@ declare namespace ts {
interface TupleType extends GenericType {
minLength: number;
hasRestElement: boolean;
readonly: boolean;
associatedNames?: __String[];
}
interface TupleTypeReference extends TypeReference {
@ -3358,6 +3360,7 @@ declare namespace ts {
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
function isConstTypeReference(node: Node): boolean;
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
function skipPartiallyEmittedExpressions(node: Expression): Expression;
function skipPartiallyEmittedExpressions(node: Node): Node;
@ -3758,7 +3761,7 @@ declare namespace ts {
function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode;
function createThisTypeNode(): ThisTypeNode;
function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode;
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;

View file

@ -30,15 +30,15 @@ const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(is
>isNumber : (x: any) => x is number
const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean>;
>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray<string | number | boolean>
>arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean> : ReadonlyArray<string | number | boolean>
>readonlyArrayOfStringsNumbersAndBooleans : readonly (string | number | boolean)[]
>arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean> : readonly (string | number | boolean)[]
>arrayOfStringsNumbersAndBooleans : (string | number | boolean)[]
const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber);
>readonlyFoundNumber : number
>readonlyArrayOfStringsNumbersAndBooleans.find(isNumber) : number
>readonlyArrayOfStringsNumbersAndBooleans.find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => boolean, thisArg?: any): string | number | boolean; }
>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray<string | number | boolean>
>find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => boolean, thisArg?: any): string | number | boolean; }
>readonlyArrayOfStringsNumbersAndBooleans.find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; }
>readonlyArrayOfStringsNumbersAndBooleans : readonly (string | number | boolean)[]
>find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; }
>isNumber : (x: any) => x is number

View file

@ -4,22 +4,22 @@ const array: number[] = [];
>[] : undefined[]
const readonlyArray: ReadonlyArray<number> = [];
>readonlyArray : ReadonlyArray<number>
>readonlyArray : readonly number[]
>[] : undefined[]
array.flatMap((): ReadonlyArray<number> => []); // ok
>array.flatMap((): ReadonlyArray<number> => []) : number[]
>array.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
>array.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
>array : number[]
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
>(): ReadonlyArray<number> => [] : () => ReadonlyArray<number>
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
>(): ReadonlyArray<number> => [] : () => readonly number[]
>[] : undefined[]
readonlyArray.flatMap((): ReadonlyArray<number> => []); // ok
>readonlyArray.flatMap((): ReadonlyArray<number> => []) : number[]
>readonlyArray.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
>readonlyArray : ReadonlyArray<number>
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
>(): ReadonlyArray<number> => [] : () => ReadonlyArray<number>
>readonlyArray.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
>readonlyArray : readonly number[]
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
>(): ReadonlyArray<number> => [] : () => readonly number[]
>[] : undefined[]

View file

@ -1,6 +1,6 @@
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'readonly B[]'.
Property 'b' is missing in type 'A' but required in type 'B'.
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C<A>' is not assignable to type 'readonly B[]'.
Types of property 'concat' are incompatible.
Type '{ (...items: ConcatArray<A>[]): A[]; (...items: (A | ConcatArray<A>)[]): A[]; }' is not assignable to type '{ (...items: ConcatArray<B>[]): B[]; (...items: (B | ConcatArray<B>)[]): B[]; }'.
Type 'A[]' is not assignable to type 'B[]'.
@ -22,7 +22,7 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T
rra = arb;
rrb = ara; // error: 'A' is not assignable to 'B'
~~~
!!! error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
!!! error TS2322: Type 'A[]' is not assignable to type 'readonly B[]'.
!!! error TS2322: Property 'b' is missing in type 'A' but required in type 'B'.
!!! related TS2728 tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts:2:21: 'b' is declared here.
@ -31,7 +31,7 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T
rrb = crb;
rrb = cra; // error: 'A' is not assignable to 'B'
~~~
!!! error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
!!! error TS2322: Type 'C<A>' is not assignable to type 'readonly B[]'.
!!! error TS2322: Types of property 'concat' are incompatible.
!!! error TS2322: Type '{ (...items: ConcatArray<A>[]): A[]; (...items: (A | ConcatArray<A>)[]): A[]; }' is not assignable to type '{ (...items: ConcatArray<B>[]): B[]; (...items: (B | ConcatArray<B>)[]): B[]; }'.
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.

View file

@ -26,48 +26,48 @@ declare var crb: C<B>;
>crb : C<B>
declare var rra: ReadonlyArray<A>;
>rra : ReadonlyArray<A>
>rra : readonly A[]
declare var rrb: ReadonlyArray<B>;
>rrb : ReadonlyArray<B>
>rrb : readonly B[]
rra = ara;
>rra = ara : A[]
>rra : ReadonlyArray<A>
>rra : readonly A[]
>ara : A[]
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
>rrb = arb : B[]
>rrb : ReadonlyArray<B>
>rrb : readonly B[]
>arb : B[]
rra = arb;
>rra = arb : B[]
>rra : ReadonlyArray<A>
>rra : readonly A[]
>arb : B[]
rrb = ara; // error: 'A' is not assignable to 'B'
>rrb = ara : A[]
>rrb : ReadonlyArray<B>
>rrb : readonly B[]
>ara : A[]
rra = cra;
>rra = cra : C<A>
>rra : ReadonlyArray<A>
>rra : readonly A[]
>cra : C<A>
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
>rra = crb : C<B>
>rra : ReadonlyArray<A>
>rra : readonly A[]
>crb : C<B>
rrb = crb;
>rrb = crb : C<B>
>rrb : ReadonlyArray<B>
>rrb : readonly B[]
>crb : C<B>
rrb = cra; // error: 'A' is not assignable to 'B'
>rrb = cra : C<A>
>rrb : ReadonlyArray<B>
>rrb : readonly B[]
>cra : C<A>

View file

@ -3,9 +3,9 @@
interface Array<T> {
equalsShallow<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>): boolean;
>equalsShallow : <T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean
>this : ReadonlyArray<T>
>other : ReadonlyArray<T>
>equalsShallow : <T>(this: readonly T[], other: readonly T[]) => boolean
>this : readonly T[]
>other : readonly T[]
}
declare const a: (string | number)[] | null[] | undefined[] | {}[];
@ -19,8 +19,8 @@ declare const b: (string | number)[] | null[] | undefined[] | {}[];
let x = a.equalsShallow(b);
>x : boolean
>a.equalsShallow(b) : boolean
>a.equalsShallow : (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean)
>a.equalsShallow : (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean)
>a : (string | number)[] | null[] | undefined[] | {}[]
>equalsShallow : (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean)
>equalsShallow : (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean)
>b : (string | number)[] | null[] | undefined[] | {}[]

View file

@ -3,9 +3,9 @@
Object.freeze({
>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }>
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>{ foo() { return Object.freeze('a'); },} : { foo(): string; }
foo() {
@ -13,9 +13,9 @@ Object.freeze({
return Object.freeze('a');
>Object.freeze('a') : string
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>'a' : "a"
},

View file

@ -1,11 +1,11 @@
tests/cases/conformance/salsa/bug24934.js(2,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
tests/cases/conformance/salsa/bug24934.js(2,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
==== tests/cases/conformance/salsa/bug24934.js (1 errors) ====
export function abc(a, b, c) { return 5; }
module.exports = { abc };
~~~~~~
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
==== tests/cases/conformance/salsa/use.js (0 errors) ====
import { abc } from './bug24934';
abc(1, 2, 3);

View file

@ -0,0 +1,79 @@
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(44,32): error TS2540: Cannot assign to 'x' because it is a read-only property.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
==== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts (4 errors) ====
let v1 = 'abc' as const;
let v2 = `abc` as const;
let v3 = 10 as const;
let v4 = -10 as const;
let v5 = +10 as const;
let v6 = 10n as const;
let v7 = -10n as const;
let v8 = true as const;
let v9 = false as const;
let c1 = 'abc' as const;
let c2 = `abc` as const;
let c3 = 10 as const;
let c4 = -10 as const;
let c5 = +10 as const;
let c6 = 10n as const;
let c7 = -10n as const;
let c8 = true as const;
let c9 = false as const;
let vv1 = v1;
let vc1 = c1;
let a1 = [] as const;
let a2 = [1, 2, 3] as const;
let a3 = [10, 'hello', true] as const;
let a4 = [...[1, 2, 3]] as const;
let a5 = [1, 2, 3];
let a6 = [...a5] as const;
let a7 = [...a6];
let a8 = ['abc', ...a7] as const;
let a9 = [...a8];
declare let d: { [x: string]: string };
let o1 = { x: 10, y: 20 } as const;
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
let o3 = { ...o1, ...o2 } as const;
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 } as const;
let o6 = { ...o5 };
let o7 = { ...d } as const;
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
~
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
let p1 = (10) as const;
let p2 = ((-10)) as const;
let p3 = ([(10)]) as const;
let p4 = [[[[10]]]] as const;
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
let q1 = <const> 10;
let q2 = <const> 'abc';
let q3 = <const> true;
let q4 = <const> [1, 2, 3];
let q5 = <const> { x: 10, y: 20 };
declare function id<T>(x: T): T;
let e1 = v1 as const; // Error
~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
let e2 = (true ? 1 : 0) as const; // Error
~~~~~~~~~~~~~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
let e3 = id(1) as const; // Error
~~~~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.

View file

@ -0,0 +1,220 @@
//// [constAssertions.ts]
let v1 = 'abc' as const;
let v2 = `abc` as const;
let v3 = 10 as const;
let v4 = -10 as const;
let v5 = +10 as const;
let v6 = 10n as const;
let v7 = -10n as const;
let v8 = true as const;
let v9 = false as const;
let c1 = 'abc' as const;
let c2 = `abc` as const;
let c3 = 10 as const;
let c4 = -10 as const;
let c5 = +10 as const;
let c6 = 10n as const;
let c7 = -10n as const;
let c8 = true as const;
let c9 = false as const;
let vv1 = v1;
let vc1 = c1;
let a1 = [] as const;
let a2 = [1, 2, 3] as const;
let a3 = [10, 'hello', true] as const;
let a4 = [...[1, 2, 3]] as const;
let a5 = [1, 2, 3];
let a6 = [...a5] as const;
let a7 = [...a6];
let a8 = ['abc', ...a7] as const;
let a9 = [...a8];
declare let d: { [x: string]: string };
let o1 = { x: 10, y: 20 } as const;
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
let o3 = { ...o1, ...o2 } as const;
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 } as const;
let o6 = { ...o5 };
let o7 = { ...d } as const;
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
let p1 = (10) as const;
let p2 = ((-10)) as const;
let p3 = ([(10)]) as const;
let p4 = [[[[10]]]] as const;
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
let q1 = <const> 10;
let q2 = <const> 'abc';
let q3 = <const> true;
let q4 = <const> [1, 2, 3];
let q5 = <const> { x: 10, y: 20 };
declare function id<T>(x: T): T;
let e1 = v1 as const; // Error
let e2 = (true ? 1 : 0) as const; // Error
let e3 = id(1) as const; // Error
//// [constAssertions.js]
"use strict";
let v1 = 'abc';
let v2 = `abc`;
let v3 = 10;
let v4 = -10;
let v5 = +10;
let v6 = 10n;
let v7 = -10n;
let v8 = true;
let v9 = false;
let c1 = 'abc';
let c2 = `abc`;
let c3 = 10;
let c4 = -10;
let c5 = +10;
let c6 = 10n;
let c7 = -10n;
let c8 = true;
let c9 = false;
let vv1 = v1;
let vc1 = c1;
let a1 = [];
let a2 = [1, 2, 3];
let a3 = [10, 'hello', true];
let a4 = [...[1, 2, 3]];
let a5 = [1, 2, 3];
let a6 = [...a5];
let a7 = [...a6];
let a8 = ['abc', ...a7];
let a9 = [...a8];
let o1 = { x: 10, y: 20 };
let o2 = { a: 1, 'b': 2, ['c']: 3, d() { }, ['e' + '']: 4 };
let o3 = { ...o1, ...o2 };
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 };
let o6 = { ...o5 };
let o7 = { ...d };
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20; } }; // Error
let p1 = (10);
let p2 = ((-10));
let p3 = ([(10)]);
let p4 = [[[[10]]]];
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } };
let q1 = 10;
let q2 = 'abc';
let q3 = true;
let q4 = [1, 2, 3];
let q5 = { x: 10, y: 20 };
let e1 = v1; // Error
let e2 = (true ? 1 : 0); // Error
let e3 = id(1); // Error
//// [constAssertions.d.ts]
declare let v1: "abc";
declare let v2: "abc";
declare let v3: 10;
declare let v4: -10;
declare let v5: 10;
declare let v6: 10n;
declare let v7: -10n;
declare let v8: true;
declare let v9: false;
declare let c1: "abc";
declare let c2: "abc";
declare let c3: 10;
declare let c4: -10;
declare let c5: 10;
declare let c6: 10n;
declare let c7: -10n;
declare let c8: true;
declare let c9: false;
declare let vv1: "abc";
declare let vc1: "abc";
declare let a1: readonly [];
declare let a2: readonly [1, 2, 3];
declare let a3: readonly [10, "hello", true];
declare let a4: readonly (1 | 2 | 3)[];
declare let a5: number[];
declare let a6: readonly number[];
declare let a7: number[];
declare let a8: readonly ["abc", ...number[]];
declare let a9: (number | "abc")[];
declare let d: {
[x: string]: string;
};
declare let o1: {
readonly x: 10;
readonly y: 20;
};
declare let o2: {
readonly [x: string]: 1 | 2 | 3 | (() => void) | 4;
readonly a: 1;
readonly 'b': 2;
readonly ['c']: 3;
readonly d: () => void;
};
declare let o3: {
readonly a: 1;
readonly 'b': 2;
readonly ['c']: 3;
readonly d: () => void;
readonly x: 10;
readonly y: 20;
};
declare let o4: {
a: number;
b: number;
};
declare let o5: {
readonly a: number;
readonly b: number;
};
declare let o6: {
a: number;
b: number;
};
declare let o7: {
readonly [x: string]: string;
};
declare let o8: {
[x: string]: string;
};
declare let o9: {
readonly x: 10;
readonly foo: () => void;
};
declare let p1: 10;
declare let p2: -10;
declare let p3: readonly [10];
declare let p4: readonly [readonly [readonly [readonly [10]]]];
declare let x1: {
readonly x: 10;
readonly y: readonly [20, 30];
z: {
a: {
readonly b: 42;
};
};
};
declare let q1: 10;
declare let q2: "abc";
declare let q3: true;
declare let q4: readonly [1, 2, 3];
declare let q5: {
readonly x: 10;
readonly y: 20;
};
declare function id<T>(x: T): T;
declare let e1: "abc";
declare let e2: 0 | 1;
declare let e3: 1;

View file

@ -0,0 +1,201 @@
=== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts ===
let v1 = 'abc' as const;
>v1 : Symbol(v1, Decl(constAssertions.ts, 0, 3))
let v2 = `abc` as const;
>v2 : Symbol(v2, Decl(constAssertions.ts, 1, 3))
let v3 = 10 as const;
>v3 : Symbol(v3, Decl(constAssertions.ts, 2, 3))
let v4 = -10 as const;
>v4 : Symbol(v4, Decl(constAssertions.ts, 3, 3))
let v5 = +10 as const;
>v5 : Symbol(v5, Decl(constAssertions.ts, 4, 3))
let v6 = 10n as const;
>v6 : Symbol(v6, Decl(constAssertions.ts, 5, 3))
let v7 = -10n as const;
>v7 : Symbol(v7, Decl(constAssertions.ts, 6, 3))
let v8 = true as const;
>v8 : Symbol(v8, Decl(constAssertions.ts, 7, 3))
let v9 = false as const;
>v9 : Symbol(v9, Decl(constAssertions.ts, 8, 3))
let c1 = 'abc' as const;
>c1 : Symbol(c1, Decl(constAssertions.ts, 10, 3))
let c2 = `abc` as const;
>c2 : Symbol(c2, Decl(constAssertions.ts, 11, 3))
let c3 = 10 as const;
>c3 : Symbol(c3, Decl(constAssertions.ts, 12, 3))
let c4 = -10 as const;
>c4 : Symbol(c4, Decl(constAssertions.ts, 13, 3))
let c5 = +10 as const;
>c5 : Symbol(c5, Decl(constAssertions.ts, 14, 3))
let c6 = 10n as const;
>c6 : Symbol(c6, Decl(constAssertions.ts, 15, 3))
let c7 = -10n as const;
>c7 : Symbol(c7, Decl(constAssertions.ts, 16, 3))
let c8 = true as const;
>c8 : Symbol(c8, Decl(constAssertions.ts, 17, 3))
let c9 = false as const;
>c9 : Symbol(c9, Decl(constAssertions.ts, 18, 3))
let vv1 = v1;
>vv1 : Symbol(vv1, Decl(constAssertions.ts, 20, 3))
>v1 : Symbol(v1, Decl(constAssertions.ts, 0, 3))
let vc1 = c1;
>vc1 : Symbol(vc1, Decl(constAssertions.ts, 21, 3))
>c1 : Symbol(c1, Decl(constAssertions.ts, 10, 3))
let a1 = [] as const;
>a1 : Symbol(a1, Decl(constAssertions.ts, 23, 3))
let a2 = [1, 2, 3] as const;
>a2 : Symbol(a2, Decl(constAssertions.ts, 24, 3))
let a3 = [10, 'hello', true] as const;
>a3 : Symbol(a3, Decl(constAssertions.ts, 25, 3))
let a4 = [...[1, 2, 3]] as const;
>a4 : Symbol(a4, Decl(constAssertions.ts, 26, 3))
let a5 = [1, 2, 3];
>a5 : Symbol(a5, Decl(constAssertions.ts, 27, 3))
let a6 = [...a5] as const;
>a6 : Symbol(a6, Decl(constAssertions.ts, 28, 3))
>a5 : Symbol(a5, Decl(constAssertions.ts, 27, 3))
let a7 = [...a6];
>a7 : Symbol(a7, Decl(constAssertions.ts, 29, 3))
>a6 : Symbol(a6, Decl(constAssertions.ts, 28, 3))
let a8 = ['abc', ...a7] as const;
>a8 : Symbol(a8, Decl(constAssertions.ts, 30, 3))
>a7 : Symbol(a7, Decl(constAssertions.ts, 29, 3))
let a9 = [...a8];
>a9 : Symbol(a9, Decl(constAssertions.ts, 31, 3))
>a8 : Symbol(a8, Decl(constAssertions.ts, 30, 3))
declare let d: { [x: string]: string };
>d : Symbol(d, Decl(constAssertions.ts, 33, 11))
>x : Symbol(x, Decl(constAssertions.ts, 33, 18))
let o1 = { x: 10, y: 20 } as const;
>o1 : Symbol(o1, Decl(constAssertions.ts, 35, 3))
>x : Symbol(x, Decl(constAssertions.ts, 35, 10))
>y : Symbol(y, Decl(constAssertions.ts, 35, 17))
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
>o2 : Symbol(o2, Decl(constAssertions.ts, 36, 3))
>a : Symbol(a, Decl(constAssertions.ts, 36, 10))
>'b' : Symbol('b', Decl(constAssertions.ts, 36, 16))
>['c'] : Symbol(['c'], Decl(constAssertions.ts, 36, 24))
>'c' : Symbol(['c'], Decl(constAssertions.ts, 36, 24))
>d : Symbol(d, Decl(constAssertions.ts, 36, 34))
>['e' + ''] : Symbol(['e' + ''], Decl(constAssertions.ts, 36, 42))
let o3 = { ...o1, ...o2 } as const;
>o3 : Symbol(o3, Decl(constAssertions.ts, 37, 3))
>o1 : Symbol(o1, Decl(constAssertions.ts, 35, 3))
>o2 : Symbol(o2, Decl(constAssertions.ts, 36, 3))
let o4 = { a: 1, b: 2 };
>o4 : Symbol(o4, Decl(constAssertions.ts, 38, 3))
>a : Symbol(a, Decl(constAssertions.ts, 38, 10))
>b : Symbol(b, Decl(constAssertions.ts, 38, 16))
let o5 = { ...o4 } as const;
>o5 : Symbol(o5, Decl(constAssertions.ts, 39, 3))
>o4 : Symbol(o4, Decl(constAssertions.ts, 38, 3))
let o6 = { ...o5 };
>o6 : Symbol(o6, Decl(constAssertions.ts, 40, 3))
>o5 : Symbol(o5, Decl(constAssertions.ts, 39, 3))
let o7 = { ...d } as const;
>o7 : Symbol(o7, Decl(constAssertions.ts, 41, 3))
>d : Symbol(d, Decl(constAssertions.ts, 33, 11))
let o8 = { ...o7 };
>o8 : Symbol(o8, Decl(constAssertions.ts, 42, 3))
>o7 : Symbol(o7, Decl(constAssertions.ts, 41, 3))
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
>o9 : Symbol(o9, Decl(constAssertions.ts, 43, 3))
>x : Symbol(x, Decl(constAssertions.ts, 43, 10))
>foo : Symbol(foo, Decl(constAssertions.ts, 43, 17))
>this.x : Symbol(x, Decl(constAssertions.ts, 43, 10))
>this : Symbol(__object, Decl(constAssertions.ts, 43, 8))
>x : Symbol(x, Decl(constAssertions.ts, 43, 10))
let p1 = (10) as const;
>p1 : Symbol(p1, Decl(constAssertions.ts, 45, 3))
let p2 = ((-10)) as const;
>p2 : Symbol(p2, Decl(constAssertions.ts, 46, 3))
let p3 = ([(10)]) as const;
>p3 : Symbol(p3, Decl(constAssertions.ts, 47, 3))
let p4 = [[[[10]]]] as const;
>p4 : Symbol(p4, Decl(constAssertions.ts, 48, 3))
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
>x1 : Symbol(x1, Decl(constAssertions.ts, 50, 3))
>x : Symbol(x, Decl(constAssertions.ts, 50, 10))
>y : Symbol(y, Decl(constAssertions.ts, 50, 17))
>z : Symbol(z, Decl(constAssertions.ts, 50, 30))
>a : Symbol(a, Decl(constAssertions.ts, 50, 35))
>b : Symbol(b, Decl(constAssertions.ts, 50, 40))
let q1 = <const> 10;
>q1 : Symbol(q1, Decl(constAssertions.ts, 52, 3))
let q2 = <const> 'abc';
>q2 : Symbol(q2, Decl(constAssertions.ts, 53, 3))
let q3 = <const> true;
>q3 : Symbol(q3, Decl(constAssertions.ts, 54, 3))
let q4 = <const> [1, 2, 3];
>q4 : Symbol(q4, Decl(constAssertions.ts, 55, 3))
let q5 = <const> { x: 10, y: 20 };
>q5 : Symbol(q5, Decl(constAssertions.ts, 56, 3))
>x : Symbol(x, Decl(constAssertions.ts, 56, 18))
>y : Symbol(y, Decl(constAssertions.ts, 56, 25))
declare function id<T>(x: T): T;
>id : Symbol(id, Decl(constAssertions.ts, 56, 34))
>T : Symbol(T, Decl(constAssertions.ts, 58, 20))
>x : Symbol(x, Decl(constAssertions.ts, 58, 23))
>T : Symbol(T, Decl(constAssertions.ts, 58, 20))
>T : Symbol(T, Decl(constAssertions.ts, 58, 20))
let e1 = v1 as const; // Error
>e1 : Symbol(e1, Decl(constAssertions.ts, 60, 3))
>v1 : Symbol(v1, Decl(constAssertions.ts, 0, 3))
let e2 = (true ? 1 : 0) as const; // Error
>e2 : Symbol(e2, Decl(constAssertions.ts, 61, 3))
let e3 = id(1) as const; // Error
>e3 : Symbol(e3, Decl(constAssertions.ts, 62, 3))
>id : Symbol(id, Decl(constAssertions.ts, 56, 34))

View file

@ -0,0 +1,356 @@
=== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts ===
let v1 = 'abc' as const;
>v1 : "abc"
>'abc' as const : "abc"
>'abc' : "abc"
let v2 = `abc` as const;
>v2 : "abc"
>`abc` as const : "abc"
>`abc` : "abc"
let v3 = 10 as const;
>v3 : 10
>10 as const : 10
>10 : 10
let v4 = -10 as const;
>v4 : -10
>-10 as const : -10
>-10 : -10
>10 : 10
let v5 = +10 as const;
>v5 : 10
>+10 as const : 10
>+10 : 10
>10 : 10
let v6 = 10n as const;
>v6 : 10n
>10n as const : 10n
>10n : 10n
let v7 = -10n as const;
>v7 : -10n
>-10n as const : -10n
>-10n : -10n
>10n : 10n
let v8 = true as const;
>v8 : true
>true as const : true
>true : true
let v9 = false as const;
>v9 : false
>false as const : false
>false : false
let c1 = 'abc' as const;
>c1 : "abc"
>'abc' as const : "abc"
>'abc' : "abc"
let c2 = `abc` as const;
>c2 : "abc"
>`abc` as const : "abc"
>`abc` : "abc"
let c3 = 10 as const;
>c3 : 10
>10 as const : 10
>10 : 10
let c4 = -10 as const;
>c4 : -10
>-10 as const : -10
>-10 : -10
>10 : 10
let c5 = +10 as const;
>c5 : 10
>+10 as const : 10
>+10 : 10
>10 : 10
let c6 = 10n as const;
>c6 : 10n
>10n as const : 10n
>10n : 10n
let c7 = -10n as const;
>c7 : -10n
>-10n as const : -10n
>-10n : -10n
>10n : 10n
let c8 = true as const;
>c8 : true
>true as const : true
>true : true
let c9 = false as const;
>c9 : false
>false as const : false
>false : false
let vv1 = v1;
>vv1 : "abc"
>v1 : "abc"
let vc1 = c1;
>vc1 : "abc"
>c1 : "abc"
let a1 = [] as const;
>a1 : readonly []
>[] as const : readonly []
>[] : readonly []
let a2 = [1, 2, 3] as const;
>a2 : readonly [1, 2, 3]
>[1, 2, 3] as const : readonly [1, 2, 3]
>[1, 2, 3] : readonly [1, 2, 3]
>1 : 1
>2 : 2
>3 : 3
let a3 = [10, 'hello', true] as const;
>a3 : readonly [10, "hello", true]
>[10, 'hello', true] as const : readonly [10, "hello", true]
>[10, 'hello', true] : readonly [10, "hello", true]
>10 : 10
>'hello' : "hello"
>true : true
let a4 = [...[1, 2, 3]] as const;
>a4 : readonly (1 | 2 | 3)[]
>[...[1, 2, 3]] as const : readonly (1 | 2 | 3)[]
>[...[1, 2, 3]] : readonly (1 | 2 | 3)[]
>...[1, 2, 3] : 1 | 2 | 3
>[1, 2, 3] : readonly [1, 2, 3]
>1 : 1
>2 : 2
>3 : 3
let a5 = [1, 2, 3];
>a5 : number[]
>[1, 2, 3] : number[]
>1 : 1
>2 : 2
>3 : 3
let a6 = [...a5] as const;
>a6 : readonly number[]
>[...a5] as const : readonly number[]
>[...a5] : readonly number[]
>...a5 : number
>a5 : number[]
let a7 = [...a6];
>a7 : number[]
>[...a6] : number[]
>...a6 : number
>a6 : readonly number[]
let a8 = ['abc', ...a7] as const;
>a8 : readonly ["abc", ...number[]]
>['abc', ...a7] as const : readonly ["abc", ...number[]]
>['abc', ...a7] : readonly ["abc", ...number[]]
>'abc' : "abc"
>...a7 : number
>a7 : number[]
let a9 = [...a8];
>a9 : (number | "abc")[]
>[...a8] : (number | "abc")[]
>...a8 : number | "abc"
>a8 : readonly ["abc", ...number[]]
declare let d: { [x: string]: string };
>d : { [x: string]: string; }
>x : string
let o1 = { x: 10, y: 20 } as const;
>o1 : { readonly x: 10; readonly y: 20; }
>{ x: 10, y: 20 } as const : { readonly x: 10; readonly y: 20; }
>{ x: 10, y: 20 } : { readonly x: 10; readonly y: 20; }
>x : 10
>10 : 10
>y : 20
>20 : 20
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
>o2 : { readonly [x: string]: 1 | 2 | 3 | (() => void) | 4; readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; }
>{ a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const : { readonly [x: string]: 1 | 2 | 3 | (() => void) | 4; readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; }
>{ a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } : { readonly [x: string]: 1 | 2 | 3 | (() => void) | 4; readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; }
>a : 1
>1 : 1
>'b' : 2
>2 : 2
>['c'] : 3
>'c' : "c"
>3 : 3
>d : () => void
>['e' + ''] : 4
>'e' + '' : string
>'e' : "e"
>'' : ""
>4 : 4
let o3 = { ...o1, ...o2 } as const;
>o3 : { readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; readonly x: 10; readonly y: 20; }
>{ ...o1, ...o2 } as const : { readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; readonly x: 10; readonly y: 20; }
>{ ...o1, ...o2 } : { readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; readonly x: 10; readonly y: 20; }
>o1 : { readonly x: 10; readonly y: 20; }
>o2 : { readonly [x: string]: 1 | 2 | 3 | (() => void) | 4; readonly a: 1; readonly 'b': 2; readonly ['c']: 3; readonly d: () => void; }
let o4 = { a: 1, b: 2 };
>o4 : { a: number; b: number; }
>{ a: 1, b: 2 } : { a: number; b: number; }
>a : number
>1 : 1
>b : number
>2 : 2
let o5 = { ...o4 } as const;
>o5 : { readonly a: number; readonly b: number; }
>{ ...o4 } as const : { readonly a: number; readonly b: number; }
>{ ...o4 } : { readonly a: number; readonly b: number; }
>o4 : { a: number; b: number; }
let o6 = { ...o5 };
>o6 : { a: number; b: number; }
>{ ...o5 } : { a: number; b: number; }
>o5 : { readonly a: number; readonly b: number; }
let o7 = { ...d } as const;
>o7 : { readonly [x: string]: string; }
>{ ...d } as const : { readonly [x: string]: string; }
>{ ...d } : { readonly [x: string]: string; }
>d : { [x: string]: string; }
let o8 = { ...o7 };
>o8 : { [x: string]: string; }
>{ ...o7 } : { [x: string]: string; }
>o7 : { readonly [x: string]: string; }
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
>o9 : { readonly x: 10; readonly foo: () => void; }
>{ x: 10, foo() { this.x = 20 } } as const : { readonly x: 10; readonly foo: () => void; }
>{ x: 10, foo() { this.x = 20 } } : { readonly x: 10; readonly foo: () => void; }
>x : 10
>10 : 10
>foo : () => void
>this.x = 20 : 20
>this.x : any
>this : { readonly x: 10; readonly foo: () => void; }
>x : any
>20 : 20
let p1 = (10) as const;
>p1 : 10
>(10) as const : 10
>(10) : 10
>10 : 10
let p2 = ((-10)) as const;
>p2 : -10
>((-10)) as const : -10
>((-10)) : -10
>(-10) : -10
>-10 : -10
>10 : 10
let p3 = ([(10)]) as const;
>p3 : readonly [10]
>([(10)]) as const : readonly [10]
>([(10)]) : readonly [10]
>[(10)] : readonly [10]
>(10) : 10
>10 : 10
let p4 = [[[[10]]]] as const;
>p4 : readonly [readonly [readonly [readonly [10]]]]
>[[[[10]]]] as const : readonly [readonly [readonly [readonly [10]]]]
>[[[[10]]]] : readonly [readonly [readonly [readonly [10]]]]
>[[[10]]] : readonly [readonly [readonly [10]]]
>[[10]] : readonly [readonly [10]]
>[10] : readonly [10]
>10 : 10
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
>x1 : { readonly x: 10; readonly y: readonly [20, 30]; z: { a: { readonly b: 42; }; }; }
>{ x: 10, y: [20, 30], z: { a: { b: 42 } } } as const : { readonly x: 10; readonly y: readonly [20, 30]; readonly z: { readonly a: { readonly b: 42; }; }; }
>{ x: 10, y: [20, 30], z: { a: { b: 42 } } } : { readonly x: 10; readonly y: readonly [20, 30]; readonly z: { readonly a: { readonly b: 42; }; }; }
>x : 10
>10 : 10
>y : readonly [20, 30]
>[20, 30] : readonly [20, 30]
>20 : 20
>30 : 30
>z : { readonly a: { readonly b: 42; }; }
>{ a: { b: 42 } } : { readonly a: { readonly b: 42; }; }
>a : { readonly b: 42; }
>{ b: 42 } : { readonly b: 42; }
>b : 42
>42 : 42
let q1 = <const> 10;
>q1 : 10
><const> 10 : 10
>10 : 10
let q2 = <const> 'abc';
>q2 : "abc"
><const> 'abc' : "abc"
>'abc' : "abc"
let q3 = <const> true;
>q3 : true
><const> true : true
>true : true
let q4 = <const> [1, 2, 3];
>q4 : readonly [1, 2, 3]
><const> [1, 2, 3] : readonly [1, 2, 3]
>[1, 2, 3] : readonly [1, 2, 3]
>1 : 1
>2 : 2
>3 : 3
let q5 = <const> { x: 10, y: 20 };
>q5 : { readonly x: 10; readonly y: 20; }
><const> { x: 10, y: 20 } : { readonly x: 10; readonly y: 20; }
>{ x: 10, y: 20 } : { readonly x: 10; readonly y: 20; }
>x : 10
>10 : 10
>y : 20
>20 : 20
declare function id<T>(x: T): T;
>id : <T>(x: T) => T
>x : T
let e1 = v1 as const; // Error
>e1 : "abc"
>v1 as const : "abc"
>v1 : "abc"
let e2 = (true ? 1 : 0) as const; // Error
>e2 : 0 | 1
>(true ? 1 : 0) as const : 0 | 1
>(true ? 1 : 0) : 0 | 1
>true ? 1 : 0 : 0 | 1
>true : true
>1 : 1
>0 : 0
let e3 = id(1) as const; // Error
>e3 : 1
>id(1) as const : 1
>id(1) : 1
>id : <T>(x: T) => T
>1 : 1

View file

@ -1,5 +1,5 @@
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2503: Cannot find namespace 'module'.
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,19): error TS1005: ';' expected.
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(22,35): error TS1005: ')' expected.
tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(22,39): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
@ -105,7 +105,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS
~~~~~~
!!! error TS2503: Cannot find namespace 'module'.
~~~~~~
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.
!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`.
~
!!! error TS1005: ';' expected.

View file

@ -93,7 +93,34 @@ let xyz: LikeA | LikeB = {
}
};
xyz;
xyz;
// Repro from #29168
interface TestObject {
type?: 'object';
items: {
[k: string]: TestGeneric;
};
}
interface TestString {
type: 'string';
}
type TestGeneric = (TestString | TestObject) & { [k: string]: any; };
const test: TestGeneric = {
items: {
hello: { type: 'string' },
world: {
items: {
nested: { type: 'string' }
}
}
}
};
//// [contextualTypeShouldBeLiteral.js]
"use strict";
@ -134,3 +161,13 @@ var xyz = {
}
};
xyz;
var test = {
items: {
hello: { type: 'string' },
world: {
items: {
nested: { type: 'string' }
}
}
}
};

View file

@ -227,3 +227,59 @@ let xyz: LikeA | LikeB = {
xyz;
>xyz : Symbol(xyz, Decl(contextualTypeShouldBeLiteral.ts, 82, 3))
// Repro from #29168
interface TestObject {
>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4))
type?: 'object';
>type : Symbol(TestObject.type, Decl(contextualTypeShouldBeLiteral.ts, 98, 22))
items: {
>items : Symbol(TestObject.items, Decl(contextualTypeShouldBeLiteral.ts, 99, 18))
[k: string]: TestGeneric;
>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 101, 5))
>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1))
};
}
interface TestString {
>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1))
type: 'string';
>type : Symbol(TestString.type, Decl(contextualTypeShouldBeLiteral.ts, 105, 22))
}
type TestGeneric = (TestString | TestObject) & { [k: string]: any; };
>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1))
>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1))
>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4))
>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 109, 50))
const test: TestGeneric = {
>test : Symbol(test, Decl(contextualTypeShouldBeLiteral.ts, 111, 5))
>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1))
items: {
>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 111, 27))
hello: { type: 'string' },
>hello : Symbol(hello, Decl(contextualTypeShouldBeLiteral.ts, 112, 10))
>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 113, 12))
world: {
>world : Symbol(world, Decl(contextualTypeShouldBeLiteral.ts, 113, 30))
items: {
>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 114, 12))
nested: { type: 'string' }
>nested : Symbol(nested, Decl(contextualTypeShouldBeLiteral.ts, 115, 14))
>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 116, 17))
}
}
}
};

View file

@ -222,3 +222,59 @@ let xyz: LikeA | LikeB = {
xyz;
>xyz : LikeA
// Repro from #29168
interface TestObject {
type?: 'object';
>type : "object" | undefined
items: {
>items : { [k: string]: TestGeneric; }
[k: string]: TestGeneric;
>k : string
};
}
interface TestString {
type: 'string';
>type : "string"
}
type TestGeneric = (TestString | TestObject) & { [k: string]: any; };
>TestGeneric : TestGeneric
>k : string
const test: TestGeneric = {
>test : TestGeneric
>{ items: { hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } }} : { items: { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; }; }
items: {
>items : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; }
>{ hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } } : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; }
hello: { type: 'string' },
>hello : { type: "string"; }
>{ type: 'string' } : { type: "string"; }
>type : "string"
>'string' : "string"
world: {
>world : { items: { nested: { type: "string"; }; }; }
>{ items: { nested: { type: 'string' } } } : { items: { nested: { type: "string"; }; }; }
items: {
>items : { nested: { type: "string"; }; }
>{ nested: { type: 'string' } } : { nested: { type: "string"; }; }
nested: { type: 'string' }
>nested : { type: "string"; }
>{ type: 'string' } : { type: "string"; }
>type : "string"
>'string' : "string"
}
}
}
};

View file

@ -0,0 +1,42 @@
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(8,29): error TS7031: Binding element 'foo' implicitly has an 'any' type.
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(14,27): error TS7006: Parameter 'foo' implicitly has an 'any' type.
tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(27,42): error TS7031: Binding element 'foo' implicitly has an 'any' type.
==== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts (3 errors) ====
declare function id1<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
declare function id5<T extends (x?: number) => any>(input: T): T;
const f10 = function ({ foo = 42 }) { return foo };
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
~~~
!!! error TS7031: Binding element 'foo' implicitly has an 'any' type.
const f12 = id2(function ({ foo = 42 }) { return foo });
const f13 = id3(function ({ foo = 42 }) { return foo });
const f14 = id4(function ({ foo = 42 }) { return foo });
const f20 = function (foo = 42) { return foo };
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
~~~~~~~~
!!! error TS7006: Parameter 'foo' implicitly has an 'any' type.
const f22 = id2(function (foo = 42) { return foo });
const f25 = id5(function (foo = 42) { return foo });
// Repro from #28816
function id<T>(input: T): T { return input }
function getFoo ({ foo = 42 }) {
return foo;
}
const newGetFoo = id(getFoo);
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
~~~
!!! error TS7031: Binding element 'foo' implicitly has an 'any' type.
return foo;
});

View file

@ -0,0 +1,114 @@
//// [contextuallyTypedParametersWithInitializers.ts]
declare function id1<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
declare function id5<T extends (x?: number) => any>(input: T): T;
const f10 = function ({ foo = 42 }) { return foo };
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
const f12 = id2(function ({ foo = 42 }) { return foo });
const f13 = id3(function ({ foo = 42 }) { return foo });
const f14 = id4(function ({ foo = 42 }) { return foo });
const f20 = function (foo = 42) { return foo };
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
const f22 = id2(function (foo = 42) { return foo });
const f25 = id5(function (foo = 42) { return foo });
// Repro from #28816
function id<T>(input: T): T { return input }
function getFoo ({ foo = 42 }) {
return foo;
}
const newGetFoo = id(getFoo);
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
return foo;
});
//// [contextuallyTypedParametersWithInitializers.js]
"use strict";
var f10 = function (_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
};
var f11 = id1(function (_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
}); // Implicit any error
var f12 = id2(function (_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
});
var f13 = id3(function (_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
});
var f14 = id4(function (_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
});
var f20 = function (foo) {
if (foo === void 0) { foo = 42; }
return foo;
};
var f21 = id1(function (foo) {
if (foo === void 0) { foo = 42; }
return foo;
}); // Implicit any error
var f22 = id2(function (foo) {
if (foo === void 0) { foo = 42; }
return foo;
});
var f25 = id5(function (foo) {
if (foo === void 0) { foo = 42; }
return foo;
});
// Repro from #28816
function id(input) { return input; }
function getFoo(_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
}
var newGetFoo = id(getFoo);
var newGetFoo2 = id(function getFoo(_a) {
var _b = _a.foo, foo = _b === void 0 ? 42 : _b;
return foo;
});
//// [contextuallyTypedParametersWithInitializers.d.ts]
declare function id1<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: {
foo: any;
}) => any>(input: T): T;
declare function id4<T extends (x: {
foo?: number;
}) => any>(input: T): T;
declare function id5<T extends (x?: number) => any>(input: T): T;
declare const f10: ({ foo }: {
foo?: number | undefined;
}) => number;
declare const f11: ({ foo }: any) => any;
declare const f12: ({ foo }: any) => any;
declare const f13: ({ foo }: {
foo: any;
}) => any;
declare const f14: ({ foo }: {
foo?: number | undefined;
}) => number;
declare const f20: (foo?: number) => number;
declare const f21: (foo?: any) => any;
declare const f22: (foo?: any) => any;
declare const f25: (foo?: number | undefined) => number;
declare function id<T>(input: T): T;
declare function getFoo({ foo }: {
foo?: number | undefined;
}): number;
declare const newGetFoo: typeof getFoo;
declare const newGetFoo2: ({ foo }: any) => any;

View file

@ -0,0 +1,128 @@
=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts ===
declare function id1<T>(input: T): T;
>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 24))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21))
declare function id2<T extends (x: any) => any>(input: T): T;
>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21))
>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 32))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 48))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21))
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
>id3 : Symbol(id3, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 61))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21))
>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 32))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 36))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 57))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21))
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
>id4 : Symbol(id4, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 70))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21))
>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 32))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 36))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 61))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21))
declare function id5<T extends (x?: number) => any>(input: T): T;
>id5 : Symbol(id5, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 74))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21))
>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 32))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 52))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21))
const f10 = function ({ foo = 42 }) { return foo };
>f10 : Symbol(f10, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 5))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 23))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 23))
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
>f11 : Symbol(f11, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 5))
>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 27))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 27))
const f12 = id2(function ({ foo = 42 }) { return foo });
>f12 : Symbol(f12, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 5))
>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 27))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 27))
const f13 = id3(function ({ foo = 42 }) { return foo });
>f13 : Symbol(f13, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 5))
>id3 : Symbol(id3, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 61))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 27))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 27))
const f14 = id4(function ({ foo = 42 }) { return foo });
>f14 : Symbol(f14, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 5))
>id4 : Symbol(id4, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 70))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 27))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 27))
const f20 = function (foo = 42) { return foo };
>f20 : Symbol(f20, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 5))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 22))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 22))
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
>f21 : Symbol(f21, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 5))
>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 26))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 26))
const f22 = id2(function (foo = 42) { return foo });
>f22 : Symbol(f22, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 5))
>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 26))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 26))
const f25 = id5(function (foo = 42) { return foo });
>f25 : Symbol(f25, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 5))
>id5 : Symbol(id5, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 74))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 26))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 26))
// Repro from #28816
function id<T>(input: T): T { return input }
>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 15))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12))
>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12))
>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 15))
function getFoo ({ foo = 42 }) {
>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 44))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 21, 18))
return foo;
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 21, 18))
}
const newGetFoo = id(getFoo);
>newGetFoo : Symbol(newGetFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 25, 5))
>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52))
>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 44))
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
>newGetFoo2 : Symbol(newGetFoo2, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 5))
>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52))
>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 22))
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 40))
return foo;
>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 40))
});

View file

@ -0,0 +1,140 @@
=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts ===
declare function id1<T>(input: T): T;
>id1 : <T>(input: T) => T
>input : T
declare function id2<T extends (x: any) => any>(input: T): T;
>id2 : <T extends (x: any) => any>(input: T) => T
>x : any
>input : T
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
>id3 : <T extends (x: { foo: any; }) => any>(input: T) => T
>x : { foo: any; }
>foo : any
>input : T
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
>id4 : <T extends (x: { foo?: number | undefined; }) => any>(input: T) => T
>x : { foo?: number | undefined; }
>foo : number | undefined
>input : T
declare function id5<T extends (x?: number) => any>(input: T): T;
>id5 : <T extends (x?: number | undefined) => any>(input: T) => T
>x : number | undefined
>input : T
const f10 = function ({ foo = 42 }) { return foo };
>f10 : ({ foo }: { foo?: number | undefined; }) => number
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
>foo : number
const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error
>f11 : ({ foo }: any) => any
>id1(function ({ foo = 42 }) { return foo }) : ({ foo }: any) => any
>id1 : <T>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo }: any) => any
>foo : any
>42 : 42
>foo : any
const f12 = id2(function ({ foo = 42 }) { return foo });
>f12 : ({ foo }: any) => any
>id2(function ({ foo = 42 }) { return foo }) : ({ foo }: any) => any
>id2 : <T extends (x: any) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo }: any) => any
>foo : any
>42 : 42
>foo : any
const f13 = id3(function ({ foo = 42 }) { return foo });
>f13 : ({ foo }: { foo: any; }) => any
>id3(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo: any; }) => any
>id3 : <T extends (x: { foo: any; }) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo: any; }) => any
>foo : any
>42 : 42
>foo : any
const f14 = id4(function ({ foo = 42 }) { return foo });
>f14 : ({ foo }: { foo?: number | undefined; }) => number
>id4(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number | undefined; }) => number
>id4 : <T extends (x: { foo?: number | undefined; }) => any>(input: T) => T
>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
>foo : number
const f20 = function (foo = 42) { return foo };
>f20 : (foo?: number) => number
>function (foo = 42) { return foo } : (foo?: number) => number
>foo : number
>42 : 42
>foo : number
const f21 = id1(function (foo = 42) { return foo }); // Implicit any error
>f21 : (foo?: any) => any
>id1(function (foo = 42) { return foo }) : (foo?: any) => any
>id1 : <T>(input: T) => T
>function (foo = 42) { return foo } : (foo?: any) => any
>foo : any
>42 : 42
>foo : any
const f22 = id2(function (foo = 42) { return foo });
>f22 : (foo?: any) => any
>id2(function (foo = 42) { return foo }) : (foo?: any) => any
>id2 : <T extends (x: any) => any>(input: T) => T
>function (foo = 42) { return foo } : (foo?: any) => any
>foo : any
>42 : 42
>foo : any
const f25 = id5(function (foo = 42) { return foo });
>f25 : (foo?: number | undefined) => number
>id5(function (foo = 42) { return foo }) : (foo?: number | undefined) => number
>id5 : <T extends (x?: number | undefined) => any>(input: T) => T
>function (foo = 42) { return foo } : (foo?: number | undefined) => number
>foo : number | undefined
>42 : 42
>foo : number
// Repro from #28816
function id<T>(input: T): T { return input }
>id : <T>(input: T) => T
>input : T
>input : T
function getFoo ({ foo = 42 }) {
>getFoo : ({ foo }: { foo?: number | undefined; }) => number
>foo : number
>42 : 42
return foo;
>foo : number
}
const newGetFoo = id(getFoo);
>newGetFoo : ({ foo }: { foo?: number | undefined; }) => number
>id(getFoo) : ({ foo }: { foo?: number | undefined; }) => number
>id : <T>(input: T) => T
>getFoo : ({ foo }: { foo?: number | undefined; }) => number
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
>newGetFoo2 : ({ foo }: any) => any
>id(function getFoo ({ foo = 42 }) { return foo;}) : ({ foo }: any) => any
>id : <T>(input: T) => T
>function getFoo ({ foo = 42 }) { return foo;} : ({ foo }: any) => any
>getFoo : ({ foo }: any) => any
>foo : any
>42 : 42
return foo;
>foo : any
});

View file

@ -0,0 +1,36 @@
tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts(23,24): error TS2525: Initializer provides no value for this binding element and the binding element has no default value.
==== tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts (1 errors) ====
// https://github.com/Microsoft/TypeScript/issues/29006
export interface A { type: 'a' }
export interface B { type: 'b' }
export type AB = A | B
const itemId = 'some-id'
// --- test on first level ---
const items: { [id: string]: AB } = {}
const { [itemId]: itemOk1 } = items
typeof itemOk1 // pass
// --- test on second level ---
interface ObjWithItems {
items: {[s: string]: AB}
}
const objWithItems: ObjWithItems = { items: {}}
const itemOk2 = objWithItems.items[itemId]
typeof itemOk2 // pass
const {
items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/
~~~~~~~~~~~~~~~
!!! error TS2525: Initializer provides no value for this binding element and the binding element has no default value.
} = objWithItems
// in order to re-produce the error, uncomment next line:
typeof itemWithTSError // :(
// will result in:
// Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined

View file

@ -0,0 +1,48 @@
//// [crashInGetTextOfComputedPropertyName.ts]
// https://github.com/Microsoft/TypeScript/issues/29006
export interface A { type: 'a' }
export interface B { type: 'b' }
export type AB = A | B
const itemId = 'some-id'
// --- test on first level ---
const items: { [id: string]: AB } = {}
const { [itemId]: itemOk1 } = items
typeof itemOk1 // pass
// --- test on second level ---
interface ObjWithItems {
items: {[s: string]: AB}
}
const objWithItems: ObjWithItems = { items: {}}
const itemOk2 = objWithItems.items[itemId]
typeof itemOk2 // pass
const {
items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/
} = objWithItems
// in order to re-produce the error, uncomment next line:
typeof itemWithTSError // :(
// will result in:
// Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined
//// [crashInGetTextOfComputedPropertyName.js]
"use strict";
exports.__esModule = true;
var itemId = 'some-id';
// --- test on first level ---
var items = {};
var _a = itemId, itemOk1 = items[_a];
typeof itemOk1; // pass
var objWithItems = { items: {} };
var itemOk2 = objWithItems.items[itemId];
typeof itemOk2; // pass
var _b = objWithItems.items /*happens when default value is provided*/, _c = itemId, itemWithTSError = (_b === void 0 ? {} /*happens when default value is provided*/ : _b)[_c];
// in order to re-produce the error, uncomment next line:
typeof itemWithTSError; // :(
// will result in:
// Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined

View file

@ -0,0 +1,71 @@
=== tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts ===
// https://github.com/Microsoft/TypeScript/issues/29006
export interface A { type: 'a' }
>A : Symbol(A, Decl(crashInGetTextOfComputedPropertyName.ts, 0, 0))
>type : Symbol(A.type, Decl(crashInGetTextOfComputedPropertyName.ts, 1, 20))
export interface B { type: 'b' }
>B : Symbol(B, Decl(crashInGetTextOfComputedPropertyName.ts, 1, 32))
>type : Symbol(B.type, Decl(crashInGetTextOfComputedPropertyName.ts, 2, 20))
export type AB = A | B
>AB : Symbol(AB, Decl(crashInGetTextOfComputedPropertyName.ts, 2, 32))
>A : Symbol(A, Decl(crashInGetTextOfComputedPropertyName.ts, 0, 0))
>B : Symbol(B, Decl(crashInGetTextOfComputedPropertyName.ts, 1, 32))
const itemId = 'some-id'
>itemId : Symbol(itemId, Decl(crashInGetTextOfComputedPropertyName.ts, 5, 5))
// --- test on first level ---
const items: { [id: string]: AB } = {}
>items : Symbol(items, Decl(crashInGetTextOfComputedPropertyName.ts, 8, 5))
>id : Symbol(id, Decl(crashInGetTextOfComputedPropertyName.ts, 8, 16))
>AB : Symbol(AB, Decl(crashInGetTextOfComputedPropertyName.ts, 2, 32))
const { [itemId]: itemOk1 } = items
>itemId : Symbol(itemId, Decl(crashInGetTextOfComputedPropertyName.ts, 5, 5))
>itemOk1 : Symbol(itemOk1, Decl(crashInGetTextOfComputedPropertyName.ts, 9, 7))
>items : Symbol(items, Decl(crashInGetTextOfComputedPropertyName.ts, 8, 5))
typeof itemOk1 // pass
>itemOk1 : Symbol(itemOk1, Decl(crashInGetTextOfComputedPropertyName.ts, 9, 7))
// --- test on second level ---
interface ObjWithItems {
>ObjWithItems : Symbol(ObjWithItems, Decl(crashInGetTextOfComputedPropertyName.ts, 10, 14))
items: {[s: string]: AB}
>items : Symbol(ObjWithItems.items, Decl(crashInGetTextOfComputedPropertyName.ts, 13, 24))
>s : Symbol(s, Decl(crashInGetTextOfComputedPropertyName.ts, 14, 13))
>AB : Symbol(AB, Decl(crashInGetTextOfComputedPropertyName.ts, 2, 32))
}
const objWithItems: ObjWithItems = { items: {}}
>objWithItems : Symbol(objWithItems, Decl(crashInGetTextOfComputedPropertyName.ts, 16, 5))
>ObjWithItems : Symbol(ObjWithItems, Decl(crashInGetTextOfComputedPropertyName.ts, 10, 14))
>items : Symbol(items, Decl(crashInGetTextOfComputedPropertyName.ts, 16, 36))
const itemOk2 = objWithItems.items[itemId]
>itemOk2 : Symbol(itemOk2, Decl(crashInGetTextOfComputedPropertyName.ts, 18, 5))
>objWithItems.items : Symbol(ObjWithItems.items, Decl(crashInGetTextOfComputedPropertyName.ts, 13, 24))
>objWithItems : Symbol(objWithItems, Decl(crashInGetTextOfComputedPropertyName.ts, 16, 5))
>items : Symbol(ObjWithItems.items, Decl(crashInGetTextOfComputedPropertyName.ts, 13, 24))
>itemId : Symbol(itemId, Decl(crashInGetTextOfComputedPropertyName.ts, 5, 5))
typeof itemOk2 // pass
>itemOk2 : Symbol(itemOk2, Decl(crashInGetTextOfComputedPropertyName.ts, 18, 5))
const {
items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/
>items : Symbol(ObjWithItems.items, Decl(crashInGetTextOfComputedPropertyName.ts, 13, 24))
>itemId : Symbol(itemId, Decl(crashInGetTextOfComputedPropertyName.ts, 5, 5))
>itemWithTSError : Symbol(itemWithTSError, Decl(crashInGetTextOfComputedPropertyName.ts, 22, 12))
} = objWithItems
>objWithItems : Symbol(objWithItems, Decl(crashInGetTextOfComputedPropertyName.ts, 16, 5))
// in order to re-produce the error, uncomment next line:
typeof itemWithTSError // :(
>itemWithTSError : Symbol(itemWithTSError, Decl(crashInGetTextOfComputedPropertyName.ts, 22, 12))
// will result in:
// Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined

View file

@ -0,0 +1,71 @@
=== tests/cases/compiler/crashInGetTextOfComputedPropertyName.ts ===
// https://github.com/Microsoft/TypeScript/issues/29006
export interface A { type: 'a' }
>type : "a"
export interface B { type: 'b' }
>type : "b"
export type AB = A | B
>AB : AB
const itemId = 'some-id'
>itemId : "some-id"
>'some-id' : "some-id"
// --- test on first level ---
const items: { [id: string]: AB } = {}
>items : { [id: string]: AB; }
>id : string
>{} : {}
const { [itemId]: itemOk1 } = items
>itemId : "some-id"
>itemOk1 : AB
>items : { [id: string]: AB; }
typeof itemOk1 // pass
>typeof itemOk1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>itemOk1 : AB
// --- test on second level ---
interface ObjWithItems {
items: {[s: string]: AB}
>items : { [s: string]: AB; }
>s : string
}
const objWithItems: ObjWithItems = { items: {}}
>objWithItems : ObjWithItems
>{ items: {}} : { items: {}; }
>items : {}
>{} : {}
const itemOk2 = objWithItems.items[itemId]
>itemOk2 : AB
>objWithItems.items[itemId] : AB
>objWithItems.items : { [s: string]: AB; }
>objWithItems : ObjWithItems
>items : { [s: string]: AB; }
>itemId : "some-id"
typeof itemOk2 // pass
>typeof itemOk2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>itemOk2 : AB
const {
items: { [itemId]: itemWithTSError } = {} /*happens when default value is provided*/
>items : any
>itemId : "some-id"
>itemWithTSError : any
>{} : { some-id: any; }
} = objWithItems
>objWithItems : ObjWithItems
// in order to re-produce the error, uncomment next line:
typeof itemWithTSError // :(
>typeof itemWithTSError : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>itemWithTSError : any
// will result in:
// Error from compilation: TypeError: Cannot read property 'charCodeAt' of undefined TypeError: Cannot read property 'charCodeAt' of undefined

View file

@ -1,9 +1,10 @@
tests/cases/compiler/destructureComputedProperty.ts(7,7): error TS2341: Property 'p' is private and only accessible within class 'C'.
tests/cases/compiler/destructureComputedProperty.ts(8,7): error TS2341: Property 'p' is private and only accessible within class 'C'.
tests/cases/compiler/destructureComputedProperty.ts(9,7): error TS2341: Property 'p' is private and only accessible within class 'C'.
tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Property 'p' is private and only accessible within class 'C'.
==== tests/cases/compiler/destructureComputedProperty.ts (3 errors) ====
==== tests/cases/compiler/destructureComputedProperty.ts (4 errors) ====
declare const ab: { n: number } | { n: string };
const nameN = "n";
const { [nameN]: n } = ab;
@ -17,6 +18,8 @@ tests/cases/compiler/destructureComputedProperty.ts(10,7): error TS2341: Propert
~~~~~~~~~~~~~
!!! error TS2341: Property 'p' is private and only accessible within class 'C'.
const { [nameP]: p2 } = new C();
~~~~~~~~~~~~~~~
!!! error TS2341: Property 'p' is private and only accessible within class 'C'.
const { p: p3 } = new C();
~~~~~~~~~
!!! error TS2341: Property 'p' is private and only accessible within class 'C'.

View file

@ -1,7 +1,8 @@
tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,8): error TS2339: Property 'prop2' does not exist on type '{ prop: string; }'.
tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,21): error TS2525: Initializer provides no value for this binding element and the binding element has no default value.
tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,37): error TS2353: Object literal may only specify known properties, and 'prop' does not exist in type '{ prop2: any; }'.
==== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts (1 errors) ====
==== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts (2 errors) ====
let { [Symbol.iterator]: destructured } = [];
void destructured;
@ -13,6 +14,8 @@ tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,8): error TS
const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };
~~~~~~~~~~
!!! error TS2339: Property 'prop2' does not exist on type '{ prop: string; }'.
~~~~~~~~~
!!! error TS2525: Initializer provides no value for this binding element and the binding element has no default value.
~~~~
!!! error TS2353: Object literal may only specify known properties, and 'prop' does not exist in type '{ prop2: any; }'.

View file

@ -32,7 +32,7 @@ const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };
>notPresent : "prop2"
>computed2 : any
>{ prop: "b" } : { prop: string; }
>{ prop: "b" } : { prop: string; prop2: any; }
>prop : string
>"b" : "b"

View file

@ -1,8 +1,10 @@
tests/cases/compiler/destructuringAssignment_private.ts(6,10): error TS2341: Property 'x' is private and only accessible within class 'C'.
tests/cases/compiler/destructuringAssignment_private.ts(7,4): error TS2341: Property 'o' is private and only accessible within class 'C'.
tests/cases/compiler/destructuringAssignment_private.ts(10,10): error TS2341: Property 'x' is private and only accessible within class 'C'.
tests/cases/compiler/destructuringAssignment_private.ts(13,4): error TS2341: Property 'o' is private and only accessible within class 'C'.
==== tests/cases/compiler/destructuringAssignment_private.ts (2 errors) ====
==== tests/cases/compiler/destructuringAssignment_private.ts (4 errors) ====
class C {
private x = 0;
private o = [{ a: 1 }];
@ -14,4 +16,14 @@ tests/cases/compiler/destructuringAssignment_private.ts(7,4): error TS2341: Prop
({ o: [{ a: x }]} = new C());
~
!!! error TS2341: Property 'o' is private and only accessible within class 'C'.
const nameX = "x";
([{ a: { [nameX]: x } }] = [{ a: new C() }]);
~~~~~~~
!!! error TS2341: Property 'x' is private and only accessible within class 'C'.
const nameO = "o";
({ [nameO]: [{ a: x }]} = new C());
~~~~~~~
!!! error TS2341: Property 'o' is private and only accessible within class 'C'.

Some files were not shown because too many files have changed in this diff Show more