| 1 | "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 | var _tokenizer = require('../parser/tokenizer');
|
|---|
| 5 | var _keywords = require('../parser/tokenizer/keywords');
|
|---|
| 6 | var _types = require('../parser/tokenizer/types');
|
|---|
| 7 |
|
|---|
| 8 | var _elideImportEquals = require('../util/elideImportEquals'); var _elideImportEquals2 = _interopRequireDefault(_elideImportEquals);
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 | var _getDeclarationInfo = require('../util/getDeclarationInfo'); var _getDeclarationInfo2 = _interopRequireDefault(_getDeclarationInfo);
|
|---|
| 13 | var _getImportExportSpecifierInfo = require('../util/getImportExportSpecifierInfo'); var _getImportExportSpecifierInfo2 = _interopRequireDefault(_getImportExportSpecifierInfo);
|
|---|
| 14 | var _isExportFrom = require('../util/isExportFrom'); var _isExportFrom2 = _interopRequireDefault(_isExportFrom);
|
|---|
| 15 | var _removeMaybeImportAttributes = require('../util/removeMaybeImportAttributes');
|
|---|
| 16 | var _shouldElideDefaultExport = require('../util/shouldElideDefaultExport'); var _shouldElideDefaultExport2 = _interopRequireDefault(_shouldElideDefaultExport);
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 | var _Transformer = require('./Transformer'); var _Transformer2 = _interopRequireDefault(_Transformer);
|
|---|
| 20 |
|
|---|
| 21 | /**
|
|---|
| 22 | * Class for editing import statements when we are transforming to commonjs.
|
|---|
| 23 | */
|
|---|
| 24 | class CJSImportTransformer extends _Transformer2.default {
|
|---|
| 25 | __init() {this.hadExport = false}
|
|---|
| 26 | __init2() {this.hadNamedExport = false}
|
|---|
| 27 | __init3() {this.hadDefaultExport = false}
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 | constructor(
|
|---|
| 31 | rootTransformer,
|
|---|
| 32 | tokens,
|
|---|
| 33 | importProcessor,
|
|---|
| 34 | nameManager,
|
|---|
| 35 | helperManager,
|
|---|
| 36 | reactHotLoaderTransformer,
|
|---|
| 37 | enableLegacyBabel5ModuleInterop,
|
|---|
| 38 | enableLegacyTypeScriptModuleInterop,
|
|---|
| 39 | isTypeScriptTransformEnabled,
|
|---|
| 40 | isFlowTransformEnabled,
|
|---|
| 41 | preserveDynamicImport,
|
|---|
| 42 | keepUnusedImports,
|
|---|
| 43 | ) {
|
|---|
| 44 | super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.importProcessor = importProcessor;this.nameManager = nameManager;this.helperManager = helperManager;this.reactHotLoaderTransformer = reactHotLoaderTransformer;this.enableLegacyBabel5ModuleInterop = enableLegacyBabel5ModuleInterop;this.enableLegacyTypeScriptModuleInterop = enableLegacyTypeScriptModuleInterop;this.isTypeScriptTransformEnabled = isTypeScriptTransformEnabled;this.isFlowTransformEnabled = isFlowTransformEnabled;this.preserveDynamicImport = preserveDynamicImport;this.keepUnusedImports = keepUnusedImports;CJSImportTransformer.prototype.__init.call(this);CJSImportTransformer.prototype.__init2.call(this);CJSImportTransformer.prototype.__init3.call(this);;
|
|---|
| 45 | this.declarationInfo = isTypeScriptTransformEnabled
|
|---|
| 46 | ? _getDeclarationInfo2.default.call(void 0, tokens)
|
|---|
| 47 | : _getDeclarationInfo.EMPTY_DECLARATION_INFO;
|
|---|
| 48 | }
|
|---|
| 49 |
|
|---|
| 50 | getPrefixCode() {
|
|---|
| 51 | let prefix = "";
|
|---|
| 52 | if (this.hadExport) {
|
|---|
| 53 | prefix += 'Object.defineProperty(exports, "__esModule", {value: true});';
|
|---|
| 54 | }
|
|---|
| 55 | return prefix;
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 | getSuffixCode() {
|
|---|
| 59 | if (this.enableLegacyBabel5ModuleInterop && this.hadDefaultExport && !this.hadNamedExport) {
|
|---|
| 60 | return "\nmodule.exports = exports.default;\n";
|
|---|
| 61 | }
|
|---|
| 62 | return "";
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | process() {
|
|---|
| 66 | // TypeScript `import foo = require('foo');` should always just be translated to plain require.
|
|---|
| 67 | if (this.tokens.matches3(_types.TokenType._import, _types.TokenType.name, _types.TokenType.eq)) {
|
|---|
| 68 | return this.processImportEquals();
|
|---|
| 69 | }
|
|---|
| 70 | if (this.tokens.matches1(_types.TokenType._import)) {
|
|---|
| 71 | this.processImport();
|
|---|
| 72 | return true;
|
|---|
| 73 | }
|
|---|
| 74 | if (this.tokens.matches2(_types.TokenType._export, _types.TokenType.eq)) {
|
|---|
| 75 | this.tokens.replaceToken("module.exports");
|
|---|
| 76 | return true;
|
|---|
| 77 | }
|
|---|
| 78 | if (this.tokens.matches1(_types.TokenType._export) && !this.tokens.currentToken().isType) {
|
|---|
| 79 | this.hadExport = true;
|
|---|
| 80 | return this.processExport();
|
|---|
| 81 | }
|
|---|
| 82 | if (this.tokens.matches2(_types.TokenType.name, _types.TokenType.postIncDec)) {
|
|---|
| 83 | // Fall through to normal identifier matching if this doesn't apply.
|
|---|
| 84 | if (this.processPostIncDec()) {
|
|---|
| 85 | return true;
|
|---|
| 86 | }
|
|---|
| 87 | }
|
|---|
| 88 | if (this.tokens.matches1(_types.TokenType.name) || this.tokens.matches1(_types.TokenType.jsxName)) {
|
|---|
| 89 | return this.processIdentifier();
|
|---|
| 90 | }
|
|---|
| 91 | if (this.tokens.matches1(_types.TokenType.eq)) {
|
|---|
| 92 | return this.processAssignment();
|
|---|
| 93 | }
|
|---|
| 94 | if (this.tokens.matches1(_types.TokenType.assign)) {
|
|---|
| 95 | return this.processComplexAssignment();
|
|---|
| 96 | }
|
|---|
| 97 | if (this.tokens.matches1(_types.TokenType.preIncDec)) {
|
|---|
| 98 | return this.processPreIncDec();
|
|---|
| 99 | }
|
|---|
| 100 | return false;
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 | processImportEquals() {
|
|---|
| 104 | const importName = this.tokens.identifierNameAtIndex(this.tokens.currentIndex() + 1);
|
|---|
| 105 | if (this.importProcessor.shouldAutomaticallyElideImportedName(importName)) {
|
|---|
| 106 | // If this name is only used as a type, elide the whole import.
|
|---|
| 107 | _elideImportEquals2.default.call(void 0, this.tokens);
|
|---|
| 108 | } else {
|
|---|
| 109 | // Otherwise, switch `import` to `const`.
|
|---|
| 110 | this.tokens.replaceToken("const");
|
|---|
| 111 | }
|
|---|
| 112 | return true;
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | /**
|
|---|
| 116 | * Transform this:
|
|---|
| 117 | * import foo, {bar} from 'baz';
|
|---|
| 118 | * into
|
|---|
| 119 | * var _baz = require('baz'); var _baz2 = _interopRequireDefault(_baz);
|
|---|
| 120 | *
|
|---|
| 121 | * The import code was already generated in the import preprocessing step, so
|
|---|
| 122 | * we just need to look it up.
|
|---|
| 123 | */
|
|---|
| 124 | processImport() {
|
|---|
| 125 | if (this.tokens.matches2(_types.TokenType._import, _types.TokenType.parenL)) {
|
|---|
| 126 | if (this.preserveDynamicImport) {
|
|---|
| 127 | // Bail out, only making progress for this one token.
|
|---|
| 128 | this.tokens.copyToken();
|
|---|
| 129 | return;
|
|---|
| 130 | }
|
|---|
| 131 | const requireWrapper = this.enableLegacyTypeScriptModuleInterop
|
|---|
| 132 | ? ""
|
|---|
| 133 | : `${this.helperManager.getHelperName("interopRequireWildcard")}(`;
|
|---|
| 134 | this.tokens.replaceToken(`Promise.resolve().then(() => ${requireWrapper}require`);
|
|---|
| 135 | const contextId = this.tokens.currentToken().contextId;
|
|---|
| 136 | if (contextId == null) {
|
|---|
| 137 | throw new Error("Expected context ID on dynamic import invocation.");
|
|---|
| 138 | }
|
|---|
| 139 | this.tokens.copyToken();
|
|---|
| 140 | while (!this.tokens.matchesContextIdAndLabel(_types.TokenType.parenR, contextId)) {
|
|---|
| 141 | this.rootTransformer.processToken();
|
|---|
| 142 | }
|
|---|
| 143 | this.tokens.replaceToken(requireWrapper ? ")))" : "))");
|
|---|
| 144 | return;
|
|---|
| 145 | }
|
|---|
| 146 |
|
|---|
| 147 | const shouldElideImport = this.removeImportAndDetectIfShouldElide();
|
|---|
| 148 | if (shouldElideImport) {
|
|---|
| 149 | this.tokens.removeToken();
|
|---|
| 150 | } else {
|
|---|
| 151 | const path = this.tokens.stringValue();
|
|---|
| 152 | this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path));
|
|---|
| 153 | this.tokens.appendCode(this.importProcessor.claimImportCode(path));
|
|---|
| 154 | }
|
|---|
| 155 | _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|---|
| 156 | if (this.tokens.matches1(_types.TokenType.semi)) {
|
|---|
| 157 | this.tokens.removeToken();
|
|---|
| 158 | }
|
|---|
| 159 | }
|
|---|
| 160 |
|
|---|
| 161 | /**
|
|---|
| 162 | * Erase this import (since any CJS output would be completely different), and
|
|---|
| 163 | * return true if this import is should be elided due to being a type-only
|
|---|
| 164 | * import. Such imports will not be emitted at all to avoid side effects.
|
|---|
| 165 | *
|
|---|
| 166 | * Import elision only happens with the TypeScript or Flow transforms enabled.
|
|---|
| 167 | *
|
|---|
| 168 | * TODO: This function has some awkward overlap with
|
|---|
| 169 | * CJSImportProcessor.pruneTypeOnlyImports , and the two should be unified.
|
|---|
| 170 | * That function handles TypeScript implicit import name elision, and removes
|
|---|
| 171 | * an import if all typical imported names (without `type`) are removed due
|
|---|
| 172 | * to being type-only imports. This function handles Flow import removal and
|
|---|
| 173 | * properly distinguishes `import 'foo'` from `import {} from 'foo'` for TS
|
|---|
| 174 | * purposes.
|
|---|
| 175 | *
|
|---|
| 176 | * The position should end at the import string.
|
|---|
| 177 | */
|
|---|
| 178 | removeImportAndDetectIfShouldElide() {
|
|---|
| 179 | this.tokens.removeInitialToken();
|
|---|
| 180 | if (
|
|---|
| 181 | this.tokens.matchesContextual(_keywords.ContextualKeyword._type) &&
|
|---|
| 182 | !this.tokens.matches1AtIndex(this.tokens.currentIndex() + 1, _types.TokenType.comma) &&
|
|---|
| 183 | !this.tokens.matchesContextualAtIndex(this.tokens.currentIndex() + 1, _keywords.ContextualKeyword._from)
|
|---|
| 184 | ) {
|
|---|
| 185 | // This is an "import type" statement, so exit early.
|
|---|
| 186 | this.removeRemainingImport();
|
|---|
| 187 | return true;
|
|---|
| 188 | }
|
|---|
| 189 |
|
|---|
| 190 | if (this.tokens.matches1(_types.TokenType.name) || this.tokens.matches1(_types.TokenType.star)) {
|
|---|
| 191 | // We have a default import or namespace import, so there must be some
|
|---|
| 192 | // non-type import.
|
|---|
| 193 | this.removeRemainingImport();
|
|---|
| 194 | return false;
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 | if (this.tokens.matches1(_types.TokenType.string)) {
|
|---|
| 198 | // This is a bare import, so we should proceed with the import.
|
|---|
| 199 | return false;
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | let foundNonTypeImport = false;
|
|---|
| 203 | let foundAnyNamedImport = false;
|
|---|
| 204 | while (!this.tokens.matches1(_types.TokenType.string)) {
|
|---|
| 205 | // Check if any named imports are of the form "foo" or "foo as bar", with
|
|---|
| 206 | // no leading "type".
|
|---|
| 207 | if (
|
|---|
| 208 | (!foundNonTypeImport && this.tokens.matches1(_types.TokenType.braceL)) ||
|
|---|
| 209 | this.tokens.matches1(_types.TokenType.comma)
|
|---|
| 210 | ) {
|
|---|
| 211 | this.tokens.removeToken();
|
|---|
| 212 | if (!this.tokens.matches1(_types.TokenType.braceR)) {
|
|---|
| 213 | foundAnyNamedImport = true;
|
|---|
| 214 | }
|
|---|
| 215 | if (
|
|---|
| 216 | this.tokens.matches2(_types.TokenType.name, _types.TokenType.comma) ||
|
|---|
| 217 | this.tokens.matches2(_types.TokenType.name, _types.TokenType.braceR) ||
|
|---|
| 218 | this.tokens.matches4(_types.TokenType.name, _types.TokenType.name, _types.TokenType.name, _types.TokenType.comma) ||
|
|---|
| 219 | this.tokens.matches4(_types.TokenType.name, _types.TokenType.name, _types.TokenType.name, _types.TokenType.braceR)
|
|---|
| 220 | ) {
|
|---|
| 221 | foundNonTypeImport = true;
|
|---|
| 222 | }
|
|---|
| 223 | }
|
|---|
| 224 | this.tokens.removeToken();
|
|---|
| 225 | }
|
|---|
| 226 | if (this.keepUnusedImports) {
|
|---|
| 227 | return false;
|
|---|
| 228 | }
|
|---|
| 229 | if (this.isTypeScriptTransformEnabled) {
|
|---|
| 230 | return !foundNonTypeImport;
|
|---|
| 231 | } else if (this.isFlowTransformEnabled) {
|
|---|
| 232 | // In Flow, unlike TS, `import {} from 'foo';` preserves the import.
|
|---|
| 233 | return foundAnyNamedImport && !foundNonTypeImport;
|
|---|
| 234 | } else {
|
|---|
| 235 | return false;
|
|---|
| 236 | }
|
|---|
| 237 | }
|
|---|
| 238 |
|
|---|
| 239 | removeRemainingImport() {
|
|---|
| 240 | while (!this.tokens.matches1(_types.TokenType.string)) {
|
|---|
| 241 | this.tokens.removeToken();
|
|---|
| 242 | }
|
|---|
| 243 | }
|
|---|
| 244 |
|
|---|
| 245 | processIdentifier() {
|
|---|
| 246 | const token = this.tokens.currentToken();
|
|---|
| 247 | if (token.shadowsGlobal) {
|
|---|
| 248 | return false;
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 | if (token.identifierRole === _tokenizer.IdentifierRole.ObjectShorthand) {
|
|---|
| 252 | return this.processObjectShorthand();
|
|---|
| 253 | }
|
|---|
| 254 |
|
|---|
| 255 | if (token.identifierRole !== _tokenizer.IdentifierRole.Access) {
|
|---|
| 256 | return false;
|
|---|
| 257 | }
|
|---|
| 258 | const replacement = this.importProcessor.getIdentifierReplacement(
|
|---|
| 259 | this.tokens.identifierNameForToken(token),
|
|---|
| 260 | );
|
|---|
| 261 | if (!replacement) {
|
|---|
| 262 | return false;
|
|---|
| 263 | }
|
|---|
| 264 | // Tolerate any number of closing parens while looking for an opening paren
|
|---|
| 265 | // that indicates a function call.
|
|---|
| 266 | let possibleOpenParenIndex = this.tokens.currentIndex() + 1;
|
|---|
| 267 | while (
|
|---|
| 268 | possibleOpenParenIndex < this.tokens.tokens.length &&
|
|---|
| 269 | this.tokens.tokens[possibleOpenParenIndex].type === _types.TokenType.parenR
|
|---|
| 270 | ) {
|
|---|
| 271 | possibleOpenParenIndex++;
|
|---|
| 272 | }
|
|---|
| 273 | // Avoid treating imported functions as methods of their `exports` object
|
|---|
| 274 | // by using `(0, f)` when the identifier is in a paren expression. Else
|
|---|
| 275 | // use `Function.prototype.call` when the identifier is a guaranteed
|
|---|
| 276 | // function call. When using `call`, pass undefined as the context.
|
|---|
| 277 | if (this.tokens.tokens[possibleOpenParenIndex].type === _types.TokenType.parenL) {
|
|---|
| 278 | if (
|
|---|
| 279 | this.tokens.tokenAtRelativeIndex(1).type === _types.TokenType.parenL &&
|
|---|
| 280 | this.tokens.tokenAtRelativeIndex(-1).type !== _types.TokenType._new
|
|---|
| 281 | ) {
|
|---|
| 282 | this.tokens.replaceToken(`${replacement}.call(void 0, `);
|
|---|
| 283 | // Remove the old paren.
|
|---|
| 284 | this.tokens.removeToken();
|
|---|
| 285 | // Balance out the new paren.
|
|---|
| 286 | this.rootTransformer.processBalancedCode();
|
|---|
| 287 | this.tokens.copyExpectedToken(_types.TokenType.parenR);
|
|---|
| 288 | } else {
|
|---|
| 289 | // See here: http://2ality.com/2015/12/references.html
|
|---|
| 290 | this.tokens.replaceToken(`(0, ${replacement})`);
|
|---|
| 291 | }
|
|---|
| 292 | } else {
|
|---|
| 293 | this.tokens.replaceToken(replacement);
|
|---|
| 294 | }
|
|---|
| 295 | return true;
|
|---|
| 296 | }
|
|---|
| 297 |
|
|---|
| 298 | processObjectShorthand() {
|
|---|
| 299 | const identifier = this.tokens.identifierName();
|
|---|
| 300 | const replacement = this.importProcessor.getIdentifierReplacement(identifier);
|
|---|
| 301 | if (!replacement) {
|
|---|
| 302 | return false;
|
|---|
| 303 | }
|
|---|
| 304 | this.tokens.replaceToken(`${identifier}: ${replacement}`);
|
|---|
| 305 | return true;
|
|---|
| 306 | }
|
|---|
| 307 |
|
|---|
| 308 | processExport() {
|
|---|
| 309 | if (
|
|---|
| 310 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._enum) ||
|
|---|
| 311 | this.tokens.matches3(_types.TokenType._export, _types.TokenType._const, _types.TokenType._enum)
|
|---|
| 312 | ) {
|
|---|
| 313 | this.hadNamedExport = true;
|
|---|
| 314 | // Let the TypeScript transform handle it.
|
|---|
| 315 | return false;
|
|---|
| 316 | }
|
|---|
| 317 | if (this.tokens.matches2(_types.TokenType._export, _types.TokenType._default)) {
|
|---|
| 318 | if (this.tokens.matches3(_types.TokenType._export, _types.TokenType._default, _types.TokenType._enum)) {
|
|---|
| 319 | this.hadDefaultExport = true;
|
|---|
| 320 | // Flow export default enums need some special handling, so handle them
|
|---|
| 321 | // in that tranform rather than this one.
|
|---|
| 322 | return false;
|
|---|
| 323 | }
|
|---|
| 324 | this.processExportDefault();
|
|---|
| 325 | return true;
|
|---|
| 326 | } else if (this.tokens.matches2(_types.TokenType._export, _types.TokenType.braceL)) {
|
|---|
| 327 | this.processExportBindings();
|
|---|
| 328 | return true;
|
|---|
| 329 | } else if (
|
|---|
| 330 | this.tokens.matches2(_types.TokenType._export, _types.TokenType.name) &&
|
|---|
| 331 | this.tokens.matchesContextualAtIndex(this.tokens.currentIndex() + 1, _keywords.ContextualKeyword._type)
|
|---|
| 332 | ) {
|
|---|
| 333 | // export type {a};
|
|---|
| 334 | // export type {a as b};
|
|---|
| 335 | // export type {a} from './b';
|
|---|
| 336 | // export type * from './b';
|
|---|
| 337 | // export type * as ns from './b';
|
|---|
| 338 | this.tokens.removeInitialToken();
|
|---|
| 339 | this.tokens.removeToken();
|
|---|
| 340 | if (this.tokens.matches1(_types.TokenType.braceL)) {
|
|---|
| 341 | while (!this.tokens.matches1(_types.TokenType.braceR)) {
|
|---|
| 342 | this.tokens.removeToken();
|
|---|
| 343 | }
|
|---|
| 344 | this.tokens.removeToken();
|
|---|
| 345 | } else {
|
|---|
| 346 | // *
|
|---|
| 347 | this.tokens.removeToken();
|
|---|
| 348 | if (this.tokens.matches1(_types.TokenType._as)) {
|
|---|
| 349 | // as
|
|---|
| 350 | this.tokens.removeToken();
|
|---|
| 351 | // ns
|
|---|
| 352 | this.tokens.removeToken();
|
|---|
| 353 | }
|
|---|
| 354 | }
|
|---|
| 355 | // Remove type re-export `... } from './T'`
|
|---|
| 356 | if (
|
|---|
| 357 | this.tokens.matchesContextual(_keywords.ContextualKeyword._from) &&
|
|---|
| 358 | this.tokens.matches1AtIndex(this.tokens.currentIndex() + 1, _types.TokenType.string)
|
|---|
| 359 | ) {
|
|---|
| 360 | this.tokens.removeToken();
|
|---|
| 361 | this.tokens.removeToken();
|
|---|
| 362 | _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|---|
| 363 | }
|
|---|
| 364 | return true;
|
|---|
| 365 | }
|
|---|
| 366 | this.hadNamedExport = true;
|
|---|
| 367 | if (
|
|---|
| 368 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._var) ||
|
|---|
| 369 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._let) ||
|
|---|
| 370 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._const)
|
|---|
| 371 | ) {
|
|---|
| 372 | this.processExportVar();
|
|---|
| 373 | return true;
|
|---|
| 374 | } else if (
|
|---|
| 375 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._function) ||
|
|---|
| 376 | // export async function
|
|---|
| 377 | this.tokens.matches3(_types.TokenType._export, _types.TokenType.name, _types.TokenType._function)
|
|---|
| 378 | ) {
|
|---|
| 379 | this.processExportFunction();
|
|---|
| 380 | return true;
|
|---|
| 381 | } else if (
|
|---|
| 382 | this.tokens.matches2(_types.TokenType._export, _types.TokenType._class) ||
|
|---|
| 383 | this.tokens.matches3(_types.TokenType._export, _types.TokenType._abstract, _types.TokenType._class) ||
|
|---|
| 384 | this.tokens.matches2(_types.TokenType._export, _types.TokenType.at)
|
|---|
| 385 | ) {
|
|---|
| 386 | this.processExportClass();
|
|---|
| 387 | return true;
|
|---|
| 388 | } else if (this.tokens.matches2(_types.TokenType._export, _types.TokenType.star)) {
|
|---|
| 389 | this.processExportStar();
|
|---|
| 390 | return true;
|
|---|
| 391 | } else {
|
|---|
| 392 | throw new Error("Unrecognized export syntax.");
|
|---|
| 393 | }
|
|---|
| 394 | }
|
|---|
| 395 |
|
|---|
| 396 | processAssignment() {
|
|---|
| 397 | const index = this.tokens.currentIndex();
|
|---|
| 398 | const identifierToken = this.tokens.tokens[index - 1];
|
|---|
| 399 | // If the LHS is a type identifier, this must be a declaration like `let a: b = c;`,
|
|---|
| 400 | // with `b` as the identifier, so nothing needs to be done in that case.
|
|---|
| 401 | if (identifierToken.isType || identifierToken.type !== _types.TokenType.name) {
|
|---|
| 402 | return false;
|
|---|
| 403 | }
|
|---|
| 404 | if (identifierToken.shadowsGlobal) {
|
|---|
| 405 | return false;
|
|---|
| 406 | }
|
|---|
| 407 | if (index >= 2 && this.tokens.matches1AtIndex(index - 2, _types.TokenType.dot)) {
|
|---|
| 408 | return false;
|
|---|
| 409 | }
|
|---|
| 410 | if (index >= 2 && [_types.TokenType._var, _types.TokenType._let, _types.TokenType._const].includes(this.tokens.tokens[index - 2].type)) {
|
|---|
| 411 | // Declarations don't need an extra assignment. This doesn't avoid the
|
|---|
| 412 | // assignment for comma-separated declarations, but it's still correct
|
|---|
| 413 | // since the assignment is just redundant.
|
|---|
| 414 | return false;
|
|---|
| 415 | }
|
|---|
| 416 | const assignmentSnippet = this.importProcessor.resolveExportBinding(
|
|---|
| 417 | this.tokens.identifierNameForToken(identifierToken),
|
|---|
| 418 | );
|
|---|
| 419 | if (!assignmentSnippet) {
|
|---|
| 420 | return false;
|
|---|
| 421 | }
|
|---|
| 422 | this.tokens.copyToken();
|
|---|
| 423 | this.tokens.appendCode(` ${assignmentSnippet} =`);
|
|---|
| 424 | return true;
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | /**
|
|---|
| 428 | * Process something like `a += 3`, where `a` might be an exported value.
|
|---|
| 429 | */
|
|---|
| 430 | processComplexAssignment() {
|
|---|
| 431 | const index = this.tokens.currentIndex();
|
|---|
| 432 | const identifierToken = this.tokens.tokens[index - 1];
|
|---|
| 433 | if (identifierToken.type !== _types.TokenType.name) {
|
|---|
| 434 | return false;
|
|---|
| 435 | }
|
|---|
| 436 | if (identifierToken.shadowsGlobal) {
|
|---|
| 437 | return false;
|
|---|
| 438 | }
|
|---|
| 439 | if (index >= 2 && this.tokens.matches1AtIndex(index - 2, _types.TokenType.dot)) {
|
|---|
| 440 | return false;
|
|---|
| 441 | }
|
|---|
| 442 | const assignmentSnippet = this.importProcessor.resolveExportBinding(
|
|---|
| 443 | this.tokens.identifierNameForToken(identifierToken),
|
|---|
| 444 | );
|
|---|
| 445 | if (!assignmentSnippet) {
|
|---|
| 446 | return false;
|
|---|
| 447 | }
|
|---|
| 448 | this.tokens.appendCode(` = ${assignmentSnippet}`);
|
|---|
| 449 | this.tokens.copyToken();
|
|---|
| 450 | return true;
|
|---|
| 451 | }
|
|---|
| 452 |
|
|---|
| 453 | /**
|
|---|
| 454 | * Process something like `++a`, where `a` might be an exported value.
|
|---|
| 455 | */
|
|---|
| 456 | processPreIncDec() {
|
|---|
| 457 | const index = this.tokens.currentIndex();
|
|---|
| 458 | const identifierToken = this.tokens.tokens[index + 1];
|
|---|
| 459 | if (identifierToken.type !== _types.TokenType.name) {
|
|---|
| 460 | return false;
|
|---|
| 461 | }
|
|---|
| 462 | if (identifierToken.shadowsGlobal) {
|
|---|
| 463 | return false;
|
|---|
| 464 | }
|
|---|
| 465 | // Ignore things like ++a.b and ++a[b] and ++a().b.
|
|---|
| 466 | if (
|
|---|
| 467 | index + 2 < this.tokens.tokens.length &&
|
|---|
| 468 | (this.tokens.matches1AtIndex(index + 2, _types.TokenType.dot) ||
|
|---|
| 469 | this.tokens.matches1AtIndex(index + 2, _types.TokenType.bracketL) ||
|
|---|
| 470 | this.tokens.matches1AtIndex(index + 2, _types.TokenType.parenL))
|
|---|
| 471 | ) {
|
|---|
| 472 | return false;
|
|---|
| 473 | }
|
|---|
| 474 | const identifierName = this.tokens.identifierNameForToken(identifierToken);
|
|---|
| 475 | const assignmentSnippet = this.importProcessor.resolveExportBinding(identifierName);
|
|---|
| 476 | if (!assignmentSnippet) {
|
|---|
| 477 | return false;
|
|---|
| 478 | }
|
|---|
| 479 | this.tokens.appendCode(`${assignmentSnippet} = `);
|
|---|
| 480 | this.tokens.copyToken();
|
|---|
| 481 | return true;
|
|---|
| 482 | }
|
|---|
| 483 |
|
|---|
| 484 | /**
|
|---|
| 485 | * Process something like `a++`, where `a` might be an exported value.
|
|---|
| 486 | * This starts at the `a`, not at the `++`.
|
|---|
| 487 | */
|
|---|
| 488 | processPostIncDec() {
|
|---|
| 489 | const index = this.tokens.currentIndex();
|
|---|
| 490 | const identifierToken = this.tokens.tokens[index];
|
|---|
| 491 | const operatorToken = this.tokens.tokens[index + 1];
|
|---|
| 492 | if (identifierToken.type !== _types.TokenType.name) {
|
|---|
| 493 | return false;
|
|---|
| 494 | }
|
|---|
| 495 | if (identifierToken.shadowsGlobal) {
|
|---|
| 496 | return false;
|
|---|
| 497 | }
|
|---|
| 498 | if (index >= 1 && this.tokens.matches1AtIndex(index - 1, _types.TokenType.dot)) {
|
|---|
| 499 | return false;
|
|---|
| 500 | }
|
|---|
| 501 | const identifierName = this.tokens.identifierNameForToken(identifierToken);
|
|---|
| 502 | const assignmentSnippet = this.importProcessor.resolveExportBinding(identifierName);
|
|---|
| 503 | if (!assignmentSnippet) {
|
|---|
| 504 | return false;
|
|---|
| 505 | }
|
|---|
| 506 | const operatorCode = this.tokens.rawCodeForToken(operatorToken);
|
|---|
| 507 | // We might also replace the identifier with something like exports.x, so
|
|---|
| 508 | // do that replacement here as well.
|
|---|
| 509 | const base = this.importProcessor.getIdentifierReplacement(identifierName) || identifierName;
|
|---|
| 510 | if (operatorCode === "++") {
|
|---|
| 511 | this.tokens.replaceToken(`(${base} = ${assignmentSnippet} = ${base} + 1, ${base} - 1)`);
|
|---|
| 512 | } else if (operatorCode === "--") {
|
|---|
| 513 | this.tokens.replaceToken(`(${base} = ${assignmentSnippet} = ${base} - 1, ${base} + 1)`);
|
|---|
| 514 | } else {
|
|---|
| 515 | throw new Error(`Unexpected operator: ${operatorCode}`);
|
|---|
| 516 | }
|
|---|
| 517 | this.tokens.removeToken();
|
|---|
| 518 | return true;
|
|---|
| 519 | }
|
|---|
| 520 |
|
|---|
| 521 | processExportDefault() {
|
|---|
| 522 | let exportedRuntimeValue = true;
|
|---|
| 523 | if (
|
|---|
| 524 | this.tokens.matches4(_types.TokenType._export, _types.TokenType._default, _types.TokenType._function, _types.TokenType.name) ||
|
|---|
| 525 | // export default async function
|
|---|
| 526 | (this.tokens.matches5(_types.TokenType._export, _types.TokenType._default, _types.TokenType.name, _types.TokenType._function, _types.TokenType.name) &&
|
|---|
| 527 | this.tokens.matchesContextualAtIndex(
|
|---|
| 528 | this.tokens.currentIndex() + 2,
|
|---|
| 529 | _keywords.ContextualKeyword._async,
|
|---|
| 530 | ))
|
|---|
| 531 | ) {
|
|---|
| 532 | this.tokens.removeInitialToken();
|
|---|
| 533 | this.tokens.removeToken();
|
|---|
| 534 | // Named function export case: change it to a top-level function
|
|---|
| 535 | // declaration followed by exports statement.
|
|---|
| 536 | const name = this.processNamedFunction();
|
|---|
| 537 | this.tokens.appendCode(` exports.default = ${name};`);
|
|---|
| 538 | } else if (
|
|---|
| 539 | this.tokens.matches4(_types.TokenType._export, _types.TokenType._default, _types.TokenType._class, _types.TokenType.name) ||
|
|---|
| 540 | this.tokens.matches5(_types.TokenType._export, _types.TokenType._default, _types.TokenType._abstract, _types.TokenType._class, _types.TokenType.name) ||
|
|---|
| 541 | this.tokens.matches3(_types.TokenType._export, _types.TokenType._default, _types.TokenType.at)
|
|---|
| 542 | ) {
|
|---|
| 543 | this.tokens.removeInitialToken();
|
|---|
| 544 | this.tokens.removeToken();
|
|---|
| 545 | this.copyDecorators();
|
|---|
| 546 | if (this.tokens.matches1(_types.TokenType._abstract)) {
|
|---|
| 547 | this.tokens.removeToken();
|
|---|
| 548 | }
|
|---|
| 549 | const name = this.rootTransformer.processNamedClass();
|
|---|
| 550 | this.tokens.appendCode(` exports.default = ${name};`);
|
|---|
| 551 | // After this point, this is a plain "export default E" statement.
|
|---|
| 552 | } else if (
|
|---|
| 553 | _shouldElideDefaultExport2.default.call(void 0,
|
|---|
| 554 | this.isTypeScriptTransformEnabled,
|
|---|
| 555 | this.keepUnusedImports,
|
|---|
| 556 | this.tokens,
|
|---|
| 557 | this.declarationInfo,
|
|---|
| 558 | )
|
|---|
| 559 | ) {
|
|---|
| 560 | // If the exported value is just an identifier and should be elided by TypeScript
|
|---|
| 561 | // rules, then remove it entirely. It will always have the form `export default e`,
|
|---|
| 562 | // where `e` is an identifier.
|
|---|
| 563 | exportedRuntimeValue = false;
|
|---|
| 564 | this.tokens.removeInitialToken();
|
|---|
| 565 | this.tokens.removeToken();
|
|---|
| 566 | this.tokens.removeToken();
|
|---|
| 567 | } else if (this.reactHotLoaderTransformer) {
|
|---|
| 568 | // We need to assign E to a variable. Change "export default E" to
|
|---|
| 569 | // "let _default; exports.default = _default = E"
|
|---|
| 570 | const defaultVarName = this.nameManager.claimFreeName("_default");
|
|---|
| 571 | this.tokens.replaceToken(`let ${defaultVarName}; exports.`);
|
|---|
| 572 | this.tokens.copyToken();
|
|---|
| 573 | this.tokens.appendCode(` = ${defaultVarName} =`);
|
|---|
| 574 | this.reactHotLoaderTransformer.setExtractedDefaultExportName(defaultVarName);
|
|---|
| 575 | } else {
|
|---|
| 576 | // Change "export default E" to "exports.default = E"
|
|---|
| 577 | this.tokens.replaceToken("exports.");
|
|---|
| 578 | this.tokens.copyToken();
|
|---|
| 579 | this.tokens.appendCode(" =");
|
|---|
| 580 | }
|
|---|
| 581 | if (exportedRuntimeValue) {
|
|---|
| 582 | this.hadDefaultExport = true;
|
|---|
| 583 | }
|
|---|
| 584 | }
|
|---|
| 585 |
|
|---|
| 586 | copyDecorators() {
|
|---|
| 587 | while (this.tokens.matches1(_types.TokenType.at)) {
|
|---|
| 588 | this.tokens.copyToken();
|
|---|
| 589 | if (this.tokens.matches1(_types.TokenType.parenL)) {
|
|---|
| 590 | this.tokens.copyExpectedToken(_types.TokenType.parenL);
|
|---|
| 591 | this.rootTransformer.processBalancedCode();
|
|---|
| 592 | this.tokens.copyExpectedToken(_types.TokenType.parenR);
|
|---|
| 593 | } else {
|
|---|
| 594 | this.tokens.copyExpectedToken(_types.TokenType.name);
|
|---|
| 595 | while (this.tokens.matches1(_types.TokenType.dot)) {
|
|---|
| 596 | this.tokens.copyExpectedToken(_types.TokenType.dot);
|
|---|
| 597 | this.tokens.copyExpectedToken(_types.TokenType.name);
|
|---|
| 598 | }
|
|---|
| 599 | if (this.tokens.matches1(_types.TokenType.parenL)) {
|
|---|
| 600 | this.tokens.copyExpectedToken(_types.TokenType.parenL);
|
|---|
| 601 | this.rootTransformer.processBalancedCode();
|
|---|
| 602 | this.tokens.copyExpectedToken(_types.TokenType.parenR);
|
|---|
| 603 | }
|
|---|
| 604 | }
|
|---|
| 605 | }
|
|---|
| 606 | }
|
|---|
| 607 |
|
|---|
| 608 | /**
|
|---|
| 609 | * Transform a declaration like `export var`, `export let`, or `export const`.
|
|---|
| 610 | */
|
|---|
| 611 | processExportVar() {
|
|---|
| 612 | if (this.isSimpleExportVar()) {
|
|---|
| 613 | this.processSimpleExportVar();
|
|---|
| 614 | } else {
|
|---|
| 615 | this.processComplexExportVar();
|
|---|
| 616 | }
|
|---|
| 617 | }
|
|---|
| 618 |
|
|---|
| 619 | /**
|
|---|
| 620 | * Determine if the export is of the form:
|
|---|
| 621 | * export var/let/const [varName] = [expr];
|
|---|
| 622 | * In other words, determine if function name inference might apply.
|
|---|
| 623 | */
|
|---|
| 624 | isSimpleExportVar() {
|
|---|
| 625 | let tokenIndex = this.tokens.currentIndex();
|
|---|
| 626 | // export
|
|---|
| 627 | tokenIndex++;
|
|---|
| 628 | // var/let/const
|
|---|
| 629 | tokenIndex++;
|
|---|
| 630 | if (!this.tokens.matches1AtIndex(tokenIndex, _types.TokenType.name)) {
|
|---|
| 631 | return false;
|
|---|
| 632 | }
|
|---|
| 633 | tokenIndex++;
|
|---|
| 634 | while (tokenIndex < this.tokens.tokens.length && this.tokens.tokens[tokenIndex].isType) {
|
|---|
| 635 | tokenIndex++;
|
|---|
| 636 | }
|
|---|
| 637 | if (!this.tokens.matches1AtIndex(tokenIndex, _types.TokenType.eq)) {
|
|---|
| 638 | return false;
|
|---|
| 639 | }
|
|---|
| 640 | return true;
|
|---|
| 641 | }
|
|---|
| 642 |
|
|---|
| 643 | /**
|
|---|
| 644 | * Transform an `export var` declaration initializing a single variable.
|
|---|
| 645 | *
|
|---|
| 646 | * For example, this:
|
|---|
| 647 | * export const f = () => {};
|
|---|
| 648 | * becomes this:
|
|---|
| 649 | * const f = () => {}; exports.f = f;
|
|---|
| 650 | *
|
|---|
| 651 | * The variable is unused (e.g. exports.f has the true value of the export).
|
|---|
| 652 | * We need to produce an assignment of this form so that the function will
|
|---|
| 653 | * have an inferred name of "f", which wouldn't happen in the more general
|
|---|
| 654 | * case below.
|
|---|
| 655 | */
|
|---|
| 656 | processSimpleExportVar() {
|
|---|
| 657 | // export
|
|---|
| 658 | this.tokens.removeInitialToken();
|
|---|
| 659 | // var/let/const
|
|---|
| 660 | this.tokens.copyToken();
|
|---|
| 661 | const varName = this.tokens.identifierName();
|
|---|
| 662 | // x: number -> x
|
|---|
| 663 | while (!this.tokens.matches1(_types.TokenType.eq)) {
|
|---|
| 664 | this.rootTransformer.processToken();
|
|---|
| 665 | }
|
|---|
| 666 | const endIndex = this.tokens.currentToken().rhsEndIndex;
|
|---|
| 667 | if (endIndex == null) {
|
|---|
| 668 | throw new Error("Expected = token with an end index.");
|
|---|
| 669 | }
|
|---|
| 670 | while (this.tokens.currentIndex() < endIndex) {
|
|---|
| 671 | this.rootTransformer.processToken();
|
|---|
| 672 | }
|
|---|
| 673 | this.tokens.appendCode(`; exports.${varName} = ${varName}`);
|
|---|
| 674 | }
|
|---|
| 675 |
|
|---|
| 676 | /**
|
|---|
| 677 | * Transform normal declaration exports, including handling destructuring.
|
|---|
| 678 | * For example, this:
|
|---|
| 679 | * export const {x: [a = 2, b], c} = d;
|
|---|
| 680 | * becomes this:
|
|---|
| 681 | * ({x: [exports.a = 2, exports.b], c: exports.c} = d;)
|
|---|
| 682 | */
|
|---|
| 683 | processComplexExportVar() {
|
|---|
| 684 | this.tokens.removeInitialToken();
|
|---|
| 685 | this.tokens.removeToken();
|
|---|
| 686 | const needsParens = this.tokens.matches1(_types.TokenType.braceL);
|
|---|
| 687 | if (needsParens) {
|
|---|
| 688 | this.tokens.appendCode("(");
|
|---|
| 689 | }
|
|---|
| 690 |
|
|---|
| 691 | let depth = 0;
|
|---|
| 692 | while (true) {
|
|---|
| 693 | if (
|
|---|
| 694 | this.tokens.matches1(_types.TokenType.braceL) ||
|
|---|
| 695 | this.tokens.matches1(_types.TokenType.dollarBraceL) ||
|
|---|
| 696 | this.tokens.matches1(_types.TokenType.bracketL)
|
|---|
| 697 | ) {
|
|---|
| 698 | depth++;
|
|---|
| 699 | this.tokens.copyToken();
|
|---|
| 700 | } else if (this.tokens.matches1(_types.TokenType.braceR) || this.tokens.matches1(_types.TokenType.bracketR)) {
|
|---|
| 701 | depth--;
|
|---|
| 702 | this.tokens.copyToken();
|
|---|
| 703 | } else if (
|
|---|
| 704 | depth === 0 &&
|
|---|
| 705 | !this.tokens.matches1(_types.TokenType.name) &&
|
|---|
| 706 | !this.tokens.currentToken().isType
|
|---|
| 707 | ) {
|
|---|
| 708 | break;
|
|---|
| 709 | } else if (this.tokens.matches1(_types.TokenType.eq)) {
|
|---|
| 710 | // Default values might have assignments in the RHS that we want to ignore, so skip past
|
|---|
| 711 | // them.
|
|---|
| 712 | const endIndex = this.tokens.currentToken().rhsEndIndex;
|
|---|
| 713 | if (endIndex == null) {
|
|---|
| 714 | throw new Error("Expected = token with an end index.");
|
|---|
| 715 | }
|
|---|
| 716 | while (this.tokens.currentIndex() < endIndex) {
|
|---|
| 717 | this.rootTransformer.processToken();
|
|---|
| 718 | }
|
|---|
| 719 | } else {
|
|---|
| 720 | const token = this.tokens.currentToken();
|
|---|
| 721 | if (_tokenizer.isDeclaration.call(void 0, token)) {
|
|---|
| 722 | const name = this.tokens.identifierName();
|
|---|
| 723 | let replacement = this.importProcessor.getIdentifierReplacement(name);
|
|---|
| 724 | if (replacement === null) {
|
|---|
| 725 | throw new Error(`Expected a replacement for ${name} in \`export var\` syntax.`);
|
|---|
| 726 | }
|
|---|
| 727 | if (_tokenizer.isObjectShorthandDeclaration.call(void 0, token)) {
|
|---|
| 728 | replacement = `${name}: ${replacement}`;
|
|---|
| 729 | }
|
|---|
| 730 | this.tokens.replaceToken(replacement);
|
|---|
| 731 | } else {
|
|---|
| 732 | this.rootTransformer.processToken();
|
|---|
| 733 | }
|
|---|
| 734 | }
|
|---|
| 735 | }
|
|---|
| 736 |
|
|---|
| 737 | if (needsParens) {
|
|---|
| 738 | // Seek to the end of the RHS.
|
|---|
| 739 | const endIndex = this.tokens.currentToken().rhsEndIndex;
|
|---|
| 740 | if (endIndex == null) {
|
|---|
| 741 | throw new Error("Expected = token with an end index.");
|
|---|
| 742 | }
|
|---|
| 743 | while (this.tokens.currentIndex() < endIndex) {
|
|---|
| 744 | this.rootTransformer.processToken();
|
|---|
| 745 | }
|
|---|
| 746 | this.tokens.appendCode(")");
|
|---|
| 747 | }
|
|---|
| 748 | }
|
|---|
| 749 |
|
|---|
| 750 | /**
|
|---|
| 751 | * Transform this:
|
|---|
| 752 | * export function foo() {}
|
|---|
| 753 | * into this:
|
|---|
| 754 | * function foo() {} exports.foo = foo;
|
|---|
| 755 | */
|
|---|
| 756 | processExportFunction() {
|
|---|
| 757 | this.tokens.replaceToken("");
|
|---|
| 758 | const name = this.processNamedFunction();
|
|---|
| 759 | this.tokens.appendCode(` exports.${name} = ${name};`);
|
|---|
| 760 | }
|
|---|
| 761 |
|
|---|
| 762 | /**
|
|---|
| 763 | * Skip past a function with a name and return that name.
|
|---|
| 764 | */
|
|---|
| 765 | processNamedFunction() {
|
|---|
| 766 | if (this.tokens.matches1(_types.TokenType._function)) {
|
|---|
| 767 | this.tokens.copyToken();
|
|---|
| 768 | } else if (this.tokens.matches2(_types.TokenType.name, _types.TokenType._function)) {
|
|---|
| 769 | if (!this.tokens.matchesContextual(_keywords.ContextualKeyword._async)) {
|
|---|
| 770 | throw new Error("Expected async keyword in function export.");
|
|---|
| 771 | }
|
|---|
| 772 | this.tokens.copyToken();
|
|---|
| 773 | this.tokens.copyToken();
|
|---|
| 774 | }
|
|---|
| 775 | if (this.tokens.matches1(_types.TokenType.star)) {
|
|---|
| 776 | this.tokens.copyToken();
|
|---|
| 777 | }
|
|---|
| 778 | if (!this.tokens.matches1(_types.TokenType.name)) {
|
|---|
| 779 | throw new Error("Expected identifier for exported function name.");
|
|---|
| 780 | }
|
|---|
| 781 | const name = this.tokens.identifierName();
|
|---|
| 782 | this.tokens.copyToken();
|
|---|
| 783 | if (this.tokens.currentToken().isType) {
|
|---|
| 784 | this.tokens.removeInitialToken();
|
|---|
| 785 | while (this.tokens.currentToken().isType) {
|
|---|
| 786 | this.tokens.removeToken();
|
|---|
| 787 | }
|
|---|
| 788 | }
|
|---|
| 789 | this.tokens.copyExpectedToken(_types.TokenType.parenL);
|
|---|
| 790 | this.rootTransformer.processBalancedCode();
|
|---|
| 791 | this.tokens.copyExpectedToken(_types.TokenType.parenR);
|
|---|
| 792 | this.rootTransformer.processPossibleTypeRange();
|
|---|
| 793 | this.tokens.copyExpectedToken(_types.TokenType.braceL);
|
|---|
| 794 | this.rootTransformer.processBalancedCode();
|
|---|
| 795 | this.tokens.copyExpectedToken(_types.TokenType.braceR);
|
|---|
| 796 | return name;
|
|---|
| 797 | }
|
|---|
| 798 |
|
|---|
| 799 | /**
|
|---|
| 800 | * Transform this:
|
|---|
| 801 | * export class A {}
|
|---|
| 802 | * into this:
|
|---|
| 803 | * class A {} exports.A = A;
|
|---|
| 804 | */
|
|---|
| 805 | processExportClass() {
|
|---|
| 806 | this.tokens.removeInitialToken();
|
|---|
| 807 | this.copyDecorators();
|
|---|
| 808 | if (this.tokens.matches1(_types.TokenType._abstract)) {
|
|---|
| 809 | this.tokens.removeToken();
|
|---|
| 810 | }
|
|---|
| 811 | const name = this.rootTransformer.processNamedClass();
|
|---|
| 812 | this.tokens.appendCode(` exports.${name} = ${name};`);
|
|---|
| 813 | }
|
|---|
| 814 |
|
|---|
| 815 | /**
|
|---|
| 816 | * Transform this:
|
|---|
| 817 | * export {a, b as c};
|
|---|
| 818 | * into this:
|
|---|
| 819 | * exports.a = a; exports.c = b;
|
|---|
| 820 | *
|
|---|
| 821 | * OR
|
|---|
| 822 | *
|
|---|
| 823 | * Transform this:
|
|---|
| 824 | * export {a, b as c} from './foo';
|
|---|
| 825 | * into the pre-generated Object.defineProperty code from the ImportProcessor.
|
|---|
| 826 | *
|
|---|
| 827 | * For the first case, if the TypeScript transform is enabled, we need to skip
|
|---|
| 828 | * exports that are only defined as types.
|
|---|
| 829 | */
|
|---|
| 830 | processExportBindings() {
|
|---|
| 831 | this.tokens.removeInitialToken();
|
|---|
| 832 | this.tokens.removeToken();
|
|---|
| 833 |
|
|---|
| 834 | const isReExport = _isExportFrom2.default.call(void 0, this.tokens);
|
|---|
| 835 |
|
|---|
| 836 | const exportStatements = [];
|
|---|
| 837 | while (true) {
|
|---|
| 838 | if (this.tokens.matches1(_types.TokenType.braceR)) {
|
|---|
| 839 | this.tokens.removeToken();
|
|---|
| 840 | break;
|
|---|
| 841 | }
|
|---|
| 842 |
|
|---|
| 843 | const specifierInfo = _getImportExportSpecifierInfo2.default.call(void 0, this.tokens);
|
|---|
| 844 |
|
|---|
| 845 | while (this.tokens.currentIndex() < specifierInfo.endIndex) {
|
|---|
| 846 | this.tokens.removeToken();
|
|---|
| 847 | }
|
|---|
| 848 |
|
|---|
| 849 | const shouldRemoveExport =
|
|---|
| 850 | specifierInfo.isType ||
|
|---|
| 851 | (!isReExport && this.shouldElideExportedIdentifier(specifierInfo.leftName));
|
|---|
| 852 | if (!shouldRemoveExport) {
|
|---|
| 853 | const exportedName = specifierInfo.rightName;
|
|---|
| 854 | if (exportedName === "default") {
|
|---|
| 855 | this.hadDefaultExport = true;
|
|---|
| 856 | } else {
|
|---|
| 857 | this.hadNamedExport = true;
|
|---|
| 858 | }
|
|---|
| 859 | const localName = specifierInfo.leftName;
|
|---|
| 860 | const newLocalName = this.importProcessor.getIdentifierReplacement(localName);
|
|---|
| 861 | exportStatements.push(`exports.${exportedName} = ${newLocalName || localName};`);
|
|---|
| 862 | }
|
|---|
| 863 |
|
|---|
| 864 | if (this.tokens.matches1(_types.TokenType.braceR)) {
|
|---|
| 865 | this.tokens.removeToken();
|
|---|
| 866 | break;
|
|---|
| 867 | }
|
|---|
| 868 | if (this.tokens.matches2(_types.TokenType.comma, _types.TokenType.braceR)) {
|
|---|
| 869 | this.tokens.removeToken();
|
|---|
| 870 | this.tokens.removeToken();
|
|---|
| 871 | break;
|
|---|
| 872 | } else if (this.tokens.matches1(_types.TokenType.comma)) {
|
|---|
| 873 | this.tokens.removeToken();
|
|---|
| 874 | } else {
|
|---|
| 875 | throw new Error(`Unexpected token: ${JSON.stringify(this.tokens.currentToken())}`);
|
|---|
| 876 | }
|
|---|
| 877 | }
|
|---|
| 878 |
|
|---|
| 879 | if (this.tokens.matchesContextual(_keywords.ContextualKeyword._from)) {
|
|---|
| 880 | // This is an export...from, so throw away the normal named export code
|
|---|
| 881 | // and use the Object.defineProperty code from ImportProcessor.
|
|---|
| 882 | this.tokens.removeToken();
|
|---|
| 883 | const path = this.tokens.stringValue();
|
|---|
| 884 | this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path));
|
|---|
| 885 | _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|---|
| 886 | } else {
|
|---|
| 887 | // This is a normal named export, so use that.
|
|---|
| 888 | this.tokens.appendCode(exportStatements.join(" "));
|
|---|
| 889 | }
|
|---|
| 890 |
|
|---|
| 891 | if (this.tokens.matches1(_types.TokenType.semi)) {
|
|---|
| 892 | this.tokens.removeToken();
|
|---|
| 893 | }
|
|---|
| 894 | }
|
|---|
| 895 |
|
|---|
| 896 | processExportStar() {
|
|---|
| 897 | this.tokens.removeInitialToken();
|
|---|
| 898 | while (!this.tokens.matches1(_types.TokenType.string)) {
|
|---|
| 899 | this.tokens.removeToken();
|
|---|
| 900 | }
|
|---|
| 901 | const path = this.tokens.stringValue();
|
|---|
| 902 | this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path));
|
|---|
| 903 | _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|---|
| 904 | if (this.tokens.matches1(_types.TokenType.semi)) {
|
|---|
| 905 | this.tokens.removeToken();
|
|---|
| 906 | }
|
|---|
| 907 | }
|
|---|
| 908 |
|
|---|
| 909 | shouldElideExportedIdentifier(name) {
|
|---|
| 910 | return (
|
|---|
| 911 | this.isTypeScriptTransformEnabled &&
|
|---|
| 912 | !this.keepUnusedImports &&
|
|---|
| 913 | !this.declarationInfo.valueDeclarations.has(name)
|
|---|
| 914 | );
|
|---|
| 915 | }
|
|---|
| 916 | } exports.default = CJSImportTransformer;
|
|---|