ts-internals.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.getEmitScriptTarget = exports.getUseDefineForClassFields = exports.getPatternFromSpec = exports.createTsInternals = void 0;
  4. const path_1 = require("path");
  5. const util_1 = require("./util");
  6. /** @internal */
  7. exports.createTsInternals = (0, util_1.cachedLookup)(createTsInternalsUncached);
  8. /**
  9. * Given a reference to the TS compiler, return some TS internal functions that we
  10. * could not or did not want to grab off the `ts` object.
  11. * These have been copy-pasted from TS's source and tweaked as necessary.
  12. *
  13. * NOTE: This factory returns *only* functions which need a reference to the TS
  14. * compiler. Other functions do not need a reference to the TS compiler so are
  15. * exported directly from this file.
  16. */
  17. function createTsInternalsUncached(_ts) {
  18. const ts = _ts;
  19. /**
  20. * Copied from:
  21. * https://github.com/microsoft/TypeScript/blob/v4.3.2/src/compiler/commandLineParser.ts#L2821-L2846
  22. */
  23. function getExtendsConfigPath(extendedConfig, host, basePath, errors, createDiagnostic) {
  24. extendedConfig = (0, util_1.normalizeSlashes)(extendedConfig);
  25. if (isRootedDiskPath(extendedConfig) ||
  26. startsWith(extendedConfig, './') ||
  27. startsWith(extendedConfig, '../')) {
  28. let extendedConfigPath = getNormalizedAbsolutePath(extendedConfig, basePath);
  29. if (!host.fileExists(extendedConfigPath) &&
  30. !endsWith(extendedConfigPath, ts.Extension.Json)) {
  31. extendedConfigPath = `${extendedConfigPath}.json`;
  32. if (!host.fileExists(extendedConfigPath)) {
  33. errors.push(createDiagnostic(ts.Diagnostics.File_0_not_found, extendedConfig));
  34. return undefined;
  35. }
  36. }
  37. return extendedConfigPath;
  38. }
  39. // If the path isn't a rooted or relative path, resolve like a module
  40. const tsGte5_3_0 = (0, util_1.versionGteLt)(ts.version, '5.3.0');
  41. const resolved = ts.nodeModuleNameResolver(extendedConfig, combinePaths(basePath, 'tsconfig.json'), { moduleResolution: ts.ModuleResolutionKind.NodeJs }, host,
  42. /*cache*/ undefined,
  43. /*projectRefs*/ undefined,
  44. /*conditionsOrIsConfigLookup*/ tsGte5_3_0 ? undefined : true,
  45. /*isConfigLookup*/ tsGte5_3_0 ? true : undefined);
  46. if (resolved.resolvedModule) {
  47. return resolved.resolvedModule.resolvedFileName;
  48. }
  49. errors.push(createDiagnostic(ts.Diagnostics.File_0_not_found, extendedConfig));
  50. return undefined;
  51. }
  52. return { getExtendsConfigPath };
  53. }
  54. // These functions have alternative implementation to avoid copying too much from TS
  55. function isRootedDiskPath(path) {
  56. return (0, path_1.isAbsolute)(path);
  57. }
  58. function combinePaths(path, ...paths) {
  59. return (0, util_1.normalizeSlashes)((0, path_1.resolve)(path, ...paths.filter((path) => path)));
  60. }
  61. function getNormalizedAbsolutePath(fileName, currentDirectory) {
  62. return (0, util_1.normalizeSlashes)(currentDirectory != null
  63. ? (0, path_1.resolve)(currentDirectory, fileName)
  64. : (0, path_1.resolve)(fileName));
  65. }
  66. function startsWith(str, prefix) {
  67. return str.lastIndexOf(prefix, 0) === 0;
  68. }
  69. function endsWith(str, suffix) {
  70. const expectedPos = str.length - suffix.length;
  71. return expectedPos >= 0 && str.indexOf(suffix, expectedPos) === expectedPos;
  72. }
  73. // Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
  74. // It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
  75. // proof.
  76. const reservedCharacterPattern = /[^\w\s\/]/g;
  77. /**
  78. * @internal
  79. * See also: getRegularExpressionForWildcard, which seems to do almost the same thing
  80. */
  81. function getPatternFromSpec(spec, basePath) {
  82. const pattern = spec && getSubPatternFromSpec(spec, basePath, excludeMatcher);
  83. return pattern && `^(${pattern})${'($|/)'}`;
  84. }
  85. exports.getPatternFromSpec = getPatternFromSpec;
  86. function getSubPatternFromSpec(spec, basePath, { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter, }) {
  87. let subpattern = '';
  88. let hasWrittenComponent = false;
  89. const components = getNormalizedPathComponents(spec, basePath);
  90. const lastComponent = last(components);
  91. // getNormalizedPathComponents includes the separator for the root component.
  92. // We need to remove to create our regex correctly.
  93. components[0] = removeTrailingDirectorySeparator(components[0]);
  94. if (isImplicitGlob(lastComponent)) {
  95. components.push('**', '*');
  96. }
  97. let optionalCount = 0;
  98. for (let component of components) {
  99. if (component === '**') {
  100. subpattern += doubleAsteriskRegexFragment;
  101. }
  102. else {
  103. if (hasWrittenComponent) {
  104. subpattern += directorySeparator;
  105. }
  106. subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
  107. }
  108. hasWrittenComponent = true;
  109. }
  110. while (optionalCount > 0) {
  111. subpattern += ')?';
  112. optionalCount--;
  113. }
  114. return subpattern;
  115. }
  116. const directoriesMatcher = {
  117. singleAsteriskRegexFragment: '[^/]*',
  118. /**
  119. * Regex for the ** wildcard. Matches any num of subdirectories. When used for including
  120. * files or directories, does not match subdirectories that start with a . character
  121. */
  122. doubleAsteriskRegexFragment: `(/[^/.][^/]*)*?`,
  123. replaceWildcardCharacter: (match) => replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment),
  124. };
  125. const excludeMatcher = {
  126. singleAsteriskRegexFragment: '[^/]*',
  127. doubleAsteriskRegexFragment: '(/.+?)?',
  128. replaceWildcardCharacter: (match) => replaceWildcardCharacter(match, excludeMatcher.singleAsteriskRegexFragment),
  129. };
  130. function getNormalizedPathComponents(path, currentDirectory) {
  131. return reducePathComponents(getPathComponents(path, currentDirectory));
  132. }
  133. function getPathComponents(path, currentDirectory = '') {
  134. path = combinePaths(currentDirectory, path);
  135. return pathComponents(path, getRootLength(path));
  136. }
  137. function reducePathComponents(components) {
  138. if (!some(components))
  139. return [];
  140. const reduced = [components[0]];
  141. for (let i = 1; i < components.length; i++) {
  142. const component = components[i];
  143. if (!component)
  144. continue;
  145. if (component === '.')
  146. continue;
  147. if (component === '..') {
  148. if (reduced.length > 1) {
  149. if (reduced[reduced.length - 1] !== '..') {
  150. reduced.pop();
  151. continue;
  152. }
  153. }
  154. else if (reduced[0])
  155. continue;
  156. }
  157. reduced.push(component);
  158. }
  159. return reduced;
  160. }
  161. function getRootLength(path) {
  162. const rootLength = getEncodedRootLength(path);
  163. return rootLength < 0 ? ~rootLength : rootLength;
  164. }
  165. function getEncodedRootLength(path) {
  166. if (!path)
  167. return 0;
  168. const ch0 = path.charCodeAt(0);
  169. // POSIX or UNC
  170. if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
  171. if (path.charCodeAt(1) !== ch0)
  172. return 1; // POSIX: "/" (or non-normalized "\")
  173. const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? directorySeparator : altDirectorySeparator, 2);
  174. if (p1 < 0)
  175. return path.length; // UNC: "//server" or "\\server"
  176. return p1 + 1; // UNC: "//server/" or "\\server\"
  177. }
  178. // DOS
  179. if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
  180. const ch2 = path.charCodeAt(2);
  181. if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
  182. return 3; // DOS: "c:/" or "c:\"
  183. if (path.length === 2)
  184. return 2; // DOS: "c:" (but not "c:d")
  185. }
  186. // URL
  187. const schemeEnd = path.indexOf(urlSchemeSeparator);
  188. if (schemeEnd !== -1) {
  189. const authorityStart = schemeEnd + urlSchemeSeparator.length;
  190. const authorityEnd = path.indexOf(directorySeparator, authorityStart);
  191. if (authorityEnd !== -1) {
  192. // URL: "file:///", "file://server/", "file://server/path"
  193. // For local "file" URLs, include the leading DOS volume (if present).
  194. // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
  195. // special case interpreted as "the machine from which the URL is being interpreted".
  196. const scheme = path.slice(0, schemeEnd);
  197. const authority = path.slice(authorityStart, authorityEnd);
  198. if (scheme === 'file' &&
  199. (authority === '' || authority === 'localhost') &&
  200. isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
  201. const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
  202. if (volumeSeparatorEnd !== -1) {
  203. if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
  204. // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
  205. return ~(volumeSeparatorEnd + 1);
  206. }
  207. if (volumeSeparatorEnd === path.length) {
  208. // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
  209. // but not "file:///c:d" or "file:///c%3ad"
  210. return ~volumeSeparatorEnd;
  211. }
  212. }
  213. }
  214. return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
  215. }
  216. return ~path.length; // URL: "file://server", "http://server"
  217. }
  218. // relative
  219. return 0;
  220. }
  221. function ensureTrailingDirectorySeparator(path) {
  222. if (!hasTrailingDirectorySeparator(path)) {
  223. return path + directorySeparator;
  224. }
  225. return path;
  226. }
  227. function hasTrailingDirectorySeparator(path) {
  228. return (path.length > 0 && isAnyDirectorySeparator(path.charCodeAt(path.length - 1)));
  229. }
  230. function isAnyDirectorySeparator(charCode) {
  231. return (charCode === 47 /* CharacterCodes.slash */ || charCode === 92 /* CharacterCodes.backslash */);
  232. }
  233. function removeTrailingDirectorySeparator(path) {
  234. if (hasTrailingDirectorySeparator(path)) {
  235. return path.substr(0, path.length - 1);
  236. }
  237. return path;
  238. }
  239. const directorySeparator = '/';
  240. const altDirectorySeparator = '\\';
  241. const urlSchemeSeparator = '://';
  242. function isVolumeCharacter(charCode) {
  243. return ((charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
  244. (charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */));
  245. }
  246. function getFileUrlVolumeSeparatorEnd(url, start) {
  247. const ch0 = url.charCodeAt(start);
  248. if (ch0 === 58 /* CharacterCodes.colon */)
  249. return start + 1;
  250. if (ch0 === 37 /* CharacterCodes.percent */ &&
  251. url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
  252. const ch2 = url.charCodeAt(start + 2);
  253. if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
  254. return start + 3;
  255. }
  256. return -1;
  257. }
  258. function some(array, predicate) {
  259. if (array) {
  260. if (predicate) {
  261. for (const v of array) {
  262. if (predicate(v)) {
  263. return true;
  264. }
  265. }
  266. }
  267. else {
  268. return array.length > 0;
  269. }
  270. }
  271. return false;
  272. }
  273. function pathComponents(path, rootLength) {
  274. const root = path.substring(0, rootLength);
  275. const rest = path.substring(rootLength).split(directorySeparator);
  276. if (rest.length && !lastOrUndefined(rest))
  277. rest.pop();
  278. return [root, ...rest];
  279. }
  280. function lastOrUndefined(array) {
  281. return array.length === 0 ? undefined : array[array.length - 1];
  282. }
  283. function last(array) {
  284. // Debug.assert(array.length !== 0);
  285. return array[array.length - 1];
  286. }
  287. function replaceWildcardCharacter(match, singleAsteriskRegexFragment) {
  288. return match === '*'
  289. ? singleAsteriskRegexFragment
  290. : match === '?'
  291. ? '[^/]'
  292. : '\\' + match;
  293. }
  294. /**
  295. * An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension,
  296. * and does not contain any glob characters itself.
  297. */
  298. function isImplicitGlob(lastPathComponent) {
  299. return !/[.*?]/.test(lastPathComponent);
  300. }
  301. const ts_ScriptTarget_ES5 = 1;
  302. const ts_ScriptTarget_ES2022 = 9;
  303. const ts_ScriptTarget_ESNext = 99;
  304. const ts_ModuleKind_Node16 = 100;
  305. const ts_ModuleKind_NodeNext = 199;
  306. // https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8761
  307. function getUseDefineForClassFields(compilerOptions) {
  308. return compilerOptions.useDefineForClassFields === undefined
  309. ? getEmitScriptTarget(compilerOptions) >= ts_ScriptTarget_ES2022
  310. : compilerOptions.useDefineForClassFields;
  311. }
  312. exports.getUseDefineForClassFields = getUseDefineForClassFields;
  313. // https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8556
  314. function getEmitScriptTarget(compilerOptions) {
  315. var _a;
  316. return ((_a = compilerOptions.target) !== null && _a !== void 0 ? _a : ((compilerOptions.module === ts_ModuleKind_Node16 && ts_ScriptTarget_ES2022) ||
  317. (compilerOptions.module === ts_ModuleKind_NodeNext && ts_ScriptTarget_ESNext) ||
  318. ts_ScriptTarget_ES5));
  319. }
  320. exports.getEmitScriptTarget = getEmitScriptTarget;
  321. //# sourceMappingURL=ts-internals.js.map