Няма описание

index.js 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import CJSImportProcessor from "./CJSImportProcessor";
  2. import computeSourceMap, {} from "./computeSourceMap";
  3. import {HelperManager} from "./HelperManager";
  4. import identifyShadowedGlobals from "./identifyShadowedGlobals";
  5. import NameManager from "./NameManager";
  6. import {validateOptions} from "./Options";
  7. import {parse} from "./parser";
  8. import TokenProcessor from "./TokenProcessor";
  9. import RootTransformer from "./transformers/RootTransformer";
  10. import formatTokens from "./util/formatTokens";
  11. import getTSImportedNames from "./util/getTSImportedNames";
  12. export function getVersion() {
  13. /* istanbul ignore next */
  14. return "3.32.0";
  15. }
  16. export function transform(code, options) {
  17. validateOptions(options);
  18. try {
  19. const sucraseContext = getSucraseContext(code, options);
  20. const transformer = new RootTransformer(
  21. sucraseContext,
  22. options.transforms,
  23. Boolean(options.enableLegacyBabel5ModuleInterop),
  24. options,
  25. );
  26. const transformerResult = transformer.transform();
  27. let result = {code: transformerResult.code};
  28. if (options.sourceMapOptions) {
  29. if (!options.filePath) {
  30. throw new Error("filePath must be specified when generating a source map.");
  31. }
  32. result = {
  33. ...result,
  34. sourceMap: computeSourceMap(
  35. transformerResult,
  36. options.filePath,
  37. options.sourceMapOptions,
  38. code,
  39. sucraseContext.tokenProcessor.tokens,
  40. ),
  41. };
  42. }
  43. return result;
  44. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  45. } catch (e) {
  46. if (options.filePath) {
  47. e.message = `Error transforming ${options.filePath}: ${e.message}`;
  48. }
  49. throw e;
  50. }
  51. }
  52. /**
  53. * Return a string representation of the sucrase tokens, mostly useful for
  54. * diagnostic purposes.
  55. */
  56. export function getFormattedTokens(code, options) {
  57. const tokens = getSucraseContext(code, options).tokenProcessor.tokens;
  58. return formatTokens(code, tokens);
  59. }
  60. /**
  61. * Call into the parser/tokenizer and do some further preprocessing:
  62. * - Come up with a set of used names so that we can assign new names.
  63. * - Preprocess all import/export statements so we know which globals we are interested in.
  64. * - Compute situations where any of those globals are shadowed.
  65. *
  66. * In the future, some of these preprocessing steps can be skipped based on what actual work is
  67. * being done.
  68. */
  69. function getSucraseContext(code, options) {
  70. const isJSXEnabled = options.transforms.includes("jsx");
  71. const isTypeScriptEnabled = options.transforms.includes("typescript");
  72. const isFlowEnabled = options.transforms.includes("flow");
  73. const disableESTransforms = options.disableESTransforms === true;
  74. const file = parse(code, isJSXEnabled, isTypeScriptEnabled, isFlowEnabled);
  75. const tokens = file.tokens;
  76. const scopes = file.scopes;
  77. const nameManager = new NameManager(code, tokens);
  78. const helperManager = new HelperManager(nameManager);
  79. const tokenProcessor = new TokenProcessor(
  80. code,
  81. tokens,
  82. isFlowEnabled,
  83. disableESTransforms,
  84. helperManager,
  85. );
  86. const enableLegacyTypeScriptModuleInterop = Boolean(options.enableLegacyTypeScriptModuleInterop);
  87. let importProcessor = null;
  88. if (options.transforms.includes("imports")) {
  89. importProcessor = new CJSImportProcessor(
  90. nameManager,
  91. tokenProcessor,
  92. enableLegacyTypeScriptModuleInterop,
  93. options,
  94. options.transforms.includes("typescript"),
  95. helperManager,
  96. );
  97. importProcessor.preprocessTokens();
  98. // We need to mark shadowed globals after processing imports so we know that the globals are,
  99. // but before type-only import pruning, since that relies on shadowing information.
  100. identifyShadowedGlobals(tokenProcessor, scopes, importProcessor.getGlobalNames());
  101. if (options.transforms.includes("typescript")) {
  102. importProcessor.pruneTypeOnlyImports();
  103. }
  104. } else if (options.transforms.includes("typescript")) {
  105. identifyShadowedGlobals(tokenProcessor, scopes, getTSImportedNames(tokenProcessor));
  106. }
  107. return {tokenProcessor, scopes, nameManager, importProcessor, helperManager};
  108. }