Socket
Socket
Sign inDemoInstall

sucrase

Package Overview
Dependencies
Maintainers
1
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sucrase - npm Package Compare versions

Comparing version 3.25.0 to 3.26.0

2

dist/CJSImportProcessor.js

@@ -172,3 +172,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

getFreeIdentifierForPath(path) {
getFreeIdentifierForPath(path) {
const components = path.split("/");

@@ -175,0 +175,0 @@ const lastComponent = components[components.length - 1];

@@ -172,3 +172,3 @@

getFreeIdentifierForPath(path) {
getFreeIdentifierForPath(path) {
const components = path.split("/");

@@ -175,0 +175,0 @@ const lastComponent = components[components.length - 1];

@@ -33,3 +33,3 @@ import CJSImportProcessor from "./CJSImportProcessor";

export function getVersion() {
return "3.25.0";
return "3.26.0";
}

@@ -36,0 +36,0 @@

@@ -22,4 +22,10 @@ /**

transforms: t.array("Transform"),
disableESTransforms: t.opt("boolean"),
jsxRuntime: t.opt(t.union(t.lit("classic"), t.lit("automatic"))),
production: t.opt("boolean"),
jsxImportSource: t.opt("string"),
jsxPragma: t.opt("string"),
jsxFragmentPragma: t.opt("string"),
preserveDynamicImport: t.opt("boolean"),
injectCreateRequireForImportRequire: t.opt("boolean"),
enableLegacyTypeScriptModuleInterop: t.opt("boolean"),

@@ -29,6 +35,2 @@ enableLegacyBabel5ModuleInterop: t.opt("boolean"),

filePath: t.opt("string"),
production: t.opt("boolean"),
disableESTransforms: t.opt("boolean"),
preserveDynamicImport: t.opt("boolean"),
injectCreateRequireForImportRequire: t.opt("boolean"),
});

@@ -35,0 +37,0 @@

@@ -72,4 +72,26 @@ import {createCheckers} from "ts-interface-checker";

export function validateOptions(options) {
OptionsChecker.strictCheck(options);
}

@@ -6,2 +6,3 @@ import {

IdentifierRole,
JSXRole,
match,

@@ -20,5 +21,23 @@ next,

// Reads inline JSX contents token.
/**
* Read token with JSX contents.
*
* In addition to detecting jsxTagStart and also regular tokens that might be
* part of an expression, this code detects the start and end of text ranges
* within JSX children. In order to properly count the number of children, we
* distinguish jsxText from jsxEmptyText, which is a text range that simplifies
* to the empty string after JSX whitespace trimming.
*
* It turns out that a JSX text range will simplify to the empty string if and
* only if both of these conditions hold:
* - The range consists entirely of whitespace characters (only counting space,
* tab, \r, and \n).
* - The range has at least one newline.
* This can be proven by analyzing any implementation of whitespace trimming,
* e.g. formatJSXTextLiteral in Sucrase or cleanJSXElementLiteralChild in Babel.
*/
function jsxReadToken() {
for (;;) {
let sawNewline = false;
let sawNonWhitespace = false;
while (true) {
if (state.pos >= input.length) {

@@ -30,21 +49,27 @@ unexpected("Unterminated JSX contents");

const ch = input.charCodeAt(state.pos);
switch (ch) {
case charCodes.lessThan:
case charCodes.leftCurlyBrace:
if (state.pos === state.start) {
if (ch === charCodes.lessThan) {
state.pos++;
finishToken(tt.jsxTagStart);
return;
}
getTokenFromCode(ch);
if (ch === charCodes.lessThan || ch === charCodes.leftCurlyBrace) {
if (state.pos === state.start) {
if (ch === charCodes.lessThan) {
state.pos++;
finishToken(tt.jsxTagStart);
return;
}
getTokenFromCode(ch);
return;
}
if (sawNewline && !sawNonWhitespace) {
finishToken(tt.jsxEmptyText);
} else {
finishToken(tt.jsxText);
return;
}
return;
}
default:
state.pos++;
// This is part of JSX text.
if (ch === charCodes.lineFeed) {
sawNewline = true;
} else if (ch !== charCodes.space && ch !== charCodes.carriageReturn && ch !== charCodes.tab) {
sawNonWhitespace = true;
}
state.pos++;
}

@@ -122,3 +147,3 @@ }

next();
jsxParseExpressionContainer();
parseExpression();
nextJSXTagToken();

@@ -141,6 +166,2 @@ return;

function jsxParseEmptyExpression() {
// Do nothing.
}
// Parse JSX spread child, after already processing the {

@@ -153,32 +174,6 @@ // Does not parse the closing }

// Parses JSX expression enclosed into curly brackets, after already processing the {
// Does not parse the closing }
function jsxParseExpressionContainer() {
if (match(tt.braceR)) {
jsxParseEmptyExpression();
} else {
parseExpression();
}
}
// Parses following JSX attribute name-value pair.
function jsxParseAttribute() {
if (eat(tt.braceL)) {
expect(tt.ellipsis);
parseMaybeAssign();
// }
nextJSXTagToken();
return;
}
jsxParseNamespacedName(IdentifierRole.ObjectKey);
if (match(tt.eq)) {
nextJSXTagToken();
jsxParseAttributeValue();
}
}
// Parses JSX opening tag starting after "<".
// Returns true if the tag was self-closing.
// Does not parse the last token.
function jsxParseOpeningElement() {
function jsxParseOpeningElement(initialTokenIndex) {
if (match(tt.jsxTagEnd)) {

@@ -192,4 +187,26 @@ // This is an open-fragment.

}
let hasSeenPropSpread = false;
while (!match(tt.slash) && !match(tt.jsxTagEnd) && !state.error) {
jsxParseAttribute();
if (eat(tt.braceL)) {
hasSeenPropSpread = true;
expect(tt.ellipsis);
parseMaybeAssign();
// }
nextJSXTagToken();
continue;
}
if (
hasSeenPropSpread &&
state.end - state.start === 3 &&
input.charCodeAt(state.start) === charCodes.lowercaseK &&
input.charCodeAt(state.start + 1) === charCodes.lowercaseE &&
input.charCodeAt(state.start + 2) === charCodes.lowercaseY
) {
state.tokens[initialTokenIndex].jsxRole = JSXRole.KeyAfterPropSpread;
}
jsxParseNamespacedName(IdentifierRole.ObjectKey);
if (match(tt.eq)) {
nextJSXTagToken();
jsxParseAttributeValue();
}
}

@@ -218,3 +235,6 @@ const isSelfClosing = match(tt.slash);

function jsxParseElementAt() {
const isSelfClosing = jsxParseOpeningElement();
const initialTokenIndex = state.tokens.length - 1;
state.tokens[initialTokenIndex].jsxRole = JSXRole.NoChildren;
let numExplicitChildren = 0;
const isSelfClosing = jsxParseOpeningElement(initialTokenIndex);
if (!isSelfClosing) {

@@ -229,4 +249,15 @@ nextJSXExprToken();

jsxParseClosingElement();
// Key after prop spread takes precedence over number of children,
// since it means we switch to createElement, which doesn't care
// about number of children.
if (state.tokens[initialTokenIndex].jsxRole !== JSXRole.KeyAfterPropSpread) {
if (numExplicitChildren === 1) {
state.tokens[initialTokenIndex].jsxRole = JSXRole.OneChild;
} else if (numExplicitChildren > 1) {
state.tokens[initialTokenIndex].jsxRole = JSXRole.StaticChildren;
}
}
return;
}
numExplicitChildren++;
jsxParseElementAt();

@@ -237,5 +268,10 @@ nextJSXExprToken();

case tt.jsxText:
numExplicitChildren++;
nextJSXExprToken();
break;
case tt.jsxEmptyText:
nextJSXExprToken();
break;
case tt.braceL:

@@ -246,4 +282,13 @@ next();

nextJSXExprToken();
// Spread children are a mechanism to explicitly mark children as
// static, so count it as 2 children to satisfy the "more than one
// child" condition.
numExplicitChildren += 2;
} else {
jsxParseExpressionContainer();
// If we see {}, this is an empty pseudo-expression that doesn't
// count as a child.
if (!match(tt.braceR)) {
numExplicitChildren++;
parseExpression();
}
nextJSXExprToken();

@@ -250,0 +295,0 @@ }

@@ -30,2 +30,22 @@ /* eslint max-len: 0 */

/**
* Extra information on jsxTagStart tokens, used to determine which of the three
* jsx functions are called in the automatic transform.
*/
export var JSXRole; (function (JSXRole) {
// The element is self-closing or has a body that resolves to empty. We
// shouldn't emit children at all in this case.
const NoChildren = 0; JSXRole[JSXRole["NoChildren"] = NoChildren] = "NoChildren";
// The element has a single explicit child, which might still be an arbitrary
// expression like an array. We should emit that expression as the children.
const OneChild = NoChildren + 1; JSXRole[JSXRole["OneChild"] = OneChild] = "OneChild";
// The element has at least two explicitly-specified children or has spread
// children, so child positions are assumed to be "static". We should wrap
// these children in an array.
const StaticChildren = OneChild + 1; JSXRole[JSXRole["StaticChildren"] = StaticChildren] = "StaticChildren";
// The element has a prop named "key" after a prop spread, so we should fall
// back to the createElement function.
const KeyAfterPropSpread = StaticChildren + 1; JSXRole[JSXRole["KeyAfterPropSpread"] = KeyAfterPropSpread] = "KeyAfterPropSpread";
})(JSXRole || (JSXRole = {}));
export function isDeclaration(token) {

@@ -101,2 +121,3 @@ const role = token.identifierRole;

this.identifierRole = null;
this.jsxRole = null;
this.shadowsGlobal = false;

@@ -122,2 +143,3 @@ this.isAsyncOperation = false;

// Initially false for all tokens, then may be computed in a follow-up step that does scope

@@ -124,0 +146,0 @@ // analysis.

@@ -72,58 +72,59 @@ // Generated file, do not edit! Run "yarn generate" to re-generate this file.

const jsxText = 56320; TokenType[TokenType["jsxText"] = jsxText] = "jsxText"; // jsxText
const jsxTagStart = 57856; TokenType[TokenType["jsxTagStart"] = jsxTagStart] = "jsxTagStart"; // jsxTagStart startsExpr
const jsxTagEnd = 58368; TokenType[TokenType["jsxTagEnd"] = jsxTagEnd] = "jsxTagEnd"; // jsxTagEnd
const typeParameterStart = 59904; TokenType[TokenType["typeParameterStart"] = typeParameterStart] = "typeParameterStart"; // typeParameterStart startsExpr
const nonNullAssertion = 60416; TokenType[TokenType["nonNullAssertion"] = nonNullAssertion] = "nonNullAssertion"; // nonNullAssertion
const _break = 61456; TokenType[TokenType["_break"] = _break] = "_break"; // break keyword
const _case = 62480; TokenType[TokenType["_case"] = _case] = "_case"; // case keyword
const _catch = 63504; TokenType[TokenType["_catch"] = _catch] = "_catch"; // catch keyword
const _continue = 64528; TokenType[TokenType["_continue"] = _continue] = "_continue"; // continue keyword
const _debugger = 65552; TokenType[TokenType["_debugger"] = _debugger] = "_debugger"; // debugger keyword
const _default = 66576; TokenType[TokenType["_default"] = _default] = "_default"; // default keyword
const _do = 67600; TokenType[TokenType["_do"] = _do] = "_do"; // do keyword
const _else = 68624; TokenType[TokenType["_else"] = _else] = "_else"; // else keyword
const _finally = 69648; TokenType[TokenType["_finally"] = _finally] = "_finally"; // finally keyword
const _for = 70672; TokenType[TokenType["_for"] = _for] = "_for"; // for keyword
const _function = 72208; TokenType[TokenType["_function"] = _function] = "_function"; // function keyword startsExpr
const _if = 72720; TokenType[TokenType["_if"] = _if] = "_if"; // if keyword
const _return = 73744; TokenType[TokenType["_return"] = _return] = "_return"; // return keyword
const _switch = 74768; TokenType[TokenType["_switch"] = _switch] = "_switch"; // switch keyword
const _throw = 76432; TokenType[TokenType["_throw"] = _throw] = "_throw"; // throw keyword prefix startsExpr
const _try = 76816; TokenType[TokenType["_try"] = _try] = "_try"; // try keyword
const _var = 77840; TokenType[TokenType["_var"] = _var] = "_var"; // var keyword
const _let = 78864; TokenType[TokenType["_let"] = _let] = "_let"; // let keyword
const _const = 79888; TokenType[TokenType["_const"] = _const] = "_const"; // const keyword
const _while = 80912; TokenType[TokenType["_while"] = _while] = "_while"; // while keyword
const _with = 81936; TokenType[TokenType["_with"] = _with] = "_with"; // with keyword
const _new = 83472; TokenType[TokenType["_new"] = _new] = "_new"; // new keyword startsExpr
const _this = 84496; TokenType[TokenType["_this"] = _this] = "_this"; // this keyword startsExpr
const _super = 85520; TokenType[TokenType["_super"] = _super] = "_super"; // super keyword startsExpr
const _class = 86544; TokenType[TokenType["_class"] = _class] = "_class"; // class keyword startsExpr
const _extends = 87056; TokenType[TokenType["_extends"] = _extends] = "_extends"; // extends keyword
const _export = 88080; TokenType[TokenType["_export"] = _export] = "_export"; // export keyword
const _import = 89616; TokenType[TokenType["_import"] = _import] = "_import"; // import keyword startsExpr
const _yield = 90640; TokenType[TokenType["_yield"] = _yield] = "_yield"; // yield keyword startsExpr
const _null = 91664; TokenType[TokenType["_null"] = _null] = "_null"; // null keyword startsExpr
const _true = 92688; TokenType[TokenType["_true"] = _true] = "_true"; // true keyword startsExpr
const _false = 93712; TokenType[TokenType["_false"] = _false] = "_false"; // false keyword startsExpr
const _in = 94232; TokenType[TokenType["_in"] = _in] = "_in"; // in prec:8 keyword
const _instanceof = 95256; TokenType[TokenType["_instanceof"] = _instanceof] = "_instanceof"; // instanceof prec:8 keyword
const _typeof = 96912; TokenType[TokenType["_typeof"] = _typeof] = "_typeof"; // typeof keyword prefix startsExpr
const _void = 97936; TokenType[TokenType["_void"] = _void] = "_void"; // void keyword prefix startsExpr
const _delete = 98960; TokenType[TokenType["_delete"] = _delete] = "_delete"; // delete keyword prefix startsExpr
const _async = 99856; TokenType[TokenType["_async"] = _async] = "_async"; // async keyword startsExpr
const _get = 100880; TokenType[TokenType["_get"] = _get] = "_get"; // get keyword startsExpr
const _set = 101904; TokenType[TokenType["_set"] = _set] = "_set"; // set keyword startsExpr
const _declare = 102928; TokenType[TokenType["_declare"] = _declare] = "_declare"; // declare keyword startsExpr
const _readonly = 103952; TokenType[TokenType["_readonly"] = _readonly] = "_readonly"; // readonly keyword startsExpr
const _abstract = 104976; TokenType[TokenType["_abstract"] = _abstract] = "_abstract"; // abstract keyword startsExpr
const _static = 106000; TokenType[TokenType["_static"] = _static] = "_static"; // static keyword startsExpr
const _public = 106512; TokenType[TokenType["_public"] = _public] = "_public"; // public keyword
const _private = 107536; TokenType[TokenType["_private"] = _private] = "_private"; // private keyword
const _protected = 108560; TokenType[TokenType["_protected"] = _protected] = "_protected"; // protected keyword
const _override = 109584; TokenType[TokenType["_override"] = _override] = "_override"; // override keyword
const _as = 111120; TokenType[TokenType["_as"] = _as] = "_as"; // as keyword startsExpr
const _enum = 112144; TokenType[TokenType["_enum"] = _enum] = "_enum"; // enum keyword startsExpr
const _type = 113168; TokenType[TokenType["_type"] = _type] = "_type"; // type keyword startsExpr
const _implements = 114192; TokenType[TokenType["_implements"] = _implements] = "_implements"; // implements keyword startsExpr
const jsxEmptyText = 57344; TokenType[TokenType["jsxEmptyText"] = jsxEmptyText] = "jsxEmptyText"; // jsxEmptyText
const jsxTagStart = 58880; TokenType[TokenType["jsxTagStart"] = jsxTagStart] = "jsxTagStart"; // jsxTagStart startsExpr
const jsxTagEnd = 59392; TokenType[TokenType["jsxTagEnd"] = jsxTagEnd] = "jsxTagEnd"; // jsxTagEnd
const typeParameterStart = 60928; TokenType[TokenType["typeParameterStart"] = typeParameterStart] = "typeParameterStart"; // typeParameterStart startsExpr
const nonNullAssertion = 61440; TokenType[TokenType["nonNullAssertion"] = nonNullAssertion] = "nonNullAssertion"; // nonNullAssertion
const _break = 62480; TokenType[TokenType["_break"] = _break] = "_break"; // break keyword
const _case = 63504; TokenType[TokenType["_case"] = _case] = "_case"; // case keyword
const _catch = 64528; TokenType[TokenType["_catch"] = _catch] = "_catch"; // catch keyword
const _continue = 65552; TokenType[TokenType["_continue"] = _continue] = "_continue"; // continue keyword
const _debugger = 66576; TokenType[TokenType["_debugger"] = _debugger] = "_debugger"; // debugger keyword
const _default = 67600; TokenType[TokenType["_default"] = _default] = "_default"; // default keyword
const _do = 68624; TokenType[TokenType["_do"] = _do] = "_do"; // do keyword
const _else = 69648; TokenType[TokenType["_else"] = _else] = "_else"; // else keyword
const _finally = 70672; TokenType[TokenType["_finally"] = _finally] = "_finally"; // finally keyword
const _for = 71696; TokenType[TokenType["_for"] = _for] = "_for"; // for keyword
const _function = 73232; TokenType[TokenType["_function"] = _function] = "_function"; // function keyword startsExpr
const _if = 73744; TokenType[TokenType["_if"] = _if] = "_if"; // if keyword
const _return = 74768; TokenType[TokenType["_return"] = _return] = "_return"; // return keyword
const _switch = 75792; TokenType[TokenType["_switch"] = _switch] = "_switch"; // switch keyword
const _throw = 77456; TokenType[TokenType["_throw"] = _throw] = "_throw"; // throw keyword prefix startsExpr
const _try = 77840; TokenType[TokenType["_try"] = _try] = "_try"; // try keyword
const _var = 78864; TokenType[TokenType["_var"] = _var] = "_var"; // var keyword
const _let = 79888; TokenType[TokenType["_let"] = _let] = "_let"; // let keyword
const _const = 80912; TokenType[TokenType["_const"] = _const] = "_const"; // const keyword
const _while = 81936; TokenType[TokenType["_while"] = _while] = "_while"; // while keyword
const _with = 82960; TokenType[TokenType["_with"] = _with] = "_with"; // with keyword
const _new = 84496; TokenType[TokenType["_new"] = _new] = "_new"; // new keyword startsExpr
const _this = 85520; TokenType[TokenType["_this"] = _this] = "_this"; // this keyword startsExpr
const _super = 86544; TokenType[TokenType["_super"] = _super] = "_super"; // super keyword startsExpr
const _class = 87568; TokenType[TokenType["_class"] = _class] = "_class"; // class keyword startsExpr
const _extends = 88080; TokenType[TokenType["_extends"] = _extends] = "_extends"; // extends keyword
const _export = 89104; TokenType[TokenType["_export"] = _export] = "_export"; // export keyword
const _import = 90640; TokenType[TokenType["_import"] = _import] = "_import"; // import keyword startsExpr
const _yield = 91664; TokenType[TokenType["_yield"] = _yield] = "_yield"; // yield keyword startsExpr
const _null = 92688; TokenType[TokenType["_null"] = _null] = "_null"; // null keyword startsExpr
const _true = 93712; TokenType[TokenType["_true"] = _true] = "_true"; // true keyword startsExpr
const _false = 94736; TokenType[TokenType["_false"] = _false] = "_false"; // false keyword startsExpr
const _in = 95256; TokenType[TokenType["_in"] = _in] = "_in"; // in prec:8 keyword
const _instanceof = 96280; TokenType[TokenType["_instanceof"] = _instanceof] = "_instanceof"; // instanceof prec:8 keyword
const _typeof = 97936; TokenType[TokenType["_typeof"] = _typeof] = "_typeof"; // typeof keyword prefix startsExpr
const _void = 98960; TokenType[TokenType["_void"] = _void] = "_void"; // void keyword prefix startsExpr
const _delete = 99984; TokenType[TokenType["_delete"] = _delete] = "_delete"; // delete keyword prefix startsExpr
const _async = 100880; TokenType[TokenType["_async"] = _async] = "_async"; // async keyword startsExpr
const _get = 101904; TokenType[TokenType["_get"] = _get] = "_get"; // get keyword startsExpr
const _set = 102928; TokenType[TokenType["_set"] = _set] = "_set"; // set keyword startsExpr
const _declare = 103952; TokenType[TokenType["_declare"] = _declare] = "_declare"; // declare keyword startsExpr
const _readonly = 104976; TokenType[TokenType["_readonly"] = _readonly] = "_readonly"; // readonly keyword startsExpr
const _abstract = 106000; TokenType[TokenType["_abstract"] = _abstract] = "_abstract"; // abstract keyword startsExpr
const _static = 107024; TokenType[TokenType["_static"] = _static] = "_static"; // static keyword startsExpr
const _public = 107536; TokenType[TokenType["_public"] = _public] = "_public"; // public keyword
const _private = 108560; TokenType[TokenType["_private"] = _private] = "_private"; // private keyword
const _protected = 109584; TokenType[TokenType["_protected"] = _protected] = "_protected"; // protected keyword
const _override = 110608; TokenType[TokenType["_override"] = _override] = "_override"; // override keyword
const _as = 112144; TokenType[TokenType["_as"] = _as] = "_as"; // as keyword startsExpr
const _enum = 113168; TokenType[TokenType["_enum"] = _enum] = "_enum"; // enum keyword startsExpr
const _type = 114192; TokenType[TokenType["_type"] = _type] = "_type"; // type keyword startsExpr
const _implements = 115216; TokenType[TokenType["_implements"] = _implements] = "_implements"; // implements keyword startsExpr
})(TokenType || (TokenType = {}));

@@ -244,2 +245,4 @@ export function formatTokenType(tokenType) {

return "jsxText";
case TokenType.jsxEmptyText:
return "jsxEmptyText";
case TokenType.jsxTagStart:

@@ -246,0 +249,0 @@ return "jsxTagStart";

@@ -451,3 +451,3 @@ /* eslint max-len: 0 */

if (match(tt.jsxText)) {
if (match(tt.jsxText) || match(tt.jsxEmptyText)) {
parseLiteral();

@@ -454,0 +454,0 @@ return false;

export var charCodes; (function (charCodes) {
const backSpace = 8; charCodes[charCodes["backSpace"] = backSpace] = "backSpace";
const lineFeed = 10; charCodes[charCodes["lineFeed"] = lineFeed] = "lineFeed"; // '\n'
const tab = 9; charCodes[charCodes["tab"] = tab] = "tab"; // '\t'
const carriageReturn = 13; charCodes[charCodes["carriageReturn"] = carriageReturn] = "carriageReturn"; // '\r'

@@ -5,0 +6,0 @@ const shiftOut = 14; charCodes[charCodes["shiftOut"] = shiftOut] = "shiftOut";

@@ -36,4 +36,13 @@

getResultCodeIndex() {
return this.resultCode.length;
/**
* Remove and return the code generated since the snapshot, leaving the
* current token position in-place. Unlike most TokenProcessor operations,
* this operation can result in input/output line number mismatches because
* the removed code may contain newlines, so this operation should be used
* sparingly.
*/
dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot) {
const result = this.resultCode.slice(snapshot.resultCode.length);
this.resultCode = snapshot.resultCode;
return result;
}

@@ -40,0 +49,0 @@

@@ -5,2 +5,3 @@

import XHTMLEntities from "../parser/plugins/jsx/xhtml";
import {JSXRole} from "../parser/tokenizer";
import {TokenType as tt} from "../parser/tokenizer/types";

@@ -14,6 +15,18 @@ import {charCodes} from "../parser/util/charcodes";

export default class JSXTransformer extends Transformer {
// State for calculating the line number of each JSX tag in development.
__init() {this.lastLineNumber = 1}
__init2() {this.lastIndex = 0}
// In development, variable name holding the name of the current file.
__init3() {this.filenameVarName = null}
// Mapping of claimed names for imports in the automatic transform, e,g.
// {jsx: "_jsx"}. This determines which imports to generate in the prefix.
__init4() {this.esmAutomaticImportNameResolutions = {}}
// When automatically adding imports in CJS mode, we store the variable name
// holding the imported CJS module so we can require it in the prefix.
__init5() {this.cjsAutomaticModuleNameResolutions = {}}

@@ -27,4 +40,6 @@ constructor(

) {
super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.importProcessor = importProcessor;this.nameManager = nameManager;this.options = options;JSXTransformer.prototype.__init.call(this);JSXTransformer.prototype.__init2.call(this);JSXTransformer.prototype.__init3.call(this);;
super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.importProcessor = importProcessor;this.nameManager = nameManager;this.options = options;JSXTransformer.prototype.__init.call(this);JSXTransformer.prototype.__init2.call(this);JSXTransformer.prototype.__init3.call(this);JSXTransformer.prototype.__init4.call(this);JSXTransformer.prototype.__init5.call(this);;
this.jsxPragmaInfo = getJSXPragmaInfo(options);
this.isAutomaticRuntime = options.jsxRuntime === "automatic";
this.jsxImportSource = options.jsxImportSource || "react";
}

@@ -41,12 +56,52 @@

getPrefixCode() {
let prefix = "";
if (this.filenameVarName) {
return `const ${this.filenameVarName} = ${JSON.stringify(this.options.filePath || "")};`;
prefix += `const ${this.filenameVarName} = ${JSON.stringify(this.options.filePath || "")};`;
}
if (this.isAutomaticRuntime) {
if (this.importProcessor) {
// CJS mode: emit require statements for all modules that were referenced.
for (const [path, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
prefix += `var ${resolvedName} = require("${path}");`;
}
} else {
// ESM mode: consolidate and emit import statements for referenced names.
const {createElement: createElementResolution, ...otherResolutions} =
this.esmAutomaticImportNameResolutions;
if (createElementResolution) {
prefix += `import {createElement as ${createElementResolution}} from "${this.jsxImportSource}";`;
}
const importSpecifiers = Object.entries(otherResolutions)
.map(([name, resolvedName]) => `${name} as ${resolvedName}`)
.join(", ");
if (importSpecifiers) {
const importPath =
this.jsxImportSource + (this.options.production ? "/jsx-runtime" : "/jsx-dev-runtime");
prefix += `import {${importSpecifiers}} from "${importPath}";`;
}
}
}
return prefix;
}
processJSXTag() {
const {jsxRole, start} = this.tokens.currentToken();
// Calculate line number information at the very start (if in development
// mode) so that the information is guaranteed to be queried in token order.
const elementLocationCode = this.options.production ? null : this.getElementLocationCode(start);
if (this.isAutomaticRuntime && jsxRole !== JSXRole.KeyAfterPropSpread) {
this.transformTagToJSXFunc(elementLocationCode, jsxRole);
} else {
return "";
this.transformTagToCreateElement(elementLocationCode);
}
}
getElementLocationCode(firstTokenStart) {
const lineNumber = this.getLineNumberForIndex(firstTokenStart);
return `lineNumber: ${lineNumber}`;
}
/**
* Lazily calculate line numbers to avoid unneeded work. We assume this is always called in
* increasing order by index.
* Get the line number for this source position. This is calculated lazily and
* must be called in increasing order by index.
*/

@@ -64,72 +119,206 @@ getLineNumberForIndex(index) {

getFilenameVarName() {
if (!this.filenameVarName) {
this.filenameVarName = this.nameManager.claimFreeName("_jsxFileName");
/**
* Convert the current JSX element to a call to jsx, jsxs, or jsxDEV. This is
* the primary transformation for the automatic transform.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* jsxs('div', {a: 1, children: ["Hello", x]}, 2)
*/
transformTagToJSXFunc(elementLocationCode, jsxRole) {
const isStatic = jsxRole === JSXRole.StaticChildren;
// First tag is always jsxTagStart.
this.tokens.replaceToken(this.getJSXFuncInvocationCode(isStatic));
let keyCode = null;
if (this.tokens.matches1(tt.jsxTagEnd)) {
// Fragment syntax.
this.tokens.replaceToken(`${this.getFragmentCode()}, {`);
this.processAutomaticChildrenAndEndProps(jsxRole);
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.tokens.appendCode(", {");
keyCode = this.processProps(true);
if (this.tokens.matches2(tt.slash, tt.jsxTagEnd)) {
// Self-closing tag, no children to add, so close the props.
this.tokens.appendCode("}");
} else if (this.tokens.matches1(tt.jsxTagEnd)) {
// Tag with children.
this.tokens.removeToken();
this.processAutomaticChildrenAndEndProps(jsxRole);
} else {
throw new Error("Expected either /> or > at the end of the tag.");
}
// If a key was present, move it to its own arg. Note that moving code
// like this will cause line numbers to get out of sync within the JSX
// element if the key expression has a newline in it. This is unfortunate,
// but hopefully should be rare.
if (keyCode) {
this.tokens.appendCode(`, ${keyCode}`);
}
}
return this.filenameVarName;
if (!this.options.production) {
// If the key wasn't already added, add it now so we can correctly set
// positional args for jsxDEV.
if (keyCode === null) {
this.tokens.appendCode(", void 0");
}
this.tokens.appendCode(`, ${isStatic}, ${this.getDevSource(elementLocationCode)}, this`);
}
// We're at the close-tag or the end of a self-closing tag, so remove
// everything else and close the function call.
this.tokens.removeInitialToken();
while (!this.tokens.matches1(tt.jsxTagEnd)) {
this.tokens.removeToken();
}
this.tokens.replaceToken(")");
}
processProps(firstTokenStart) {
const lineNumber = this.getLineNumberForIndex(firstTokenStart);
const devProps = this.options.production
? ""
: `__self: this, __source: {fileName: ${this.getFilenameVarName()}, lineNumber: ${lineNumber}}`;
if (!this.tokens.matches1(tt.jsxName) && !this.tokens.matches1(tt.braceL)) {
if (devProps) {
this.tokens.appendCode(`, {${devProps}}`);
/**
* Convert the current JSX element to a createElement call. In the classic
* runtime, this is the only case. In the automatic runtime, this is called
* as a fallback in some situations.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* React.createElement('div', {a: 1, key: 2}, "Hello", x)
*/
transformTagToCreateElement(elementLocationCode) {
// First tag is always jsxTagStart.
this.tokens.replaceToken(this.getCreateElementInvocationCode());
if (this.tokens.matches1(tt.jsxTagEnd)) {
// Fragment syntax.
this.tokens.replaceToken(`${this.getFragmentCode()}, null`);
this.processChildren(true);
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.processPropsObjectWithDevInfo(elementLocationCode);
if (this.tokens.matches2(tt.slash, tt.jsxTagEnd)) {
// Self-closing tag; no children to process.
} else if (this.tokens.matches1(tt.jsxTagEnd)) {
// Tag with children and a close-tag; process the children as args.
this.tokens.removeToken();
this.processChildren(true);
} else {
this.tokens.appendCode(`, null`);
throw new Error("Expected either /> or > at the end of the tag.");
}
return;
}
this.tokens.appendCode(`, {`);
while (true) {
if (this.tokens.matches2(tt.jsxName, tt.eq)) {
this.processPropKeyName();
this.tokens.replaceToken(": ");
if (this.tokens.matches1(tt.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else if (this.tokens.matches1(tt.jsxTagStart)) {
this.processJSXTag();
} else {
this.processStringPropValue();
}
} else if (this.tokens.matches1(tt.jsxName)) {
this.processPropKeyName();
this.tokens.appendCode(": true");
} else if (this.tokens.matches1(tt.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
// We're at the close-tag or the end of a self-closing tag, so remove
// everything else and close the function call.
this.tokens.removeInitialToken();
while (!this.tokens.matches1(tt.jsxTagEnd)) {
this.tokens.removeToken();
}
this.tokens.replaceToken(")");
}
/**
* Get the code for the relevant function for this context: jsx, jsxs,
* or jsxDEV. The following open-paren is included as well.
*
* These functions are only used for the automatic runtime, so they are always
* auto-imported, but the auto-import will be either CJS or ESM based on the
* target module format.
*/
getJSXFuncInvocationCode(isStatic) {
if (this.options.production) {
if (isStatic) {
return this.claimAutoImportedFuncInvocation("jsxs", "/jsx-runtime");
} else {
break;
return this.claimAutoImportedFuncInvocation("jsx", "/jsx-runtime");
}
this.tokens.appendCode(",");
} else {
return this.claimAutoImportedFuncInvocation("jsxDEV", "/jsx-dev-runtime");
}
if (devProps) {
this.tokens.appendCode(` ${devProps}}`);
}
/**
* Return the code to use for the createElement function, e.g.
* `React.createElement`, including the following open-paren.
*
* This is the main function to use for the classic runtime. For the
* automatic runtime, this function is used as a fallback function to
* preserve behavior when there is a prop spread followed by an explicit
* key. In that automatic runtime case, the function should be automatically
* imported.
*/
getCreateElementInvocationCode() {
if (this.isAutomaticRuntime) {
return this.claimAutoImportedFuncInvocation("createElement", "");
} else {
this.tokens.appendCode("}");
const {jsxPragmaInfo} = this;
const resolvedPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.base) || jsxPragmaInfo.base
: jsxPragmaInfo.base;
return `${resolvedPragmaBaseName}${jsxPragmaInfo.suffix}(`;
}
}
processPropKeyName() {
const keyName = this.tokens.identifierName();
if (keyName.includes("-")) {
this.tokens.replaceToken(`'${keyName}'`);
/**
* Return the code to use as the component when compiling a shorthand
* fragment, e.g. `React.Fragment`.
*
* This may be called from either the classic or automatic runtime, and
* the value should be auto-imported for the automatic runtime.
*/
getFragmentCode() {
if (this.isAutomaticRuntime) {
return this.claimAutoImportedName(
"Fragment",
this.options.production ? "/jsx-runtime" : "/jsx-dev-runtime",
);
} else {
this.tokens.copyToken();
const {jsxPragmaInfo} = this;
const resolvedFragmentPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.fragmentBase) ||
jsxPragmaInfo.fragmentBase
: jsxPragmaInfo.fragmentBase;
return resolvedFragmentPragmaBaseName + jsxPragmaInfo.fragmentSuffix;
}
}
processStringPropValue() {
const token = this.tokens.currentToken();
const valueCode = this.tokens.code.slice(token.start + 1, token.end - 1);
const replacementCode = formatJSXTextReplacement(valueCode);
const literalCode = formatJSXStringValueLiteral(valueCode);
this.tokens.replaceToken(literalCode + replacementCode);
/**
* Return code that invokes the given function.
*
* When the imports transform is enabled, use the CJSImportTransformer
* strategy of using `.call(void 0, ...` to avoid passing a `this` value in a
* situation that would otherwise look like a method call.
*/
claimAutoImportedFuncInvocation(funcName, importPathSuffix) {
const funcCode = this.claimAutoImportedName(funcName, importPathSuffix);
if (this.importProcessor) {
return `${funcCode}.call(void 0, `;
} else {
return `${funcCode}(`;
}
}
claimAutoImportedName(funcName, importPathSuffix) {
if (this.importProcessor) {
// CJS mode: claim a name for the module and mark it for import.
const path = this.jsxImportSource + importPathSuffix;
if (!this.cjsAutomaticModuleNameResolutions[path]) {
this.cjsAutomaticModuleNameResolutions[path] =
this.importProcessor.getFreeIdentifierForPath(path);
}
return `${this.cjsAutomaticModuleNameResolutions[path]}.${funcName}`;
} else {
// ESM mode: claim a name for this function and add it to the names that
// should be auto-imported when the prefix is generated.
if (!this.esmAutomaticImportNameResolutions[funcName]) {
this.esmAutomaticImportNameResolutions[funcName] = this.nameManager.claimFreeName(
`_${funcName}`,
);
}
return this.esmAutomaticImportNameResolutions[funcName];
}
}
/**

@@ -167,4 +356,147 @@ * Process the first part of a tag, before any props.

processChildren() {
/**
* Starting at the beginning of the props, add the props argument to
* React.createElement, including the comma before it.
*/
processPropsObjectWithDevInfo(elementLocationCode) {
const devProps = this.options.production
? ""
: `__self: this, __source: ${this.getDevSource(elementLocationCode)}`;
if (!this.tokens.matches1(tt.jsxName) && !this.tokens.matches1(tt.braceL)) {
if (devProps) {
this.tokens.appendCode(`, {${devProps}}`);
} else {
this.tokens.appendCode(`, null`);
}
return;
}
this.tokens.appendCode(`, {`);
this.processProps(false);
if (devProps) {
this.tokens.appendCode(` ${devProps}}`);
} else {
this.tokens.appendCode("}");
}
}
/**
* Transform the core part of the props, assuming that a { has already been
* inserted before us and that a } will be inserted after us.
*
* If extractKeyCode is true (i.e. when using any jsx... function), any prop
* named "key" has its code captured and returned rather than being emitted to
* the output code. This shifts line numbers, and emitting the code later will
* correct line numbers again. If no key is found or if extractKeyCode is
* false, this function returns null.
*/
processProps(extractKeyCode) {
let keyCode = null;
while (true) {
if (this.tokens.matches2(tt.jsxName, tt.eq)) {
// This is a regular key={value} or key="value" prop.
const propName = this.tokens.identifierName();
if (extractKeyCode && propName === "key") {
if (keyCode !== null) {
// The props list has multiple keys. Different implementations are
// inconsistent about what to do here: as of this writing, Babel and
// swc keep the *last* key and completely remove the rest, while
// TypeScript uses the *first* key and leaves the others as regular
// props. The React team collaborated with Babel on the
// implementation of this behavior, so presumably the Babel behavior
// is the one to use.
// Since we won't ever be emitting the previous key code, we need to
// at least emit its newlines here so that the line numbers match up
// in the long run.
this.tokens.appendCode(keyCode.replace(/[^\n]/g, ""));
}
// key
this.tokens.removeToken();
// =
this.tokens.removeToken();
const snapshot = this.tokens.snapshot();
this.processPropValue();
keyCode = this.tokens.dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot);
// Don't add a comma
continue;
} else {
this.processPropName(propName);
this.tokens.replaceToken(": ");
this.processPropValue();
}
} else if (this.tokens.matches1(tt.jsxName)) {
// This is a shorthand prop like <input disabled />.
const propName = this.tokens.identifierName();
this.processPropName(propName);
this.tokens.appendCode(": true");
} else if (this.tokens.matches1(tt.braceL)) {
// This is prop spread, like <div {...getProps()}>, which we can pass
// through fairly directly as an object spread.
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else {
break;
}
this.tokens.appendCode(",");
}
return keyCode;
}
processPropName(propName) {
if (propName.includes("-")) {
this.tokens.replaceToken(`'${propName}'`);
} else {
this.tokens.copyToken();
}
}
processPropValue() {
if (this.tokens.matches1(tt.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else if (this.tokens.matches1(tt.jsxTagStart)) {
this.processJSXTag();
} else {
this.processStringPropValue();
}
}
processStringPropValue() {
const token = this.tokens.currentToken();
const valueCode = this.tokens.code.slice(token.start + 1, token.end - 1);
const replacementCode = formatJSXTextReplacement(valueCode);
const literalCode = formatJSXStringValueLiteral(valueCode);
this.tokens.replaceToken(literalCode + replacementCode);
}
/**
* Starting in the middle of the props object literal, produce an additional
* prop for the children and close the object literal.
*/
processAutomaticChildrenAndEndProps(jsxRole) {
if (jsxRole === JSXRole.StaticChildren) {
this.tokens.appendCode(" children: [");
this.processChildren(false);
this.tokens.appendCode("]}");
} else {
// The parser information tells us whether we will see a real child or if
// all remaining children (if any) will resolve to empty. If there are no
// non-empty children, don't emit a children prop at all, but still
// process children so that we properly transform the code into nothing.
if (jsxRole === JSXRole.OneChild) {
this.tokens.appendCode(" children: ");
}
this.processChildren(false);
this.tokens.appendCode("}");
}
}
/**
* Transform children into a comma-separated list, which will be either
* arguments to createElement or array elements of a children prop.
*/
processChildren(needsInitialComma) {
let needsComma = needsInitialComma;
while (true) {
if (this.tokens.matches2(tt.jsxTagStart, tt.slash)) {

@@ -174,2 +506,3 @@ // Closing tag, so no more children.

}
let didEmitElement = false;
if (this.tokens.matches1(tt.braceL)) {

@@ -183,19 +516,30 @@ if (this.tokens.matches2(tt.braceL, tt.braceR)) {

// Interpolated expression.
this.tokens.replaceToken(", ");
this.tokens.replaceToken(needsComma ? ", " : "");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
didEmitElement = true;
}
} else if (this.tokens.matches1(tt.jsxTagStart)) {
// Child JSX element
this.tokens.appendCode(", ");
this.tokens.appendCode(needsComma ? ", " : "");
this.processJSXTag();
} else if (this.tokens.matches1(tt.jsxText)) {
this.processChildTextElement();
didEmitElement = true;
} else if (this.tokens.matches1(tt.jsxText) || this.tokens.matches1(tt.jsxEmptyText)) {
didEmitElement = this.processChildTextElement(needsComma);
} else {
throw new Error("Unexpected token when processing JSX children.");
}
if (didEmitElement) {
needsComma = true;
}
}
}
processChildTextElement() {
/**
* Turn a JSX text element into a string literal, or nothing at all if the JSX
* text resolves to the empty string.
*
* Returns true if a string literal is emitted, false otherwise.
*/
processChildTextElement(needsComma) {
const token = this.tokens.currentToken();

@@ -207,52 +551,18 @@ const valueCode = this.tokens.code.slice(token.start, token.end);

this.tokens.replaceToken(replacementCode);
return false;
} else {
this.tokens.replaceToken(`, ${literalCode}${replacementCode}`);
this.tokens.replaceToken(`${needsComma ? ", " : ""}${literalCode}${replacementCode}`);
return true;
}
}
processJSXTag() {
const {jsxPragmaInfo} = this;
const resolvedPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.base) || jsxPragmaInfo.base
: jsxPragmaInfo.base;
const firstTokenStart = this.tokens.currentToken().start;
// First tag is always jsxTagStart.
this.tokens.replaceToken(`${resolvedPragmaBaseName}${jsxPragmaInfo.suffix}(`);
getDevSource(elementLocationCode) {
return `{fileName: ${this.getFilenameVarName()}, ${elementLocationCode}}`;
}
if (this.tokens.matches1(tt.jsxTagEnd)) {
// Fragment syntax.
const resolvedFragmentPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.fragmentBase) ||
jsxPragmaInfo.fragmentBase
: jsxPragmaInfo.fragmentBase;
this.tokens.replaceToken(
`${resolvedFragmentPragmaBaseName}${jsxPragmaInfo.fragmentSuffix}, null`,
);
// Tag with children.
this.processChildren();
while (!this.tokens.matches1(tt.jsxTagEnd)) {
this.tokens.replaceToken("");
}
this.tokens.replaceToken(")");
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.processProps(firstTokenStart);
if (this.tokens.matches2(tt.slash, tt.jsxTagEnd)) {
// Self-closing tag.
this.tokens.replaceToken("");
this.tokens.replaceToken(")");
} else if (this.tokens.matches1(tt.jsxTagEnd)) {
this.tokens.replaceToken("");
// Tag with children.
this.processChildren();
while (!this.tokens.matches1(tt.jsxTagEnd)) {
this.tokens.replaceToken("");
}
this.tokens.replaceToken(")");
} else {
throw new Error("Expected either /> or > at the end of the tag.");
}
getFilenameVarName() {
if (!this.filenameVarName) {
this.filenameVarName = this.nameManager.claimFreeName("_jsxFileName");
}
return this.filenameVarName;
}

@@ -259,0 +569,0 @@ }

@@ -33,3 +33,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _CJSImportProcessor = require('./CJSImportProcessor'); var _CJSImportProcessor2 = _interopRequireDefault(_CJSImportProcessor);

function getVersion() {
return "3.25.0";
return "3.26.0";
} exports.getVersion = getVersion;

@@ -36,0 +36,0 @@

@@ -22,4 +22,10 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }/**

transforms: t.array("Transform"),
disableESTransforms: t.opt("boolean"),
jsxRuntime: t.opt(t.union(t.lit("classic"), t.lit("automatic"))),
production: t.opt("boolean"),
jsxImportSource: t.opt("string"),
jsxPragma: t.opt("string"),
jsxFragmentPragma: t.opt("string"),
preserveDynamicImport: t.opt("boolean"),
injectCreateRequireForImportRequire: t.opt("boolean"),
enableLegacyTypeScriptModuleInterop: t.opt("boolean"),

@@ -29,6 +35,2 @@ enableLegacyBabel5ModuleInterop: t.opt("boolean"),

filePath: t.opt("string"),
production: t.opt("boolean"),
disableESTransforms: t.opt("boolean"),
preserveDynamicImport: t.opt("boolean"),
injectCreateRequireForImportRequire: t.opt("boolean"),
}); exports.Options = Options;

@@ -35,0 +37,0 @@

@@ -72,4 +72,26 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _tsinterfacechecker = require('ts-interface-checker');

function validateOptions(options) {
OptionsChecker.strictCheck(options);
} exports.validateOptions = validateOptions;

@@ -10,2 +10,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});

var _index = require('../../tokenizer/index');

@@ -20,5 +21,23 @@ var _types = require('../../tokenizer/types');

// Reads inline JSX contents token.
/**
* Read token with JSX contents.
*
* In addition to detecting jsxTagStart and also regular tokens that might be
* part of an expression, this code detects the start and end of text ranges
* within JSX children. In order to properly count the number of children, we
* distinguish jsxText from jsxEmptyText, which is a text range that simplifies
* to the empty string after JSX whitespace trimming.
*
* It turns out that a JSX text range will simplify to the empty string if and
* only if both of these conditions hold:
* - The range consists entirely of whitespace characters (only counting space,
* tab, \r, and \n).
* - The range has at least one newline.
* This can be proven by analyzing any implementation of whitespace trimming,
* e.g. formatJSXTextLiteral in Sucrase or cleanJSXElementLiteralChild in Babel.
*/
function jsxReadToken() {
for (;;) {
let sawNewline = false;
let sawNonWhitespace = false;
while (true) {
if (_base.state.pos >= _base.input.length) {

@@ -30,21 +49,27 @@ _util.unexpected.call(void 0, "Unterminated JSX contents");

const ch = _base.input.charCodeAt(_base.state.pos);
switch (ch) {
case _charcodes.charCodes.lessThan:
case _charcodes.charCodes.leftCurlyBrace:
if (_base.state.pos === _base.state.start) {
if (ch === _charcodes.charCodes.lessThan) {
_base.state.pos++;
_index.finishToken.call(void 0, _types.TokenType.jsxTagStart);
return;
}
_index.getTokenFromCode.call(void 0, ch);
if (ch === _charcodes.charCodes.lessThan || ch === _charcodes.charCodes.leftCurlyBrace) {
if (_base.state.pos === _base.state.start) {
if (ch === _charcodes.charCodes.lessThan) {
_base.state.pos++;
_index.finishToken.call(void 0, _types.TokenType.jsxTagStart);
return;
}
_index.getTokenFromCode.call(void 0, ch);
return;
}
if (sawNewline && !sawNonWhitespace) {
_index.finishToken.call(void 0, _types.TokenType.jsxEmptyText);
} else {
_index.finishToken.call(void 0, _types.TokenType.jsxText);
return;
}
return;
}
default:
_base.state.pos++;
// This is part of JSX text.
if (ch === _charcodes.charCodes.lineFeed) {
sawNewline = true;
} else if (ch !== _charcodes.charCodes.space && ch !== _charcodes.charCodes.carriageReturn && ch !== _charcodes.charCodes.tab) {
sawNonWhitespace = true;
}
_base.state.pos++;
}

@@ -122,3 +147,3 @@ }

_index.next.call(void 0, );
jsxParseExpressionContainer();
_expression.parseExpression.call(void 0, );
nextJSXTagToken();

@@ -141,6 +166,2 @@ return;

function jsxParseEmptyExpression() {
// Do nothing.
}
// Parse JSX spread child, after already processing the {

@@ -153,32 +174,6 @@ // Does not parse the closing }

// Parses JSX expression enclosed into curly brackets, after already processing the {
// Does not parse the closing }
function jsxParseExpressionContainer() {
if (_index.match.call(void 0, _types.TokenType.braceR)) {
jsxParseEmptyExpression();
} else {
_expression.parseExpression.call(void 0, );
}
}
// Parses following JSX attribute name-value pair.
function jsxParseAttribute() {
if (_index.eat.call(void 0, _types.TokenType.braceL)) {
_util.expect.call(void 0, _types.TokenType.ellipsis);
_expression.parseMaybeAssign.call(void 0, );
// }
nextJSXTagToken();
return;
}
jsxParseNamespacedName(_index.IdentifierRole.ObjectKey);
if (_index.match.call(void 0, _types.TokenType.eq)) {
nextJSXTagToken();
jsxParseAttributeValue();
}
}
// Parses JSX opening tag starting after "<".
// Returns true if the tag was self-closing.
// Does not parse the last token.
function jsxParseOpeningElement() {
function jsxParseOpeningElement(initialTokenIndex) {
if (_index.match.call(void 0, _types.TokenType.jsxTagEnd)) {

@@ -192,4 +187,26 @@ // This is an open-fragment.

}
let hasSeenPropSpread = false;
while (!_index.match.call(void 0, _types.TokenType.slash) && !_index.match.call(void 0, _types.TokenType.jsxTagEnd) && !_base.state.error) {
jsxParseAttribute();
if (_index.eat.call(void 0, _types.TokenType.braceL)) {
hasSeenPropSpread = true;
_util.expect.call(void 0, _types.TokenType.ellipsis);
_expression.parseMaybeAssign.call(void 0, );
// }
nextJSXTagToken();
continue;
}
if (
hasSeenPropSpread &&
_base.state.end - _base.state.start === 3 &&
_base.input.charCodeAt(_base.state.start) === _charcodes.charCodes.lowercaseK &&
_base.input.charCodeAt(_base.state.start + 1) === _charcodes.charCodes.lowercaseE &&
_base.input.charCodeAt(_base.state.start + 2) === _charcodes.charCodes.lowercaseY
) {
_base.state.tokens[initialTokenIndex].jsxRole = _index.JSXRole.KeyAfterPropSpread;
}
jsxParseNamespacedName(_index.IdentifierRole.ObjectKey);
if (_index.match.call(void 0, _types.TokenType.eq)) {
nextJSXTagToken();
jsxParseAttributeValue();
}
}

@@ -218,3 +235,6 @@ const isSelfClosing = _index.match.call(void 0, _types.TokenType.slash);

function jsxParseElementAt() {
const isSelfClosing = jsxParseOpeningElement();
const initialTokenIndex = _base.state.tokens.length - 1;
_base.state.tokens[initialTokenIndex].jsxRole = _index.JSXRole.NoChildren;
let numExplicitChildren = 0;
const isSelfClosing = jsxParseOpeningElement(initialTokenIndex);
if (!isSelfClosing) {

@@ -229,4 +249,15 @@ nextJSXExprToken();

jsxParseClosingElement();
// Key after prop spread takes precedence over number of children,
// since it means we switch to createElement, which doesn't care
// about number of children.
if (_base.state.tokens[initialTokenIndex].jsxRole !== _index.JSXRole.KeyAfterPropSpread) {
if (numExplicitChildren === 1) {
_base.state.tokens[initialTokenIndex].jsxRole = _index.JSXRole.OneChild;
} else if (numExplicitChildren > 1) {
_base.state.tokens[initialTokenIndex].jsxRole = _index.JSXRole.StaticChildren;
}
}
return;
}
numExplicitChildren++;
jsxParseElementAt();

@@ -237,5 +268,10 @@ nextJSXExprToken();

case _types.TokenType.jsxText:
numExplicitChildren++;
nextJSXExprToken();
break;
case _types.TokenType.jsxEmptyText:
nextJSXExprToken();
break;
case _types.TokenType.braceL:

@@ -246,4 +282,13 @@ _index.next.call(void 0, );

nextJSXExprToken();
// Spread children are a mechanism to explicitly mark children as
// static, so count it as 2 children to satisfy the "more than one
// child" condition.
numExplicitChildren += 2;
} else {
jsxParseExpressionContainer();
// If we see {}, this is an empty pseudo-expression that doesn't
// count as a child.
if (!_index.match.call(void 0, _types.TokenType.braceR)) {
numExplicitChildren++;
_expression.parseExpression.call(void 0, );
}
nextJSXExprToken();

@@ -250,0 +295,0 @@ }

@@ -30,2 +30,22 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }/* eslint max-len: 0 */

/**
* Extra information on jsxTagStart tokens, used to determine which of the three
* jsx functions are called in the automatic transform.
*/
var JSXRole; (function (JSXRole) {
// The element is self-closing or has a body that resolves to empty. We
// shouldn't emit children at all in this case.
const NoChildren = 0; JSXRole[JSXRole["NoChildren"] = NoChildren] = "NoChildren";
// The element has a single explicit child, which might still be an arbitrary
// expression like an array. We should emit that expression as the children.
const OneChild = NoChildren + 1; JSXRole[JSXRole["OneChild"] = OneChild] = "OneChild";
// The element has at least two explicitly-specified children or has spread
// children, so child positions are assumed to be "static". We should wrap
// these children in an array.
const StaticChildren = OneChild + 1; JSXRole[JSXRole["StaticChildren"] = StaticChildren] = "StaticChildren";
// The element has a prop named "key" after a prop spread, so we should fall
// back to the createElement function.
const KeyAfterPropSpread = StaticChildren + 1; JSXRole[JSXRole["KeyAfterPropSpread"] = KeyAfterPropSpread] = "KeyAfterPropSpread";
})(JSXRole || (exports.JSXRole = JSXRole = {}));
function isDeclaration(token) {

@@ -101,2 +121,3 @@ const role = token.identifierRole;

this.identifierRole = null;
this.jsxRole = null;
this.shadowsGlobal = false;

@@ -122,2 +143,3 @@ this.isAsyncOperation = false;

// Initially false for all tokens, then may be computed in a follow-up step that does scope

@@ -124,0 +146,0 @@ // analysis.

@@ -72,58 +72,59 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// Generated file, do not edit! Run "yarn generate" to re-generate this file.

const jsxText = 56320; TokenType[TokenType["jsxText"] = jsxText] = "jsxText"; // jsxText
const jsxTagStart = 57856; TokenType[TokenType["jsxTagStart"] = jsxTagStart] = "jsxTagStart"; // jsxTagStart startsExpr
const jsxTagEnd = 58368; TokenType[TokenType["jsxTagEnd"] = jsxTagEnd] = "jsxTagEnd"; // jsxTagEnd
const typeParameterStart = 59904; TokenType[TokenType["typeParameterStart"] = typeParameterStart] = "typeParameterStart"; // typeParameterStart startsExpr
const nonNullAssertion = 60416; TokenType[TokenType["nonNullAssertion"] = nonNullAssertion] = "nonNullAssertion"; // nonNullAssertion
const _break = 61456; TokenType[TokenType["_break"] = _break] = "_break"; // break keyword
const _case = 62480; TokenType[TokenType["_case"] = _case] = "_case"; // case keyword
const _catch = 63504; TokenType[TokenType["_catch"] = _catch] = "_catch"; // catch keyword
const _continue = 64528; TokenType[TokenType["_continue"] = _continue] = "_continue"; // continue keyword
const _debugger = 65552; TokenType[TokenType["_debugger"] = _debugger] = "_debugger"; // debugger keyword
const _default = 66576; TokenType[TokenType["_default"] = _default] = "_default"; // default keyword
const _do = 67600; TokenType[TokenType["_do"] = _do] = "_do"; // do keyword
const _else = 68624; TokenType[TokenType["_else"] = _else] = "_else"; // else keyword
const _finally = 69648; TokenType[TokenType["_finally"] = _finally] = "_finally"; // finally keyword
const _for = 70672; TokenType[TokenType["_for"] = _for] = "_for"; // for keyword
const _function = 72208; TokenType[TokenType["_function"] = _function] = "_function"; // function keyword startsExpr
const _if = 72720; TokenType[TokenType["_if"] = _if] = "_if"; // if keyword
const _return = 73744; TokenType[TokenType["_return"] = _return] = "_return"; // return keyword
const _switch = 74768; TokenType[TokenType["_switch"] = _switch] = "_switch"; // switch keyword
const _throw = 76432; TokenType[TokenType["_throw"] = _throw] = "_throw"; // throw keyword prefix startsExpr
const _try = 76816; TokenType[TokenType["_try"] = _try] = "_try"; // try keyword
const _var = 77840; TokenType[TokenType["_var"] = _var] = "_var"; // var keyword
const _let = 78864; TokenType[TokenType["_let"] = _let] = "_let"; // let keyword
const _const = 79888; TokenType[TokenType["_const"] = _const] = "_const"; // const keyword
const _while = 80912; TokenType[TokenType["_while"] = _while] = "_while"; // while keyword
const _with = 81936; TokenType[TokenType["_with"] = _with] = "_with"; // with keyword
const _new = 83472; TokenType[TokenType["_new"] = _new] = "_new"; // new keyword startsExpr
const _this = 84496; TokenType[TokenType["_this"] = _this] = "_this"; // this keyword startsExpr
const _super = 85520; TokenType[TokenType["_super"] = _super] = "_super"; // super keyword startsExpr
const _class = 86544; TokenType[TokenType["_class"] = _class] = "_class"; // class keyword startsExpr
const _extends = 87056; TokenType[TokenType["_extends"] = _extends] = "_extends"; // extends keyword
const _export = 88080; TokenType[TokenType["_export"] = _export] = "_export"; // export keyword
const _import = 89616; TokenType[TokenType["_import"] = _import] = "_import"; // import keyword startsExpr
const _yield = 90640; TokenType[TokenType["_yield"] = _yield] = "_yield"; // yield keyword startsExpr
const _null = 91664; TokenType[TokenType["_null"] = _null] = "_null"; // null keyword startsExpr
const _true = 92688; TokenType[TokenType["_true"] = _true] = "_true"; // true keyword startsExpr
const _false = 93712; TokenType[TokenType["_false"] = _false] = "_false"; // false keyword startsExpr
const _in = 94232; TokenType[TokenType["_in"] = _in] = "_in"; // in prec:8 keyword
const _instanceof = 95256; TokenType[TokenType["_instanceof"] = _instanceof] = "_instanceof"; // instanceof prec:8 keyword
const _typeof = 96912; TokenType[TokenType["_typeof"] = _typeof] = "_typeof"; // typeof keyword prefix startsExpr
const _void = 97936; TokenType[TokenType["_void"] = _void] = "_void"; // void keyword prefix startsExpr
const _delete = 98960; TokenType[TokenType["_delete"] = _delete] = "_delete"; // delete keyword prefix startsExpr
const _async = 99856; TokenType[TokenType["_async"] = _async] = "_async"; // async keyword startsExpr
const _get = 100880; TokenType[TokenType["_get"] = _get] = "_get"; // get keyword startsExpr
const _set = 101904; TokenType[TokenType["_set"] = _set] = "_set"; // set keyword startsExpr
const _declare = 102928; TokenType[TokenType["_declare"] = _declare] = "_declare"; // declare keyword startsExpr
const _readonly = 103952; TokenType[TokenType["_readonly"] = _readonly] = "_readonly"; // readonly keyword startsExpr
const _abstract = 104976; TokenType[TokenType["_abstract"] = _abstract] = "_abstract"; // abstract keyword startsExpr
const _static = 106000; TokenType[TokenType["_static"] = _static] = "_static"; // static keyword startsExpr
const _public = 106512; TokenType[TokenType["_public"] = _public] = "_public"; // public keyword
const _private = 107536; TokenType[TokenType["_private"] = _private] = "_private"; // private keyword
const _protected = 108560; TokenType[TokenType["_protected"] = _protected] = "_protected"; // protected keyword
const _override = 109584; TokenType[TokenType["_override"] = _override] = "_override"; // override keyword
const _as = 111120; TokenType[TokenType["_as"] = _as] = "_as"; // as keyword startsExpr
const _enum = 112144; TokenType[TokenType["_enum"] = _enum] = "_enum"; // enum keyword startsExpr
const _type = 113168; TokenType[TokenType["_type"] = _type] = "_type"; // type keyword startsExpr
const _implements = 114192; TokenType[TokenType["_implements"] = _implements] = "_implements"; // implements keyword startsExpr
const jsxEmptyText = 57344; TokenType[TokenType["jsxEmptyText"] = jsxEmptyText] = "jsxEmptyText"; // jsxEmptyText
const jsxTagStart = 58880; TokenType[TokenType["jsxTagStart"] = jsxTagStart] = "jsxTagStart"; // jsxTagStart startsExpr
const jsxTagEnd = 59392; TokenType[TokenType["jsxTagEnd"] = jsxTagEnd] = "jsxTagEnd"; // jsxTagEnd
const typeParameterStart = 60928; TokenType[TokenType["typeParameterStart"] = typeParameterStart] = "typeParameterStart"; // typeParameterStart startsExpr
const nonNullAssertion = 61440; TokenType[TokenType["nonNullAssertion"] = nonNullAssertion] = "nonNullAssertion"; // nonNullAssertion
const _break = 62480; TokenType[TokenType["_break"] = _break] = "_break"; // break keyword
const _case = 63504; TokenType[TokenType["_case"] = _case] = "_case"; // case keyword
const _catch = 64528; TokenType[TokenType["_catch"] = _catch] = "_catch"; // catch keyword
const _continue = 65552; TokenType[TokenType["_continue"] = _continue] = "_continue"; // continue keyword
const _debugger = 66576; TokenType[TokenType["_debugger"] = _debugger] = "_debugger"; // debugger keyword
const _default = 67600; TokenType[TokenType["_default"] = _default] = "_default"; // default keyword
const _do = 68624; TokenType[TokenType["_do"] = _do] = "_do"; // do keyword
const _else = 69648; TokenType[TokenType["_else"] = _else] = "_else"; // else keyword
const _finally = 70672; TokenType[TokenType["_finally"] = _finally] = "_finally"; // finally keyword
const _for = 71696; TokenType[TokenType["_for"] = _for] = "_for"; // for keyword
const _function = 73232; TokenType[TokenType["_function"] = _function] = "_function"; // function keyword startsExpr
const _if = 73744; TokenType[TokenType["_if"] = _if] = "_if"; // if keyword
const _return = 74768; TokenType[TokenType["_return"] = _return] = "_return"; // return keyword
const _switch = 75792; TokenType[TokenType["_switch"] = _switch] = "_switch"; // switch keyword
const _throw = 77456; TokenType[TokenType["_throw"] = _throw] = "_throw"; // throw keyword prefix startsExpr
const _try = 77840; TokenType[TokenType["_try"] = _try] = "_try"; // try keyword
const _var = 78864; TokenType[TokenType["_var"] = _var] = "_var"; // var keyword
const _let = 79888; TokenType[TokenType["_let"] = _let] = "_let"; // let keyword
const _const = 80912; TokenType[TokenType["_const"] = _const] = "_const"; // const keyword
const _while = 81936; TokenType[TokenType["_while"] = _while] = "_while"; // while keyword
const _with = 82960; TokenType[TokenType["_with"] = _with] = "_with"; // with keyword
const _new = 84496; TokenType[TokenType["_new"] = _new] = "_new"; // new keyword startsExpr
const _this = 85520; TokenType[TokenType["_this"] = _this] = "_this"; // this keyword startsExpr
const _super = 86544; TokenType[TokenType["_super"] = _super] = "_super"; // super keyword startsExpr
const _class = 87568; TokenType[TokenType["_class"] = _class] = "_class"; // class keyword startsExpr
const _extends = 88080; TokenType[TokenType["_extends"] = _extends] = "_extends"; // extends keyword
const _export = 89104; TokenType[TokenType["_export"] = _export] = "_export"; // export keyword
const _import = 90640; TokenType[TokenType["_import"] = _import] = "_import"; // import keyword startsExpr
const _yield = 91664; TokenType[TokenType["_yield"] = _yield] = "_yield"; // yield keyword startsExpr
const _null = 92688; TokenType[TokenType["_null"] = _null] = "_null"; // null keyword startsExpr
const _true = 93712; TokenType[TokenType["_true"] = _true] = "_true"; // true keyword startsExpr
const _false = 94736; TokenType[TokenType["_false"] = _false] = "_false"; // false keyword startsExpr
const _in = 95256; TokenType[TokenType["_in"] = _in] = "_in"; // in prec:8 keyword
const _instanceof = 96280; TokenType[TokenType["_instanceof"] = _instanceof] = "_instanceof"; // instanceof prec:8 keyword
const _typeof = 97936; TokenType[TokenType["_typeof"] = _typeof] = "_typeof"; // typeof keyword prefix startsExpr
const _void = 98960; TokenType[TokenType["_void"] = _void] = "_void"; // void keyword prefix startsExpr
const _delete = 99984; TokenType[TokenType["_delete"] = _delete] = "_delete"; // delete keyword prefix startsExpr
const _async = 100880; TokenType[TokenType["_async"] = _async] = "_async"; // async keyword startsExpr
const _get = 101904; TokenType[TokenType["_get"] = _get] = "_get"; // get keyword startsExpr
const _set = 102928; TokenType[TokenType["_set"] = _set] = "_set"; // set keyword startsExpr
const _declare = 103952; TokenType[TokenType["_declare"] = _declare] = "_declare"; // declare keyword startsExpr
const _readonly = 104976; TokenType[TokenType["_readonly"] = _readonly] = "_readonly"; // readonly keyword startsExpr
const _abstract = 106000; TokenType[TokenType["_abstract"] = _abstract] = "_abstract"; // abstract keyword startsExpr
const _static = 107024; TokenType[TokenType["_static"] = _static] = "_static"; // static keyword startsExpr
const _public = 107536; TokenType[TokenType["_public"] = _public] = "_public"; // public keyword
const _private = 108560; TokenType[TokenType["_private"] = _private] = "_private"; // private keyword
const _protected = 109584; TokenType[TokenType["_protected"] = _protected] = "_protected"; // protected keyword
const _override = 110608; TokenType[TokenType["_override"] = _override] = "_override"; // override keyword
const _as = 112144; TokenType[TokenType["_as"] = _as] = "_as"; // as keyword startsExpr
const _enum = 113168; TokenType[TokenType["_enum"] = _enum] = "_enum"; // enum keyword startsExpr
const _type = 114192; TokenType[TokenType["_type"] = _type] = "_type"; // type keyword startsExpr
const _implements = 115216; TokenType[TokenType["_implements"] = _implements] = "_implements"; // implements keyword startsExpr
})(TokenType || (exports.TokenType = TokenType = {}));

@@ -244,2 +245,4 @@ function formatTokenType(tokenType) {

return "jsxText";
case TokenType.jsxEmptyText:
return "jsxEmptyText";
case TokenType.jsxTagStart:

@@ -246,0 +249,0 @@ return "jsxTagStart";

@@ -451,3 +451,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});/* eslint max-len: 0 */

if (_index3.match.call(void 0, _types3.TokenType.jsxText)) {
if (_index3.match.call(void 0, _types3.TokenType.jsxText) || _index3.match.call(void 0, _types3.TokenType.jsxEmptyText)) {
parseLiteral();

@@ -454,0 +454,0 @@ return false;

"use strict";Object.defineProperty(exports, "__esModule", {value: true});var charCodes; (function (charCodes) {
const backSpace = 8; charCodes[charCodes["backSpace"] = backSpace] = "backSpace";
const lineFeed = 10; charCodes[charCodes["lineFeed"] = lineFeed] = "lineFeed"; // '\n'
const tab = 9; charCodes[charCodes["tab"] = tab] = "tab"; // '\t'
const carriageReturn = 13; charCodes[charCodes["carriageReturn"] = carriageReturn] = "carriageReturn"; // '\r'

@@ -5,0 +6,0 @@ const shiftOut = 14; charCodes[charCodes["shiftOut"] = shiftOut] = "shiftOut";

@@ -36,4 +36,13 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

getResultCodeIndex() {
return this.resultCode.length;
/**
* Remove and return the code generated since the snapshot, leaving the
* current token position in-place. Unlike most TokenProcessor operations,
* this operation can result in input/output line number mismatches because
* the removed code may contain newlines, so this operation should be used
* sparingly.
*/
dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot) {
const result = this.resultCode.slice(snapshot.resultCode.length);
this.resultCode = snapshot.resultCode;
return result;
}

@@ -40,0 +49,0 @@

@@ -5,2 +5,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var _xhtml = require('../parser/plugins/jsx/xhtml'); var _xhtml2 = _interopRequireDefault(_xhtml);
var _tokenizer = require('../parser/tokenizer');
var _types = require('../parser/tokenizer/types');

@@ -14,6 +15,18 @@ var _charcodes = require('../parser/util/charcodes');

class JSXTransformer extends _Transformer2.default {
// State for calculating the line number of each JSX tag in development.
__init() {this.lastLineNumber = 1}
__init2() {this.lastIndex = 0}
// In development, variable name holding the name of the current file.
__init3() {this.filenameVarName = null}
// Mapping of claimed names for imports in the automatic transform, e,g.
// {jsx: "_jsx"}. This determines which imports to generate in the prefix.
__init4() {this.esmAutomaticImportNameResolutions = {}}
// When automatically adding imports in CJS mode, we store the variable name
// holding the imported CJS module so we can require it in the prefix.
__init5() {this.cjsAutomaticModuleNameResolutions = {}}

@@ -27,4 +40,6 @@ constructor(

) {
super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.importProcessor = importProcessor;this.nameManager = nameManager;this.options = options;JSXTransformer.prototype.__init.call(this);JSXTransformer.prototype.__init2.call(this);JSXTransformer.prototype.__init3.call(this);;
super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.importProcessor = importProcessor;this.nameManager = nameManager;this.options = options;JSXTransformer.prototype.__init.call(this);JSXTransformer.prototype.__init2.call(this);JSXTransformer.prototype.__init3.call(this);JSXTransformer.prototype.__init4.call(this);JSXTransformer.prototype.__init5.call(this);;
this.jsxPragmaInfo = _getJSXPragmaInfo2.default.call(void 0, options);
this.isAutomaticRuntime = options.jsxRuntime === "automatic";
this.jsxImportSource = options.jsxImportSource || "react";
}

@@ -41,12 +56,52 @@

getPrefixCode() {
let prefix = "";
if (this.filenameVarName) {
return `const ${this.filenameVarName} = ${JSON.stringify(this.options.filePath || "")};`;
prefix += `const ${this.filenameVarName} = ${JSON.stringify(this.options.filePath || "")};`;
}
if (this.isAutomaticRuntime) {
if (this.importProcessor) {
// CJS mode: emit require statements for all modules that were referenced.
for (const [path, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
prefix += `var ${resolvedName} = require("${path}");`;
}
} else {
// ESM mode: consolidate and emit import statements for referenced names.
const {createElement: createElementResolution, ...otherResolutions} =
this.esmAutomaticImportNameResolutions;
if (createElementResolution) {
prefix += `import {createElement as ${createElementResolution}} from "${this.jsxImportSource}";`;
}
const importSpecifiers = Object.entries(otherResolutions)
.map(([name, resolvedName]) => `${name} as ${resolvedName}`)
.join(", ");
if (importSpecifiers) {
const importPath =
this.jsxImportSource + (this.options.production ? "/jsx-runtime" : "/jsx-dev-runtime");
prefix += `import {${importSpecifiers}} from "${importPath}";`;
}
}
}
return prefix;
}
processJSXTag() {
const {jsxRole, start} = this.tokens.currentToken();
// Calculate line number information at the very start (if in development
// mode) so that the information is guaranteed to be queried in token order.
const elementLocationCode = this.options.production ? null : this.getElementLocationCode(start);
if (this.isAutomaticRuntime && jsxRole !== _tokenizer.JSXRole.KeyAfterPropSpread) {
this.transformTagToJSXFunc(elementLocationCode, jsxRole);
} else {
return "";
this.transformTagToCreateElement(elementLocationCode);
}
}
getElementLocationCode(firstTokenStart) {
const lineNumber = this.getLineNumberForIndex(firstTokenStart);
return `lineNumber: ${lineNumber}`;
}
/**
* Lazily calculate line numbers to avoid unneeded work. We assume this is always called in
* increasing order by index.
* Get the line number for this source position. This is calculated lazily and
* must be called in increasing order by index.
*/

@@ -64,72 +119,206 @@ getLineNumberForIndex(index) {

getFilenameVarName() {
if (!this.filenameVarName) {
this.filenameVarName = this.nameManager.claimFreeName("_jsxFileName");
/**
* Convert the current JSX element to a call to jsx, jsxs, or jsxDEV. This is
* the primary transformation for the automatic transform.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* jsxs('div', {a: 1, children: ["Hello", x]}, 2)
*/
transformTagToJSXFunc(elementLocationCode, jsxRole) {
const isStatic = jsxRole === _tokenizer.JSXRole.StaticChildren;
// First tag is always jsxTagStart.
this.tokens.replaceToken(this.getJSXFuncInvocationCode(isStatic));
let keyCode = null;
if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
// Fragment syntax.
this.tokens.replaceToken(`${this.getFragmentCode()}, {`);
this.processAutomaticChildrenAndEndProps(jsxRole);
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.tokens.appendCode(", {");
keyCode = this.processProps(true);
if (this.tokens.matches2(_types.TokenType.slash, _types.TokenType.jsxTagEnd)) {
// Self-closing tag, no children to add, so close the props.
this.tokens.appendCode("}");
} else if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
// Tag with children.
this.tokens.removeToken();
this.processAutomaticChildrenAndEndProps(jsxRole);
} else {
throw new Error("Expected either /> or > at the end of the tag.");
}
// If a key was present, move it to its own arg. Note that moving code
// like this will cause line numbers to get out of sync within the JSX
// element if the key expression has a newline in it. This is unfortunate,
// but hopefully should be rare.
if (keyCode) {
this.tokens.appendCode(`, ${keyCode}`);
}
}
return this.filenameVarName;
if (!this.options.production) {
// If the key wasn't already added, add it now so we can correctly set
// positional args for jsxDEV.
if (keyCode === null) {
this.tokens.appendCode(", void 0");
}
this.tokens.appendCode(`, ${isStatic}, ${this.getDevSource(elementLocationCode)}, this`);
}
// We're at the close-tag or the end of a self-closing tag, so remove
// everything else and close the function call.
this.tokens.removeInitialToken();
while (!this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
this.tokens.removeToken();
}
this.tokens.replaceToken(")");
}
processProps(firstTokenStart) {
const lineNumber = this.getLineNumberForIndex(firstTokenStart);
const devProps = this.options.production
? ""
: `__self: this, __source: {fileName: ${this.getFilenameVarName()}, lineNumber: ${lineNumber}}`;
if (!this.tokens.matches1(_types.TokenType.jsxName) && !this.tokens.matches1(_types.TokenType.braceL)) {
if (devProps) {
this.tokens.appendCode(`, {${devProps}}`);
/**
* Convert the current JSX element to a createElement call. In the classic
* runtime, this is the only case. In the automatic runtime, this is called
* as a fallback in some situations.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* React.createElement('div', {a: 1, key: 2}, "Hello", x)
*/
transformTagToCreateElement(elementLocationCode) {
// First tag is always jsxTagStart.
this.tokens.replaceToken(this.getCreateElementInvocationCode());
if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
// Fragment syntax.
this.tokens.replaceToken(`${this.getFragmentCode()}, null`);
this.processChildren(true);
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.processPropsObjectWithDevInfo(elementLocationCode);
if (this.tokens.matches2(_types.TokenType.slash, _types.TokenType.jsxTagEnd)) {
// Self-closing tag; no children to process.
} else if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
// Tag with children and a close-tag; process the children as args.
this.tokens.removeToken();
this.processChildren(true);
} else {
this.tokens.appendCode(`, null`);
throw new Error("Expected either /> or > at the end of the tag.");
}
return;
}
this.tokens.appendCode(`, {`);
while (true) {
if (this.tokens.matches2(_types.TokenType.jsxName, _types.TokenType.eq)) {
this.processPropKeyName();
this.tokens.replaceToken(": ");
if (this.tokens.matches1(_types.TokenType.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else if (this.tokens.matches1(_types.TokenType.jsxTagStart)) {
this.processJSXTag();
} else {
this.processStringPropValue();
}
} else if (this.tokens.matches1(_types.TokenType.jsxName)) {
this.processPropKeyName();
this.tokens.appendCode(": true");
} else if (this.tokens.matches1(_types.TokenType.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
// We're at the close-tag or the end of a self-closing tag, so remove
// everything else and close the function call.
this.tokens.removeInitialToken();
while (!this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
this.tokens.removeToken();
}
this.tokens.replaceToken(")");
}
/**
* Get the code for the relevant function for this context: jsx, jsxs,
* or jsxDEV. The following open-paren is included as well.
*
* These functions are only used for the automatic runtime, so they are always
* auto-imported, but the auto-import will be either CJS or ESM based on the
* target module format.
*/
getJSXFuncInvocationCode(isStatic) {
if (this.options.production) {
if (isStatic) {
return this.claimAutoImportedFuncInvocation("jsxs", "/jsx-runtime");
} else {
break;
return this.claimAutoImportedFuncInvocation("jsx", "/jsx-runtime");
}
this.tokens.appendCode(",");
} else {
return this.claimAutoImportedFuncInvocation("jsxDEV", "/jsx-dev-runtime");
}
if (devProps) {
this.tokens.appendCode(` ${devProps}}`);
}
/**
* Return the code to use for the createElement function, e.g.
* `React.createElement`, including the following open-paren.
*
* This is the main function to use for the classic runtime. For the
* automatic runtime, this function is used as a fallback function to
* preserve behavior when there is a prop spread followed by an explicit
* key. In that automatic runtime case, the function should be automatically
* imported.
*/
getCreateElementInvocationCode() {
if (this.isAutomaticRuntime) {
return this.claimAutoImportedFuncInvocation("createElement", "");
} else {
this.tokens.appendCode("}");
const {jsxPragmaInfo} = this;
const resolvedPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.base) || jsxPragmaInfo.base
: jsxPragmaInfo.base;
return `${resolvedPragmaBaseName}${jsxPragmaInfo.suffix}(`;
}
}
processPropKeyName() {
const keyName = this.tokens.identifierName();
if (keyName.includes("-")) {
this.tokens.replaceToken(`'${keyName}'`);
/**
* Return the code to use as the component when compiling a shorthand
* fragment, e.g. `React.Fragment`.
*
* This may be called from either the classic or automatic runtime, and
* the value should be auto-imported for the automatic runtime.
*/
getFragmentCode() {
if (this.isAutomaticRuntime) {
return this.claimAutoImportedName(
"Fragment",
this.options.production ? "/jsx-runtime" : "/jsx-dev-runtime",
);
} else {
this.tokens.copyToken();
const {jsxPragmaInfo} = this;
const resolvedFragmentPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.fragmentBase) ||
jsxPragmaInfo.fragmentBase
: jsxPragmaInfo.fragmentBase;
return resolvedFragmentPragmaBaseName + jsxPragmaInfo.fragmentSuffix;
}
}
processStringPropValue() {
const token = this.tokens.currentToken();
const valueCode = this.tokens.code.slice(token.start + 1, token.end - 1);
const replacementCode = formatJSXTextReplacement(valueCode);
const literalCode = formatJSXStringValueLiteral(valueCode);
this.tokens.replaceToken(literalCode + replacementCode);
/**
* Return code that invokes the given function.
*
* When the imports transform is enabled, use the CJSImportTransformer
* strategy of using `.call(void 0, ...` to avoid passing a `this` value in a
* situation that would otherwise look like a method call.
*/
claimAutoImportedFuncInvocation(funcName, importPathSuffix) {
const funcCode = this.claimAutoImportedName(funcName, importPathSuffix);
if (this.importProcessor) {
return `${funcCode}.call(void 0, `;
} else {
return `${funcCode}(`;
}
}
claimAutoImportedName(funcName, importPathSuffix) {
if (this.importProcessor) {
// CJS mode: claim a name for the module and mark it for import.
const path = this.jsxImportSource + importPathSuffix;
if (!this.cjsAutomaticModuleNameResolutions[path]) {
this.cjsAutomaticModuleNameResolutions[path] =
this.importProcessor.getFreeIdentifierForPath(path);
}
return `${this.cjsAutomaticModuleNameResolutions[path]}.${funcName}`;
} else {
// ESM mode: claim a name for this function and add it to the names that
// should be auto-imported when the prefix is generated.
if (!this.esmAutomaticImportNameResolutions[funcName]) {
this.esmAutomaticImportNameResolutions[funcName] = this.nameManager.claimFreeName(
`_${funcName}`,
);
}
return this.esmAutomaticImportNameResolutions[funcName];
}
}
/**

@@ -167,4 +356,147 @@ * Process the first part of a tag, before any props.

processChildren() {
/**
* Starting at the beginning of the props, add the props argument to
* React.createElement, including the comma before it.
*/
processPropsObjectWithDevInfo(elementLocationCode) {
const devProps = this.options.production
? ""
: `__self: this, __source: ${this.getDevSource(elementLocationCode)}`;
if (!this.tokens.matches1(_types.TokenType.jsxName) && !this.tokens.matches1(_types.TokenType.braceL)) {
if (devProps) {
this.tokens.appendCode(`, {${devProps}}`);
} else {
this.tokens.appendCode(`, null`);
}
return;
}
this.tokens.appendCode(`, {`);
this.processProps(false);
if (devProps) {
this.tokens.appendCode(` ${devProps}}`);
} else {
this.tokens.appendCode("}");
}
}
/**
* Transform the core part of the props, assuming that a { has already been
* inserted before us and that a } will be inserted after us.
*
* If extractKeyCode is true (i.e. when using any jsx... function), any prop
* named "key" has its code captured and returned rather than being emitted to
* the output code. This shifts line numbers, and emitting the code later will
* correct line numbers again. If no key is found or if extractKeyCode is
* false, this function returns null.
*/
processProps(extractKeyCode) {
let keyCode = null;
while (true) {
if (this.tokens.matches2(_types.TokenType.jsxName, _types.TokenType.eq)) {
// This is a regular key={value} or key="value" prop.
const propName = this.tokens.identifierName();
if (extractKeyCode && propName === "key") {
if (keyCode !== null) {
// The props list has multiple keys. Different implementations are
// inconsistent about what to do here: as of this writing, Babel and
// swc keep the *last* key and completely remove the rest, while
// TypeScript uses the *first* key and leaves the others as regular
// props. The React team collaborated with Babel on the
// implementation of this behavior, so presumably the Babel behavior
// is the one to use.
// Since we won't ever be emitting the previous key code, we need to
// at least emit its newlines here so that the line numbers match up
// in the long run.
this.tokens.appendCode(keyCode.replace(/[^\n]/g, ""));
}
// key
this.tokens.removeToken();
// =
this.tokens.removeToken();
const snapshot = this.tokens.snapshot();
this.processPropValue();
keyCode = this.tokens.dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot);
// Don't add a comma
continue;
} else {
this.processPropName(propName);
this.tokens.replaceToken(": ");
this.processPropValue();
}
} else if (this.tokens.matches1(_types.TokenType.jsxName)) {
// This is a shorthand prop like <input disabled />.
const propName = this.tokens.identifierName();
this.processPropName(propName);
this.tokens.appendCode(": true");
} else if (this.tokens.matches1(_types.TokenType.braceL)) {
// This is prop spread, like <div {...getProps()}>, which we can pass
// through fairly directly as an object spread.
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else {
break;
}
this.tokens.appendCode(",");
}
return keyCode;
}
processPropName(propName) {
if (propName.includes("-")) {
this.tokens.replaceToken(`'${propName}'`);
} else {
this.tokens.copyToken();
}
}
processPropValue() {
if (this.tokens.matches1(_types.TokenType.braceL)) {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else if (this.tokens.matches1(_types.TokenType.jsxTagStart)) {
this.processJSXTag();
} else {
this.processStringPropValue();
}
}
processStringPropValue() {
const token = this.tokens.currentToken();
const valueCode = this.tokens.code.slice(token.start + 1, token.end - 1);
const replacementCode = formatJSXTextReplacement(valueCode);
const literalCode = formatJSXStringValueLiteral(valueCode);
this.tokens.replaceToken(literalCode + replacementCode);
}
/**
* Starting in the middle of the props object literal, produce an additional
* prop for the children and close the object literal.
*/
processAutomaticChildrenAndEndProps(jsxRole) {
if (jsxRole === _tokenizer.JSXRole.StaticChildren) {
this.tokens.appendCode(" children: [");
this.processChildren(false);
this.tokens.appendCode("]}");
} else {
// The parser information tells us whether we will see a real child or if
// all remaining children (if any) will resolve to empty. If there are no
// non-empty children, don't emit a children prop at all, but still
// process children so that we properly transform the code into nothing.
if (jsxRole === _tokenizer.JSXRole.OneChild) {
this.tokens.appendCode(" children: ");
}
this.processChildren(false);
this.tokens.appendCode("}");
}
}
/**
* Transform children into a comma-separated list, which will be either
* arguments to createElement or array elements of a children prop.
*/
processChildren(needsInitialComma) {
let needsComma = needsInitialComma;
while (true) {
if (this.tokens.matches2(_types.TokenType.jsxTagStart, _types.TokenType.slash)) {

@@ -174,2 +506,3 @@ // Closing tag, so no more children.

}
let didEmitElement = false;
if (this.tokens.matches1(_types.TokenType.braceL)) {

@@ -183,19 +516,30 @@ if (this.tokens.matches2(_types.TokenType.braceL, _types.TokenType.braceR)) {

// Interpolated expression.
this.tokens.replaceToken(", ");
this.tokens.replaceToken(needsComma ? ", " : "");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
didEmitElement = true;
}
} else if (this.tokens.matches1(_types.TokenType.jsxTagStart)) {
// Child JSX element
this.tokens.appendCode(", ");
this.tokens.appendCode(needsComma ? ", " : "");
this.processJSXTag();
} else if (this.tokens.matches1(_types.TokenType.jsxText)) {
this.processChildTextElement();
didEmitElement = true;
} else if (this.tokens.matches1(_types.TokenType.jsxText) || this.tokens.matches1(_types.TokenType.jsxEmptyText)) {
didEmitElement = this.processChildTextElement(needsComma);
} else {
throw new Error("Unexpected token when processing JSX children.");
}
if (didEmitElement) {
needsComma = true;
}
}
}
processChildTextElement() {
/**
* Turn a JSX text element into a string literal, or nothing at all if the JSX
* text resolves to the empty string.
*
* Returns true if a string literal is emitted, false otherwise.
*/
processChildTextElement(needsComma) {
const token = this.tokens.currentToken();

@@ -207,52 +551,18 @@ const valueCode = this.tokens.code.slice(token.start, token.end);

this.tokens.replaceToken(replacementCode);
return false;
} else {
this.tokens.replaceToken(`, ${literalCode}${replacementCode}`);
this.tokens.replaceToken(`${needsComma ? ", " : ""}${literalCode}${replacementCode}`);
return true;
}
}
processJSXTag() {
const {jsxPragmaInfo} = this;
const resolvedPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.base) || jsxPragmaInfo.base
: jsxPragmaInfo.base;
const firstTokenStart = this.tokens.currentToken().start;
// First tag is always jsxTagStart.
this.tokens.replaceToken(`${resolvedPragmaBaseName}${jsxPragmaInfo.suffix}(`);
getDevSource(elementLocationCode) {
return `{fileName: ${this.getFilenameVarName()}, ${elementLocationCode}}`;
}
if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
// Fragment syntax.
const resolvedFragmentPragmaBaseName = this.importProcessor
? this.importProcessor.getIdentifierReplacement(jsxPragmaInfo.fragmentBase) ||
jsxPragmaInfo.fragmentBase
: jsxPragmaInfo.fragmentBase;
this.tokens.replaceToken(
`${resolvedFragmentPragmaBaseName}${jsxPragmaInfo.fragmentSuffix}, null`,
);
// Tag with children.
this.processChildren();
while (!this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
this.tokens.replaceToken("");
}
this.tokens.replaceToken(")");
} else {
// Normal open tag or self-closing tag.
this.processTagIntro();
this.processProps(firstTokenStart);
if (this.tokens.matches2(_types.TokenType.slash, _types.TokenType.jsxTagEnd)) {
// Self-closing tag.
this.tokens.replaceToken("");
this.tokens.replaceToken(")");
} else if (this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
this.tokens.replaceToken("");
// Tag with children.
this.processChildren();
while (!this.tokens.matches1(_types.TokenType.jsxTagEnd)) {
this.tokens.replaceToken("");
}
this.tokens.replaceToken(")");
} else {
throw new Error("Expected either /> or > at the end of the tag.");
}
getFilenameVarName() {
if (!this.filenameVarName) {
this.filenameVarName = this.nameManager.claimFreeName("_jsxFileName");
}
return this.filenameVarName;
}

@@ -259,0 +569,0 @@ } exports.default = JSXTransformer;

@@ -33,3 +33,3 @@ import type { HelperManager } from "./HelperManager";

private generateImportReplacements;
private getFreeIdentifierForPath;
getFreeIdentifierForPath(path: string): string;
private preprocessImportAtIndex;

@@ -36,0 +36,0 @@ private preprocessExportAtIndex;

@@ -10,42 +10,45 @@ export declare type Transform = "jsx" | "typescript" | "flow" | "imports" | "react-hot-loader" | "jest";

export interface Options {
transforms: Array<Transform>;
/**
* If specified, function name to use in place of React.createClass when compiling JSX.
* Unordered array of transform names describing both the allowed syntax
* (where applicable) and the transformation behavior.
*/
jsxPragma?: string;
transforms: Array<Transform>;
/**
* If specified, function name to use in place of React.Fragment when compiling JSX.
* Opts out of all ES syntax transformations: optional chaining, nullish
* coalescing, class fields, numeric separators, optional catch binding.
*/
jsxFragmentPragma?: string;
disableESTransforms?: boolean;
/**
* If true, replicate the import behavior of TypeScript's esModuleInterop: false.
* Transformation mode for the JSX transform. The automatic transform refers
* to the transform behavior released with React 17, where the `jsx` function
* (or a variation) is automatically imported. The classic transform refers to
* the previous behavior using `React.createElement`.
*
* Default value: "classic"
*/
enableLegacyTypeScriptModuleInterop?: boolean;
jsxRuntime?: "classic" | "automatic";
/**
* If true, replicate the import behavior Babel 5 and babel-plugin-add-module-exports.
* Compile code for production use. Currently only applies to the JSX
* transform.
*/
enableLegacyBabel5ModuleInterop?: boolean;
production?: boolean;
/**
* If specified, we also return a RawSourceMap object alongside the code. Currently, source maps
* simply map each line to the original line without any mappings within lines, since Sucrase
* preserves line numbers. filePath must be specified if this option is enabled.
* If specified, import path prefix to use in place of "react" when compiling
* JSX with the automatic runtime.
*/
sourceMapOptions?: SourceMapOptions;
jsxImportSource?: string;
/**
* File path to use in error messages, React display names, and source maps.
* If specified, function name to use in place of React.createClass when
* compiling JSX with the classic runtime.
*/
filePath?: string;
jsxPragma?: string;
/**
* If specified, omit any development-specific code in the output.
* If specified, function name to use in place of React.Fragment when
* compiling JSX with the classic runtime.
*/
production?: boolean;
jsxFragmentPragma?: string;
/**
* Opts out ES syntax transformations, like optional chaining, nullish coalescing, numeric
* separators, etc.
* If specified, the imports transform does not attempt to change dynamic
* import() expressions into require() calls.
*/
disableESTransforms?: boolean;
/**
* If specified, the imports transform does not attempt to change dynamic import()
* expressions into require() calls.
*/
preserveDynamicImport?: boolean;

@@ -63,3 +66,22 @@ /**

injectCreateRequireForImportRequire?: boolean;
/**
* If true, replicate the import behavior of TypeScript's esModuleInterop: false.
*/
enableLegacyTypeScriptModuleInterop?: boolean;
/**
* If true, replicate the import behavior Babel 5 and babel-plugin-add-module-exports.
*/
enableLegacyBabel5ModuleInterop?: boolean;
/**
* If specified, we also return a RawSourceMap object alongside the code.
* Currently, source maps simply map each line to the original line without
* any mappings within lines, since Sucrase preserves line numbers. filePath
* must be specified if this option is enabled.
*/
sourceMapOptions?: SourceMapOptions;
/**
* File path to use in error messages, React display names, and source maps.
*/
filePath?: string;
}
export declare function validateOptions(options: Options): void;

@@ -17,2 +17,12 @@ import { ContextualKeyword } from "./keywords";

}
/**
* Extra information on jsxTagStart tokens, used to determine which of the three
* jsx functions are called in the automatic transform.
*/
export declare enum JSXRole {
NoChildren = 0,
OneChild = 1,
StaticChildren = 2,
KeyAfterPropSpread = 3
}
export declare function isDeclaration(token: Token): boolean;

@@ -33,2 +43,3 @@ export declare function isNonTopLevelDeclaration(token: Token): boolean;

identifierRole: IdentifierRole | null;
jsxRole: JSXRole | null;
shadowsGlobal: boolean;

@@ -35,0 +46,0 @@ isAsyncOperation: boolean;

@@ -68,59 +68,60 @@ /**

jsxText = 56320,
jsxTagStart = 57856,
jsxTagEnd = 58368,
typeParameterStart = 59904,
nonNullAssertion = 60416,
_break = 61456,
_case = 62480,
_catch = 63504,
_continue = 64528,
_debugger = 65552,
_default = 66576,
_do = 67600,
_else = 68624,
_finally = 69648,
_for = 70672,
_function = 72208,
_if = 72720,
_return = 73744,
_switch = 74768,
_throw = 76432,
_try = 76816,
_var = 77840,
_let = 78864,
_const = 79888,
_while = 80912,
_with = 81936,
_new = 83472,
_this = 84496,
_super = 85520,
_class = 86544,
_extends = 87056,
_export = 88080,
_import = 89616,
_yield = 90640,
_null = 91664,
_true = 92688,
_false = 93712,
_in = 94232,
_instanceof = 95256,
_typeof = 96912,
_void = 97936,
_delete = 98960,
_async = 99856,
_get = 100880,
_set = 101904,
_declare = 102928,
_readonly = 103952,
_abstract = 104976,
_static = 106000,
_public = 106512,
_private = 107536,
_protected = 108560,
_override = 109584,
_as = 111120,
_enum = 112144,
_type = 113168,
_implements = 114192
jsxEmptyText = 57344,
jsxTagStart = 58880,
jsxTagEnd = 59392,
typeParameterStart = 60928,
nonNullAssertion = 61440,
_break = 62480,
_case = 63504,
_catch = 64528,
_continue = 65552,
_debugger = 66576,
_default = 67600,
_do = 68624,
_else = 69648,
_finally = 70672,
_for = 71696,
_function = 73232,
_if = 73744,
_return = 74768,
_switch = 75792,
_throw = 77456,
_try = 77840,
_var = 78864,
_let = 79888,
_const = 80912,
_while = 81936,
_with = 82960,
_new = 84496,
_this = 85520,
_super = 86544,
_class = 87568,
_extends = 88080,
_export = 89104,
_import = 90640,
_yield = 91664,
_null = 92688,
_true = 93712,
_false = 94736,
_in = 95256,
_instanceof = 96280,
_typeof = 97936,
_void = 98960,
_delete = 99984,
_async = 100880,
_get = 101904,
_set = 102928,
_declare = 103952,
_readonly = 104976,
_abstract = 106000,
_static = 107024,
_public = 107536,
_private = 108560,
_protected = 109584,
_override = 110608,
_as = 112144,
_enum = 113168,
_type = 114192,
_implements = 115216
}
export declare function formatTokenType(tokenType: TokenType): string;
export declare enum charCodes {
backSpace = 8,
lineFeed = 10,
tab = 9,
carriageReturn = 13,

@@ -5,0 +6,0 @@ shiftOut = 14,

@@ -23,3 +23,10 @@ import type { HelperManager } from "./HelperManager";

restoreToSnapshot(snapshot: TokenProcessorSnapshot): void;
getResultCodeIndex(): number;
/**
* Remove and return the code generated since the snapshot, leaving the
* current token position in-place. Unlike most TokenProcessor operations,
* this operation can result in input/output line number mismatches because
* the removed code may contain newlines, so this operation should be used
* sparingly.
*/
dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot: TokenProcessorSnapshot): string;
reset(): void;

@@ -26,0 +33,0 @@ matchesContextualAtIndex(index: number, contextualKeyword: ContextualKeyword): boolean;

import type CJSImportProcessor from "../CJSImportProcessor";
import type { Options } from "../index";
import type NameManager from "../NameManager";
import { JSXRole } from "../parser/tokenizer";
import type TokenProcessor from "../TokenProcessor";

@@ -14,25 +15,124 @@ import { JSXPragmaInfo } from "../util/getJSXPragmaInfo";

readonly options: Options;
jsxPragmaInfo: JSXPragmaInfo;
jsxImportSource: string;
isAutomaticRuntime: boolean;
lastLineNumber: number;
lastIndex: number;
filenameVarName: string | null;
readonly jsxPragmaInfo: JSXPragmaInfo;
esmAutomaticImportNameResolutions: {
[name: string]: string;
};
cjsAutomaticModuleNameResolutions: {
[path: string]: string;
};
constructor(rootTransformer: RootTransformer, tokens: TokenProcessor, importProcessor: CJSImportProcessor | null, nameManager: NameManager, options: Options);
process(): boolean;
getPrefixCode(): string;
processJSXTag(): void;
getElementLocationCode(firstTokenStart: number): string;
/**
* Lazily calculate line numbers to avoid unneeded work. We assume this is always called in
* increasing order by index.
* Get the line number for this source position. This is calculated lazily and
* must be called in increasing order by index.
*/
getLineNumberForIndex(index: number): number;
getFilenameVarName(): string;
processProps(firstTokenStart: number): void;
processPropKeyName(): void;
processStringPropValue(): void;
/**
* Convert the current JSX element to a call to jsx, jsxs, or jsxDEV. This is
* the primary transformation for the automatic transform.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* jsxs('div', {a: 1, children: ["Hello", x]}, 2)
*/
transformTagToJSXFunc(elementLocationCode: string | null, jsxRole: JSXRole): void;
/**
* Convert the current JSX element to a createElement call. In the classic
* runtime, this is the only case. In the automatic runtime, this is called
* as a fallback in some situations.
*
* Example:
* <div a={1} key={2}>Hello{x}</div>
* becomes
* React.createElement('div', {a: 1, key: 2}, "Hello", x)
*/
transformTagToCreateElement(elementLocationCode: string | null): void;
/**
* Get the code for the relevant function for this context: jsx, jsxs,
* or jsxDEV. The following open-paren is included as well.
*
* These functions are only used for the automatic runtime, so they are always
* auto-imported, but the auto-import will be either CJS or ESM based on the
* target module format.
*/
getJSXFuncInvocationCode(isStatic: boolean): string;
/**
* Return the code to use for the createElement function, e.g.
* `React.createElement`, including the following open-paren.
*
* This is the main function to use for the classic runtime. For the
* automatic runtime, this function is used as a fallback function to
* preserve behavior when there is a prop spread followed by an explicit
* key. In that automatic runtime case, the function should be automatically
* imported.
*/
getCreateElementInvocationCode(): string;
/**
* Return the code to use as the component when compiling a shorthand
* fragment, e.g. `React.Fragment`.
*
* This may be called from either the classic or automatic runtime, and
* the value should be auto-imported for the automatic runtime.
*/
getFragmentCode(): string;
/**
* Return code that invokes the given function.
*
* When the imports transform is enabled, use the CJSImportTransformer
* strategy of using `.call(void 0, ...` to avoid passing a `this` value in a
* situation that would otherwise look like a method call.
*/
claimAutoImportedFuncInvocation(funcName: string, importPathSuffix: string): string;
claimAutoImportedName(funcName: string, importPathSuffix: string): string;
/**
* Process the first part of a tag, before any props.
*/
processTagIntro(): void;
processChildren(): void;
processChildTextElement(): void;
processJSXTag(): void;
/**
* Starting at the beginning of the props, add the props argument to
* React.createElement, including the comma before it.
*/
processPropsObjectWithDevInfo(elementLocationCode: string | null): void;
/**
* Transform the core part of the props, assuming that a { has already been
* inserted before us and that a } will be inserted after us.
*
* If extractKeyCode is true (i.e. when using any jsx... function), any prop
* named "key" has its code captured and returned rather than being emitted to
* the output code. This shifts line numbers, and emitting the code later will
* correct line numbers again. If no key is found or if extractKeyCode is
* false, this function returns null.
*/
processProps(extractKeyCode: boolean): string | null;
processPropName(propName: string): void;
processPropValue(): void;
processStringPropValue(): void;
/**
* Starting in the middle of the props object literal, produce an additional
* prop for the children and close the object literal.
*/
processAutomaticChildrenAndEndProps(jsxRole: JSXRole): void;
/**
* Transform children into a comma-separated list, which will be either
* arguments to createElement or array elements of a children prop.
*/
processChildren(needsInitialComma: boolean): void;
/**
* Turn a JSX text element into a string literal, or nothing at all if the JSX
* text resolves to the empty string.
*
* Returns true if a string literal is emitted, false otherwise.
*/
processChildTextElement(needsComma: boolean): boolean;
getDevSource(elementLocationCode: string): string;
getFilenameVarName(): string;
}

@@ -39,0 +139,0 @@ /**

{
"name": "sucrase",
"version": "3.25.0",
"version": "3.26.0",
"description": "Super-fast alternative to Babel for when you can target modern JS runtimes",

@@ -66,3 +66,3 @@ "author": "Alan Pierce <alangpierce@gmail.com>",

"prettier": "^2.6.2",
"sucrase": "^3.24.0",
"sucrase": "^3.25.0",
"test262-harness": "^10.0.0",

@@ -69,0 +69,0 @@ "ts-interface-builder": "^0.3.3",

@@ -118,7 +118,17 @@ # Sucrase

Like Babel, Sucrase compiles JSX to React functions by default, but can be
configured for any JSX use case.
By default, JSX is compiled to React functions in development mode. This can be
configured with a few options:
* **jsxPragma**: Element creation function, defaults to `React.createElement`.
* **jsxFragmentPragma**: Fragment component, defaults to `React.Fragment`.
* **jsxRuntime**: A string specifying the transform mode, which can be one of two values:
* `"classic"` (default): The original JSX transform that calls `React.createElement` by default.
To configure for non-React use cases, specify:
* **jsxPragma**: Element creation function, defaults to `React.createElement`.
* **jsxFragmentPragma**: Fragment component, defaults to `React.Fragment`.
* `"automatic"`: The [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)
introduced with React 17, which calls `jsx` functions and auto-adds import statements.
To configure for non-React use cases, specify:
* **jsxImportSource**: Package name for auto-generated import statements, defaults to `react`.
* **production**: If `true`, use production version of functions and don't include debugging
information. When using React in production mode with the automatic transform, this *must* be
set to true to avoid an error about `jsxDEV` being missing.

@@ -125,0 +135,0 @@ ### Legacy CommonJS interop

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc