UNPKG

11 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13var __values = (this && this.__values) || function (o) {
14 var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
15 if (m) return m.call(o);
16 return {
17 next: function () {
18 if (o && i >= o.length) o = void 0;
19 return { value: o && o[i++], done: !o };
20 }
21 };
22};
23var __read = (this && this.__read) || function (o, n) {
24 var m = typeof Symbol === "function" && o[Symbol.iterator];
25 if (!m) return o;
26 var i = m.call(o), r, ar = [], e;
27 try {
28 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
29 }
30 catch (error) { e = { error: error }; }
31 finally {
32 try {
33 if (r && !r.done && (m = i["return"])) m.call(i);
34 }
35 finally { if (e) throw e.error; }
36 }
37 return ar;
38};
39var __importDefault = (this && this.__importDefault) || function (mod) {
40 return (mod && mod.__esModule) ? mod : { "default": mod };
41};
42Object.defineProperty(exports, "__esModule", { value: true });
43var bs_logger_1 = require("bs-logger");
44var buffer_from_1 = __importDefault(require("buffer-from"));
45var stableStringify = require("fast-json-stable-stringify");
46var fs_1 = require("fs");
47var mkdirp = require("mkdirp");
48var path_1 = require("path");
49var messages_1 = require("./util/messages");
50var sha1_1 = require("./util/sha1");
51var hasOwn = Object.prototype.hasOwnProperty;
52function createCompiler(configs) {
53 var e_1, _a, _b, _c;
54 var logger = configs.logger.child({ namespace: 'ts-compiler' });
55 logger.debug('creating typescript compiler', configs.tsJest.isolatedModules ? '(isolated modules)' : '(language service)');
56 var cachedir = configs.tsCacheDir;
57 var memoryCache = {
58 contents: Object.create(null),
59 versions: Object.create(null),
60 outputs: Object.create(null),
61 };
62 var ts = configs.compilerModule;
63 var cwd = configs.cwd;
64 var extensions = ['.ts', '.tsx'];
65 var _d = configs.typescript, compilerOptions = _d.options, fileNames = _d.fileNames;
66 if (compilerOptions.allowJs) {
67 extensions.push('.js');
68 extensions.push('.jsx');
69 }
70 try {
71 for (var fileNames_1 = __values(fileNames), fileNames_1_1 = fileNames_1.next(); !fileNames_1_1.done; fileNames_1_1 = fileNames_1.next()) {
72 var path = fileNames_1_1.value;
73 memoryCache.versions[path] = 1;
74 }
75 }
76 catch (e_1_1) { e_1 = { error: e_1_1 }; }
77 finally {
78 try {
79 if (fileNames_1_1 && !fileNames_1_1.done && (_a = fileNames_1.return)) _a.call(fileNames_1);
80 }
81 finally { if (e_1) throw e_1.error; }
82 }
83 var getExtension = compilerOptions.jsx === ts.JsxEmit.Preserve
84 ? function (path) { return (/\.[tj]sx$/.test(path) ? '.jsx' : '.js'); }
85 : function (_) { return '.js'; };
86 var transformers = configs.tsCustomTransformers;
87 var getOutput = function (code, fileName) {
88 logger.debug({ fileName: fileName }, 'getOutput(): compiling as isolated module');
89 var result = ts.transpileModule(code, {
90 fileName: fileName,
91 transformers: transformers,
92 compilerOptions: compilerOptions,
93 reportDiagnostics: configs.shouldReportDiagnostic(fileName),
94 });
95 if (result.diagnostics)
96 configs.raiseDiagnostics(result.diagnostics, fileName, logger);
97 return [result.outputText, result.sourceMapText];
98 };
99 var getTypeInfo = function (_code, _fileName, _position) {
100 throw new TypeError(messages_1.Errors.TypesUnavailableWithoutTypeCheck);
101 };
102 if (!configs.tsJest.isolatedModules) {
103 var updateMemoryCache_1 = function (code, fileName) {
104 logger.debug({ fileName: fileName }, "updateMemoryCache()");
105 if (memoryCache.contents[fileName] !== code) {
106 memoryCache.contents[fileName] = code;
107 memoryCache.versions[fileName] = (memoryCache.versions[fileName] || 0) + 1;
108 }
109 };
110 var serviceHostDebugCtx = (_b = {},
111 _b[bs_logger_1.LogContexts.logLevel] = bs_logger_1.LogLevels.debug,
112 _b.namespace = 'ts:serviceHost',
113 _b.call = null,
114 _b);
115 var serviceHostTraceCtx = __assign({}, serviceHostDebugCtx, (_c = {}, _c[bs_logger_1.LogContexts.logLevel] = bs_logger_1.LogLevels.trace, _c));
116 var serviceHost = {
117 getScriptFileNames: function () { return Object.keys(memoryCache.versions); },
118 getScriptVersion: function (fileName) {
119 var version = memoryCache.versions[fileName];
120 return version === undefined ? undefined : String(version);
121 },
122 getScriptSnapshot: function (fileName) {
123 var hit = hasOwn.call(memoryCache.contents, fileName);
124 logger.trace({ fileName: fileName, cacheHit: hit }, "getScriptSnapshot():", 'cache', hit ? 'hit' : 'miss');
125 if (!hit) {
126 memoryCache.contents[fileName] = ts.sys.readFile(fileName);
127 }
128 var contents = memoryCache.contents[fileName];
129 if (contents === undefined) {
130 return;
131 }
132 return ts.ScriptSnapshot.fromString(contents);
133 },
134 fileExists: ts.sys.fileExists,
135 readFile: logger.wrap(serviceHostTraceCtx, 'readFile', ts.sys.readFile),
136 readDirectory: ts.sys.readDirectory,
137 getDirectories: ts.sys.getDirectories,
138 directoryExists: ts.sys.directoryExists,
139 getNewLine: function () { return '\n'; },
140 getCurrentDirectory: function () { return cwd; },
141 getCompilationSettings: function () { return compilerOptions; },
142 getDefaultLibFileName: function () { return ts.getDefaultLibFilePath(compilerOptions); },
143 getCustomTransformers: function () { return transformers; },
144 };
145 logger.debug('creating language service');
146 var service_1 = ts.createLanguageService(serviceHost);
147 getOutput = function (code, fileName) {
148 logger.debug({ fileName: fileName }, 'getOutput(): compiling using language service');
149 updateMemoryCache_1(code, fileName);
150 var output = service_1.getEmitOutput(fileName);
151 if (configs.shouldReportDiagnostic(fileName)) {
152 logger.debug({ fileName: fileName }, 'getOutput(): computing diagnostics');
153 var diagnostics = service_1
154 .getCompilerOptionsDiagnostics()
155 .concat(service_1.getSyntacticDiagnostics(fileName))
156 .concat(service_1.getSemanticDiagnostics(fileName));
157 configs.raiseDiagnostics(diagnostics, fileName, logger);
158 }
159 if (output.emitSkipped) {
160 throw new TypeError(path_1.relative(cwd, fileName) + ": Emit skipped");
161 }
162 if (output.outputFiles.length === 0) {
163 throw new TypeError(messages_1.interpolate(messages_1.Errors.UnableToRequireDefinitionFile, {
164 file: path_1.basename(fileName),
165 }));
166 }
167 return [output.outputFiles[1].text, output.outputFiles[0].text];
168 };
169 getTypeInfo = function (code, fileName, position) {
170 updateMemoryCache_1(code, fileName);
171 var info = service_1.getQuickInfoAtPosition(fileName, position);
172 var name = ts.displayPartsToString(info ? info.displayParts : []);
173 var comment = ts.displayPartsToString(info ? info.documentation : []);
174 return { name: name, comment: comment };
175 };
176 }
177 var compile = readThrough(cachedir, memoryCache, getOutput, getExtension, cwd, logger);
178 return { cwd: cwd, compile: compile, getTypeInfo: getTypeInfo, extensions: extensions, cachedir: cachedir, ts: ts };
179}
180exports.createCompiler = createCompiler;
181function readThrough(cachedir, memoryCache, compile, getExtension, cwd, logger) {
182 if (!cachedir) {
183 return function (code, fileName, lineOffset) {
184 logger.debug({ fileName: fileName }, 'readThrough(): no cache');
185 var _a = __read(compile(code, fileName, lineOffset), 2), value = _a[0], sourceMap = _a[1];
186 var output = updateOutput(value, fileName, sourceMap, getExtension, cwd);
187 memoryCache.outputs[fileName] = output;
188 return output;
189 };
190 }
191 mkdirp.sync(cachedir);
192 return function (code, fileName, lineOffset) {
193 var cachePath = path_1.join(cachedir, getCacheName(code, fileName));
194 var extension = getExtension(fileName);
195 var outputPath = "" + cachePath + extension;
196 try {
197 var output_1 = fs_1.readFileSync(outputPath, 'utf8');
198 if (isValidCacheContent(output_1)) {
199 logger.debug({ fileName: fileName }, 'readThrough(): cache hit');
200 memoryCache.outputs[fileName] = output_1;
201 return output_1;
202 }
203 }
204 catch (err) { }
205 logger.debug({ fileName: fileName }, 'readThrough(): cache miss');
206 var _a = __read(compile(code, fileName, lineOffset), 2), value = _a[0], sourceMap = _a[1];
207 var output = updateOutput(value, fileName, sourceMap, getExtension, cwd);
208 logger.debug({ fileName: fileName, outputPath: outputPath }, 'readThrough(): writing caches');
209 memoryCache.outputs[fileName] = output;
210 fs_1.writeFileSync(outputPath, output);
211 return output;
212 };
213}
214function updateOutput(outputText, fileName, sourceMap, getExtension, sourceRoot) {
215 var base = path_1.basename(fileName);
216 var base64Map = buffer_from_1.default(updateSourceMap(sourceMap, fileName, sourceRoot), 'utf8').toString('base64');
217 var sourceMapContent = "data:application/json;charset=utf-8;base64," + base64Map;
218 var sourceMapLength = (base + ".map").length + (getExtension(fileName).length - path_1.extname(fileName).length);
219 return outputText.slice(0, -sourceMapLength) + sourceMapContent;
220}
221function updateSourceMap(sourceMapText, fileName, _sourceRoot) {
222 var sourceMap = JSON.parse(sourceMapText);
223 sourceMap.file = fileName;
224 sourceMap.sources = [fileName];
225 delete sourceMap.sourceRoot;
226 return stableStringify(sourceMap);
227}
228function getCacheName(sourceCode, fileName) {
229 return sha1_1.sha1(path_1.extname(fileName), '\x00', sourceCode);
230}
231function isValidCacheContent(contents) {
232 return /(?:9|0=|Q==)$/.test(contents.slice(-3));
233}