1 | "use strict";
|
2 | var __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 | };
|
13 | var __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 | };
|
23 | var __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 | };
|
39 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
40 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
41 | };
|
42 | Object.defineProperty(exports, "__esModule", { value: true });
|
43 | var bs_logger_1 = require("bs-logger");
|
44 | var buffer_from_1 = __importDefault(require("buffer-from"));
|
45 | var stableStringify = require("fast-json-stable-stringify");
|
46 | var fs_1 = require("fs");
|
47 | var mkdirp = require("mkdirp");
|
48 | var path_1 = require("path");
|
49 | var messages_1 = require("./util/messages");
|
50 | var sha1_1 = require("./util/sha1");
|
51 | var hasOwn = Object.prototype.hasOwnProperty;
|
52 | function 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 | }
|
180 | exports.createCompiler = createCompiler;
|
181 | function 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 | }
|
214 | function 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 | }
|
221 | function 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 | }
|
228 | function getCacheName(sourceCode, fileName) {
|
229 | return sha1_1.sha1(path_1.extname(fileName), '\x00', sourceCode);
|
230 | }
|
231 | function isValidCacheContent(contents) {
|
232 | return /(?:9|0=|Q==)$/.test(contents.slice(-3));
|
233 | }
|