This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
264 lines
7.9 KiB
JavaScript
264 lines
7.9 KiB
JavaScript
/**
|
|
* @fileoverview Translates tokens between Acorn format and Esprima format.
|
|
* @author Nicholas C. Zakas
|
|
*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Requirements
|
|
//------------------------------------------------------------------------------
|
|
|
|
// none!
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Private
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
// Esprima Token Types
|
|
const Token = {
|
|
Boolean: "Boolean",
|
|
EOF: "<end>",
|
|
Identifier: "Identifier",
|
|
PrivateIdentifier: "PrivateIdentifier",
|
|
Keyword: "Keyword",
|
|
Null: "Null",
|
|
Numeric: "Numeric",
|
|
Punctuator: "Punctuator",
|
|
String: "String",
|
|
RegularExpression: "RegularExpression",
|
|
Template: "Template",
|
|
JSXIdentifier: "JSXIdentifier",
|
|
JSXText: "JSXText"
|
|
};
|
|
|
|
/**
|
|
* Converts part of a template into an Esprima token.
|
|
* @param {AcornToken[]} tokens The Acorn tokens representing the template.
|
|
* @param {string} code The source code.
|
|
* @returns {EsprimaToken} The Esprima equivalent of the template token.
|
|
* @private
|
|
*/
|
|
function convertTemplatePart(tokens, code) {
|
|
const firstToken = tokens[0],
|
|
lastTemplateToken = tokens[tokens.length - 1];
|
|
|
|
const token = {
|
|
type: Token.Template,
|
|
value: code.slice(firstToken.start, lastTemplateToken.end)
|
|
};
|
|
|
|
if (firstToken.loc) {
|
|
token.loc = {
|
|
start: firstToken.loc.start,
|
|
end: lastTemplateToken.loc.end
|
|
};
|
|
}
|
|
|
|
if (firstToken.range) {
|
|
token.start = firstToken.range[0];
|
|
token.end = lastTemplateToken.range[1];
|
|
token.range = [token.start, token.end];
|
|
}
|
|
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* Contains logic to translate Acorn tokens into Esprima tokens.
|
|
* @param {Object} acornTokTypes The Acorn token types.
|
|
* @param {string} code The source code Acorn is parsing. This is necessary
|
|
* to correct the "value" property of some tokens.
|
|
* @constructor
|
|
*/
|
|
function TokenTranslator(acornTokTypes, code) {
|
|
|
|
// token types
|
|
this._acornTokTypes = acornTokTypes;
|
|
|
|
// token buffer for templates
|
|
this._tokens = [];
|
|
|
|
// track the last curly brace
|
|
this._curlyBrace = null;
|
|
|
|
// the source code
|
|
this._code = code;
|
|
|
|
}
|
|
|
|
TokenTranslator.prototype = {
|
|
constructor: TokenTranslator,
|
|
|
|
/**
|
|
* Translates a single Esprima token to a single Acorn token. This may be
|
|
* inaccurate due to how templates are handled differently in Esprima and
|
|
* Acorn, but should be accurate for all other tokens.
|
|
* @param {AcornToken} token The Acorn token to translate.
|
|
* @param {Object} extra Espree extra object.
|
|
* @returns {EsprimaToken} The Esprima version of the token.
|
|
*/
|
|
translate(token, extra) {
|
|
|
|
const type = token.type,
|
|
tt = this._acornTokTypes;
|
|
|
|
if (type === tt.name) {
|
|
token.type = Token.Identifier;
|
|
|
|
// TODO: See if this is an Acorn bug
|
|
if (token.value === "static") {
|
|
token.type = Token.Keyword;
|
|
}
|
|
|
|
if (extra.ecmaVersion > 5 && (token.value === "yield" || token.value === "let")) {
|
|
token.type = Token.Keyword;
|
|
}
|
|
|
|
} else if (type === tt.privateId) {
|
|
token.type = Token.PrivateIdentifier;
|
|
|
|
} else if (type === tt.semi || type === tt.comma ||
|
|
type === tt.parenL || type === tt.parenR ||
|
|
type === tt.braceL || type === tt.braceR ||
|
|
type === tt.dot || type === tt.bracketL ||
|
|
type === tt.colon || type === tt.question ||
|
|
type === tt.bracketR || type === tt.ellipsis ||
|
|
type === tt.arrow || type === tt.jsxTagStart ||
|
|
type === tt.incDec || type === tt.starstar ||
|
|
type === tt.jsxTagEnd || type === tt.prefix ||
|
|
type === tt.questionDot ||
|
|
(type.binop && !type.keyword) ||
|
|
type.isAssign) {
|
|
|
|
token.type = Token.Punctuator;
|
|
token.value = this._code.slice(token.start, token.end);
|
|
} else if (type === tt.jsxName) {
|
|
token.type = Token.JSXIdentifier;
|
|
} else if (type.label === "jsxText" || type === tt.jsxAttrValueToken) {
|
|
token.type = Token.JSXText;
|
|
} else if (type.keyword) {
|
|
if (type.keyword === "true" || type.keyword === "false") {
|
|
token.type = Token.Boolean;
|
|
} else if (type.keyword === "null") {
|
|
token.type = Token.Null;
|
|
} else {
|
|
token.type = Token.Keyword;
|
|
}
|
|
} else if (type === tt.num) {
|
|
token.type = Token.Numeric;
|
|
token.value = this._code.slice(token.start, token.end);
|
|
} else if (type === tt.string) {
|
|
|
|
if (extra.jsxAttrValueToken) {
|
|
extra.jsxAttrValueToken = false;
|
|
token.type = Token.JSXText;
|
|
} else {
|
|
token.type = Token.String;
|
|
}
|
|
|
|
token.value = this._code.slice(token.start, token.end);
|
|
} else if (type === tt.regexp) {
|
|
token.type = Token.RegularExpression;
|
|
const value = token.value;
|
|
|
|
token.regex = {
|
|
flags: value.flags,
|
|
pattern: value.pattern
|
|
};
|
|
token.value = `/${value.pattern}/${value.flags}`;
|
|
}
|
|
|
|
return token;
|
|
},
|
|
|
|
/**
|
|
* Function to call during Acorn's onToken handler.
|
|
* @param {AcornToken} token The Acorn token.
|
|
* @param {Object} extra The Espree extra object.
|
|
* @returns {void}
|
|
*/
|
|
onToken(token, extra) {
|
|
|
|
const tt = this._acornTokTypes,
|
|
tokens = extra.tokens,
|
|
templateTokens = this._tokens;
|
|
|
|
/**
|
|
* Flushes the buffered template tokens and resets the template
|
|
* tracking.
|
|
* @returns {void}
|
|
* @private
|
|
*/
|
|
const translateTemplateTokens = () => {
|
|
tokens.push(convertTemplatePart(this._tokens, this._code));
|
|
this._tokens = [];
|
|
};
|
|
|
|
if (token.type === tt.eof) {
|
|
|
|
// might be one last curlyBrace
|
|
if (this._curlyBrace) {
|
|
tokens.push(this.translate(this._curlyBrace, extra));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (token.type === tt.backQuote) {
|
|
|
|
// if there's already a curly, it's not part of the template
|
|
if (this._curlyBrace) {
|
|
tokens.push(this.translate(this._curlyBrace, extra));
|
|
this._curlyBrace = null;
|
|
}
|
|
|
|
templateTokens.push(token);
|
|
|
|
// it's the end
|
|
if (templateTokens.length > 1) {
|
|
translateTemplateTokens();
|
|
}
|
|
|
|
return;
|
|
}
|
|
if (token.type === tt.dollarBraceL) {
|
|
templateTokens.push(token);
|
|
translateTemplateTokens();
|
|
return;
|
|
}
|
|
if (token.type === tt.braceR) {
|
|
|
|
// if there's already a curly, it's not part of the template
|
|
if (this._curlyBrace) {
|
|
tokens.push(this.translate(this._curlyBrace, extra));
|
|
}
|
|
|
|
// store new curly for later
|
|
this._curlyBrace = token;
|
|
return;
|
|
}
|
|
if (token.type === tt.template || token.type === tt.invalidTemplate) {
|
|
if (this._curlyBrace) {
|
|
templateTokens.push(this._curlyBrace);
|
|
this._curlyBrace = null;
|
|
}
|
|
|
|
templateTokens.push(token);
|
|
return;
|
|
}
|
|
|
|
if (this._curlyBrace) {
|
|
tokens.push(this.translate(this._curlyBrace, extra));
|
|
this._curlyBrace = null;
|
|
}
|
|
|
|
tokens.push(this.translate(token, extra));
|
|
}
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Public
|
|
//------------------------------------------------------------------------------
|
|
|
|
export default TokenTranslator;
|