summaryrefslogtreecommitdiff
path: root/node_modules/sucrase/dist/esm/TokenProcessor.js
diff options
context:
space:
mode:
authorPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:54:57 +0100
committerPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:57:48 +0100
commitb1e2c8fd5cb5dfa46bc440a12eafaf56cd844b1c (patch)
tree49d360fd6cbc6a2754efe93524ac47ff0fbe0f7d /node_modules/sucrase/dist/esm/TokenProcessor.js
Docs
Diffstat (limited to 'node_modules/sucrase/dist/esm/TokenProcessor.js')
-rw-r--r--node_modules/sucrase/dist/esm/TokenProcessor.js357
1 files changed, 357 insertions, 0 deletions
diff --git a/node_modules/sucrase/dist/esm/TokenProcessor.js b/node_modules/sucrase/dist/esm/TokenProcessor.js
new file mode 100644
index 0000000..5335f23
--- /dev/null
+++ b/node_modules/sucrase/dist/esm/TokenProcessor.js
@@ -0,0 +1,357 @@
+
+
+
+import { TokenType as tt} from "./parser/tokenizer/types";
+import isAsyncOperation from "./util/isAsyncOperation";
+
+
+
+
+
+
+
+
+
+
+
+export default class TokenProcessor {
+ __init() {this.resultCode = ""}
+ // Array mapping input token index to optional string index position in the
+ // output code.
+ __init2() {this.resultMappings = new Array(this.tokens.length)}
+ __init3() {this.tokenIndex = 0}
+
+ constructor(
+ code,
+ tokens,
+ isFlowEnabled,
+ disableESTransforms,
+ helperManager,
+ ) {;this.code = code;this.tokens = tokens;this.isFlowEnabled = isFlowEnabled;this.disableESTransforms = disableESTransforms;this.helperManager = helperManager;TokenProcessor.prototype.__init.call(this);TokenProcessor.prototype.__init2.call(this);TokenProcessor.prototype.__init3.call(this);}
+
+ /**
+ * Snapshot the token state in a way that can be restored later, useful for
+ * things like lookahead.
+ *
+ * resultMappings do not need to be copied since in all use cases, they will
+ * be overwritten anyway after restore.
+ */
+ snapshot() {
+ return {
+ resultCode: this.resultCode,
+ tokenIndex: this.tokenIndex,
+ };
+ }
+
+ restoreToSnapshot(snapshot) {
+ this.resultCode = snapshot.resultCode;
+ this.tokenIndex = snapshot.tokenIndex;
+ }
+
+ /**
+ * 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;
+ }
+
+ reset() {
+ this.resultCode = "";
+ this.resultMappings = new Array(this.tokens.length);
+ this.tokenIndex = 0;
+ }
+
+ matchesContextualAtIndex(index, contextualKeyword) {
+ return (
+ this.matches1AtIndex(index, tt.name) &&
+ this.tokens[index].contextualKeyword === contextualKeyword
+ );
+ }
+
+ identifierNameAtIndex(index) {
+ // TODO: We need to process escapes since technically you can have unicode escapes in variable
+ // names.
+ return this.identifierNameForToken(this.tokens[index]);
+ }
+
+ identifierNameAtRelativeIndex(relativeIndex) {
+ return this.identifierNameForToken(this.tokenAtRelativeIndex(relativeIndex));
+ }
+
+ identifierName() {
+ return this.identifierNameForToken(this.currentToken());
+ }
+
+ identifierNameForToken(token) {
+ return this.code.slice(token.start, token.end);
+ }
+
+ rawCodeForToken(token) {
+ return this.code.slice(token.start, token.end);
+ }
+
+ stringValueAtIndex(index) {
+ return this.stringValueForToken(this.tokens[index]);
+ }
+
+ stringValue() {
+ return this.stringValueForToken(this.currentToken());
+ }
+
+ stringValueForToken(token) {
+ // This is used to identify when two imports are the same and to resolve TypeScript enum keys.
+ // Ideally we'd process escapes within the strings, but for now we pretty much take the raw
+ // code.
+ return this.code.slice(token.start + 1, token.end - 1);
+ }
+
+ matches1AtIndex(index, t1) {
+ return this.tokens[index].type === t1;
+ }
+
+ matches2AtIndex(index, t1, t2) {
+ return this.tokens[index].type === t1 && this.tokens[index + 1].type === t2;
+ }
+
+ matches3AtIndex(index, t1, t2, t3) {
+ return (
+ this.tokens[index].type === t1 &&
+ this.tokens[index + 1].type === t2 &&
+ this.tokens[index + 2].type === t3
+ );
+ }
+
+ matches1(t1) {
+ return this.tokens[this.tokenIndex].type === t1;
+ }
+
+ matches2(t1, t2) {
+ return this.tokens[this.tokenIndex].type === t1 && this.tokens[this.tokenIndex + 1].type === t2;
+ }
+
+ matches3(t1, t2, t3) {
+ return (
+ this.tokens[this.tokenIndex].type === t1 &&
+ this.tokens[this.tokenIndex + 1].type === t2 &&
+ this.tokens[this.tokenIndex + 2].type === t3
+ );
+ }
+
+ matches4(t1, t2, t3, t4) {
+ return (
+ this.tokens[this.tokenIndex].type === t1 &&
+ this.tokens[this.tokenIndex + 1].type === t2 &&
+ this.tokens[this.tokenIndex + 2].type === t3 &&
+ this.tokens[this.tokenIndex + 3].type === t4
+ );
+ }
+
+ matches5(t1, t2, t3, t4, t5) {
+ return (
+ this.tokens[this.tokenIndex].type === t1 &&
+ this.tokens[this.tokenIndex + 1].type === t2 &&
+ this.tokens[this.tokenIndex + 2].type === t3 &&
+ this.tokens[this.tokenIndex + 3].type === t4 &&
+ this.tokens[this.tokenIndex + 4].type === t5
+ );
+ }
+
+ matchesContextual(contextualKeyword) {
+ return this.matchesContextualAtIndex(this.tokenIndex, contextualKeyword);
+ }
+
+ matchesContextIdAndLabel(type, contextId) {
+ return this.matches1(type) && this.currentToken().contextId === contextId;
+ }
+
+ previousWhitespaceAndComments() {
+ let whitespaceAndComments = this.code.slice(
+ this.tokenIndex > 0 ? this.tokens[this.tokenIndex - 1].end : 0,
+ this.tokenIndex < this.tokens.length ? this.tokens[this.tokenIndex].start : this.code.length,
+ );
+ if (this.isFlowEnabled) {
+ whitespaceAndComments = whitespaceAndComments.replace(/@flow/g, "");
+ }
+ return whitespaceAndComments;
+ }
+
+ replaceToken(newCode) {
+ this.resultCode += this.previousWhitespaceAndComments();
+ this.appendTokenPrefix();
+ this.resultMappings[this.tokenIndex] = this.resultCode.length;
+ this.resultCode += newCode;
+ this.appendTokenSuffix();
+ this.tokenIndex++;
+ }
+
+ replaceTokenTrimmingLeftWhitespace(newCode) {
+ this.resultCode += this.previousWhitespaceAndComments().replace(/[^\r\n]/g, "");
+ this.appendTokenPrefix();
+ this.resultMappings[this.tokenIndex] = this.resultCode.length;
+ this.resultCode += newCode;
+ this.appendTokenSuffix();
+ this.tokenIndex++;
+ }
+
+ removeInitialToken() {
+ this.replaceToken("");
+ }
+
+ removeToken() {
+ this.replaceTokenTrimmingLeftWhitespace("");
+ }
+
+ /**
+ * Remove all code until the next }, accounting for balanced braces.
+ */
+ removeBalancedCode() {
+ let braceDepth = 0;
+ while (!this.isAtEnd()) {
+ if (this.matches1(tt.braceL)) {
+ braceDepth++;
+ } else if (this.matches1(tt.braceR)) {
+ if (braceDepth === 0) {
+ return;
+ }
+ braceDepth--;
+ }
+ this.removeToken();
+ }
+ }
+
+ copyExpectedToken(tokenType) {
+ if (this.tokens[this.tokenIndex].type !== tokenType) {
+ throw new Error(`Expected token ${tokenType}`);
+ }
+ this.copyToken();
+ }
+
+ copyToken() {
+ this.resultCode += this.previousWhitespaceAndComments();
+ this.appendTokenPrefix();
+ this.resultMappings[this.tokenIndex] = this.resultCode.length;
+ this.resultCode += this.code.slice(
+ this.tokens[this.tokenIndex].start,
+ this.tokens[this.tokenIndex].end,
+ );
+ this.appendTokenSuffix();
+ this.tokenIndex++;
+ }
+
+ copyTokenWithPrefix(prefix) {
+ this.resultCode += this.previousWhitespaceAndComments();
+ this.appendTokenPrefix();
+ this.resultCode += prefix;
+ this.resultMappings[this.tokenIndex] = this.resultCode.length;
+ this.resultCode += this.code.slice(
+ this.tokens[this.tokenIndex].start,
+ this.tokens[this.tokenIndex].end,
+ );
+ this.appendTokenSuffix();
+ this.tokenIndex++;
+ }
+
+ appendTokenPrefix() {
+ const token = this.currentToken();
+ if (token.numNullishCoalesceStarts || token.isOptionalChainStart) {
+ token.isAsyncOperation = isAsyncOperation(this);
+ }
+ if (this.disableESTransforms) {
+ return;
+ }
+ if (token.numNullishCoalesceStarts) {
+ for (let i = 0; i < token.numNullishCoalesceStarts; i++) {
+ if (token.isAsyncOperation) {
+ this.resultCode += "await ";
+ this.resultCode += this.helperManager.getHelperName("asyncNullishCoalesce");
+ } else {
+ this.resultCode += this.helperManager.getHelperName("nullishCoalesce");
+ }
+ this.resultCode += "(";
+ }
+ }
+ if (token.isOptionalChainStart) {
+ if (token.isAsyncOperation) {
+ this.resultCode += "await ";
+ }
+ if (this.tokenIndex > 0 && this.tokenAtRelativeIndex(-1).type === tt._delete) {
+ if (token.isAsyncOperation) {
+ this.resultCode += this.helperManager.getHelperName("asyncOptionalChainDelete");
+ } else {
+ this.resultCode += this.helperManager.getHelperName("optionalChainDelete");
+ }
+ } else if (token.isAsyncOperation) {
+ this.resultCode += this.helperManager.getHelperName("asyncOptionalChain");
+ } else {
+ this.resultCode += this.helperManager.getHelperName("optionalChain");
+ }
+ this.resultCode += "([";
+ }
+ }
+
+ appendTokenSuffix() {
+ const token = this.currentToken();
+ if (token.isOptionalChainEnd && !this.disableESTransforms) {
+ this.resultCode += "])";
+ }
+ if (token.numNullishCoalesceEnds && !this.disableESTransforms) {
+ for (let i = 0; i < token.numNullishCoalesceEnds; i++) {
+ this.resultCode += "))";
+ }
+ }
+ }
+
+ appendCode(code) {
+ this.resultCode += code;
+ }
+
+ currentToken() {
+ return this.tokens[this.tokenIndex];
+ }
+
+ currentTokenCode() {
+ const token = this.currentToken();
+ return this.code.slice(token.start, token.end);
+ }
+
+ tokenAtRelativeIndex(relativeIndex) {
+ return this.tokens[this.tokenIndex + relativeIndex];
+ }
+
+ currentIndex() {
+ return this.tokenIndex;
+ }
+
+ /**
+ * Move to the next token. Only suitable in preprocessing steps. When
+ * generating new code, you should use copyToken or removeToken.
+ */
+ nextToken() {
+ if (this.tokenIndex === this.tokens.length) {
+ throw new Error("Unexpectedly reached end of input.");
+ }
+ this.tokenIndex++;
+ }
+
+ previousToken() {
+ this.tokenIndex--;
+ }
+
+ finish() {
+ if (this.tokenIndex !== this.tokens.length) {
+ throw new Error("Tried to finish processing tokens before reaching the end.");
+ }
+ this.resultCode += this.previousWhitespaceAndComments();
+ return {code: this.resultCode, mappings: this.resultMappings};
+ }
+
+ isAtEnd() {
+ return this.tokenIndex === this.tokens.length;
+ }
+}