UNPKG

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