const ASSETS = "$asset$";
function main(configText, rootNames) {
println(`>>> ts version ${ts.version}`);
println(`>>> rootNames ${rootNames}`);
const host = new Host();
assert(rootNames.length > 0);
let { options, diagnostics } = configure(configText);
handleDiagnostics(host, diagnostics);
println(`>>> TS config: ${JSON.stringify(options)}`);
const program = ts.createProgram(rootNames, options, host);
diagnostics = ts.getPreEmitDiagnostics(program).filter(({ code }) => {
if (code === 2691) return false;
if (code === 5009) return false;
return true;
});
handleDiagnostics(host, diagnostics);
const emitResult = program.emit();
handleDiagnostics(host, emitResult.diagnostics);
dispatch("setEmitResult", emitResult);
}
function println(...s) {
Deno.core.print(s.join(" ") + "\n");
}
function unreachable() {
throw Error("unreachable");
}
function assert(cond) {
if (!cond) {
throw Error("assert");
}
}
function decodeAscii(ui8) {
let out = "";
for (let i = 0; i < ui8.length; i++) {
out += String.fromCharCode(ui8[i]);
}
return out;
}
function encode(str) {
const charCodes = str.split("").map(c => c.charCodeAt(0));
const ui8 = new Uint8Array(charCodes);
return ui8;
}
const ops = {
readFile: 49,
exit: 50,
writeFile: 51,
resolveModuleNames: 52,
setEmitResult: 53
};
class Host {
fileExists(fileName) {
println(`fileExists ${fileName}`);
return true;
}
readFile() {
unreachable();
}
useCaseSensitiveFileNames() {
return false;
}
getDefaultLibFileName(options) {
return "lib.deno_core.d.ts";
}
getDefaultLibLocation() {
return ASSETS;
}
getCurrentDirectory() {
return ".";
}
getCanonicalFileName(fileName) {
unreachable();
}
getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) {
assert(!shouldCreateNewSourceFile);
if (fileName.startsWith("$typeRoots$")) {
assert(fileName.startsWith("$typeRoots$/"));
assert(fileName.endsWith("/index.d.ts"));
fileName = fileName
.replace("$typeRoots$/", "")
.replace("/index.d.ts", "");
}
const { sourceCode, moduleName } = dispatch("readFile", {
fileName,
languageVersion,
shouldCreateNewSourceFile
});
let sourceFile = ts.createSourceFile(fileName, sourceCode, languageVersion);
sourceFile.moduleName = moduleName;
return sourceFile;
}
writeFile(
fileName,
data,
writeByteOrderMark,
onError = null,
sourceFiles = null
) {
const moduleName = sourceFiles[sourceFiles.length - 1].moduleName;
return dispatch("writeFile", { fileName, moduleName, data });
}
getSourceFileByPath(
fileName,
path,
languageVersion,
onError,
shouldCreateNewSourceFile
) {
unreachable();
}
getCancellationToken() {
unreachable();
}
getCanonicalFileName(fileName) {
return fileName;
}
getNewLine() {
return "\n";
}
readDirectory() {
unreachable();
}
resolveModuleNames(moduleNames, containingFile) {
const resolvedNames = dispatch("resolveModuleNames", {
moduleNames,
containingFile
});
const r = resolvedNames.map(resolvedFileName => {
const extension = getExtension(resolvedFileName);
return { resolvedFileName, extension };
});
return r;
}
getEnvironmentVariable() {
unreachable();
}
createHash() {
unreachable();
}
getParsedCommandLine() {
unreachable();
}
}
function configure(configurationText) {
const { config, error } = ts.parseConfigFileTextToJson(
"tsconfig.json",
configurationText
);
if (error) {
return { diagnostics: [error] };
}
const { options, errors } = ts.convertCompilerOptionsFromJson(
config.compilerOptions,
""
);
return {
options,
diagnostics: errors.length ? errors : undefined
};
}
function dispatch(opName, obj) {
const s = JSON.stringify(obj);
const msg = encode(s);
const resUi8 = Deno.core.dispatch(ops[opName], msg);
const resStr = decodeAscii(resUi8);
const res = JSON.parse(resStr);
if (!res["ok"]) {
throw Error(`${opName} failed ${res["err"]}. Args: ${JSON.stringify(obj)}`);
}
return res["ok"];
}
function exit(code) {
dispatch("exit", { code });
unreachable();
}
const MAX_ERRORS = 5;
function handleDiagnostics(host, diagnostics) {
if (diagnostics && diagnostics.length) {
let rest = 0;
if (diagnostics.length > MAX_ERRORS) {
rest = diagnostics.length - MAX_ERRORS;
diagnostics = diagnostics.slice(0, MAX_ERRORS);
}
const msg = ts.formatDiagnosticsWithColorAndContext(diagnostics, host);
println(msg);
if (rest) {
println(`And ${rest} other errors.`);
}
exit(1);
}
}
function getExtension(fileName) {
println("getExtension " + fileName);
if (fileName.endsWith(".d.ts")) {
return ts.Extension.Dts;
} else if (fileName.endsWith(".ts")) {
return ts.Extension.Ts;
} else if (fileName.endsWith(".js")) {
return ts.Extension.Js;
} else {
throw TypeError("Cannot resolve extension.");
}
}