function getAugmentedNamespace(n) { if (n.__esModule) return n;
var f = n.default; if (typeof f == "function") {
var a = function a () { if (this instanceof a) {
var args = [null];
args.push.apply(args, arguments);
var Ctor = Function.bind.apply(f, args); returnnew Ctor();
} return f.apply(this, arguments);
};
a.prototype = f.prototype;
} else a = {};
Object.defineProperty(a, '__esModule', {value: true});
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(a, k, d.get ? d : {
enumerable: true,
get: function () { return n[k];
}
});
}); return a;
}
var sourceMap$1 = {};
var sourceMapGenerator = {};
var base64Vlq = {};
var base64 = {};
var hasRequiredBase64;
function requireBase64 () { if (hasRequiredBase64) return base64;
hasRequiredBase64 = 1; /* *Copyright2011MozillaFoundationandcontributors *LicensedundertheNewBSDlicense.SeeLICENSEor: *http://opensource.org/licenses/BSD-3-Clause
*/
// A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, // the next four bits are the actual value, and the 6th bit is the // continuation bit. The continuation bit tells us whether there are more // digits in this value following this digit. // // Continuation // | Sign // | | // V V // 101011
/** *Returnsthebase64VLQencodedvalue.
*/
base64Vlq.encode = function base64VLQ_encode(aValue) {
let encoded = "";
let digit;
let vlq = toVLQSigned(aValue);
do {
digit = vlq & VLQ_BASE_MASK;
vlq >>>= VLQ_BASE_SHIFT; if (vlq > 0) { // There are still more digits in this value, so we must make sure the // continuation bit is marked.
digit |= VLQ_CONTINUATION_BIT;
}
encoded += base64.encode(digit);
} while (vlq > 0);
return encoded;
}; return base64Vlq;
}
var util = {};
var hasRequiredUtil;
function requireUtil () { if (hasRequiredUtil) return util;
hasRequiredUtil = 1;
(function (exports) { /* *Copyright2011MozillaFoundationandcontributors *LicensedundertheNewBSDlicense.SeeLICENSEor: *http://opensource.org/licenses/BSD-3-Clause
*/
/** *Thisisahelperfunctionforgettingvaluesfromparameter/options *objects. * *@paramargsTheobjectweareextractingvaluesfrom *@paramnameThenameofthepropertywearegetting. *@paramdefaultValueAnoptionalvaluetoreturnifthepropertyismissing *fromtheobject.Ifthisisnotspecifiedandthepropertyismissing,an *errorwillbethrown.
*/
function getArg(aArgs, aName, aDefaultValue) { if (aName in aArgs) { return aArgs[aName];
} elseif (arguments.length === 3) { return aDefaultValue;
} thrownew Error('"' + aName + '" is a required argument.');
// Split the path into parts between `/` characters. This is much faster than // using `.split(/\/+/g)`. const parts = [];
let start = 0;
let i = 0; while (true) {
start = i;
i = path.indexOf("/", start); if (i === -1) {
parts.push(path.slice(start)); break;
} else {
parts.push(path.slice(start, i)); while (i < path.length && path[i] === "/") {
i++;
}
}
}
let up = 0; for (i = parts.length - 1; i >= 0; i--) { const part = parts[i]; if (part === ".") {
parts.splice(i, 1);
} elseif (part === "..") {
up++;
} elseif (up > 0) { if (part === "") { // The first part is blank if the path is absolute. Trying to go // above the root is a no-op. Therefore we can remove all '..' parts // directly after the root.
parts.splice(i + 1, up);
up = 0;
} else {
parts.splice(i, 2);
up--;
}
}
}
path = parts.join("/");
/** *MakeapathrelativetoaURLoranotherpath. * *@paramaRootTherootpathorURL. *@paramaPathThepathorURLtobemaderelativetoaRoot.
*/
function relative(aRoot, aPath) { if (aRoot === "") {
aRoot = ".";
}
aRoot = aRoot.replace(/\/$/, "");
// It is possible for the path to be above the root. In this case, simply // checking whether the root is a prefix of the path won't work. Instead, we // need to remove components from the root one by one, until either we find // a prefix that fits, or we run out of components to remove.
let level = 0; while (aPath.indexOf(aRoot + "/") !== 0) { const index = aRoot.lastIndexOf("/"); if (index < 0) { return aPath;
}
// If the only part of the root that is left is the scheme (i.e. http://, // file:///, etc.), one or more slashes (/), or simply nothing at all, we // have exhausted all components, so the path is not relative to the root.
aRoot = aRoot.slice(0, index); if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { returnaPath; }
++level; }
// Make sure we add a "../" for each component we removed from the root. returnArray(level+1).join("../")+aPath.substr(aRoot.length+1); } exports.relative=relative;
if (sourceRoot) { // This follows what Chrome does. if (sourceRoot[sourceRoot.length - 1] !== "/" && sourceURL[0] !== "/") {
sourceRoot += "/";
} // The spec says: // Line 4: An optional source root, useful for relocating source // files on a server or removing repeated values in the // “sources” entry. This value is prepended to the individual // entries in the “source” field.
sourceURL = sourceRoot + sourceURL;
}
// Historically, SourceMapConsumer did not take the sourceMapURL as // a parameter. This mode is still somewhat supported, which is why // this code block is conditional. However, it's preferable to pass // the source map URL to SourceMapConsumer, so that this function // can implement the source URL resolution algorithm as outlined in // the spec. This block is basically the equivalent of: // new URL(sourceURL, sourceMapURL).toString() // ... except it avoids using URL, which wasn't available in the // older releases of node still supported by this library. // // The spec says: // If the sources are not absolute URLs after prepending of the // “sourceRoot”, the sources are resolved relative to the // SourceMap (like resolving script src in a html document). if (sourceMapURL) { const parsed = urlParse(sourceMapURL); if (!parsed) { thrownew Error("sourceMapURL could not be parsed");
} if (parsed.path) { // Strip the last path component, but keep the "/". const index = parsed.path.lastIndexOf("/"); if (index >= 0) {
parsed.path = parsed.path.substring(0, index + 1);
}
}
sourceURL = join(urlGenerate(parsed), sourceURL);
}
/** *Addasinglemappingfromoriginalsourcelineandcolumntothegenerated *source'slineandcolumnforthissourcemapbeingcreated.Themapping *objectshouldhavethefollowingproperties: * *-generated:Anobjectwiththegeneratedlineandcolumnpositions. *-original:Anobjectwiththeoriginallineandcolumnpositions. *-source:Theoriginalsourcefile(relativetothesourceRoot). *-name:Anoptionaloriginaltokennameforthismapping.
*/
addMapping(aArgs) { const generated = util.getArg(aArgs, "generated"); const original = util.getArg(aArgs, "original", null);
let source = util.getArg(aArgs, "source", null);
let name = util.getArg(aArgs, "name", null);
if (!this._skipValidation) { this._validateMapping(generated, original, source, name);
}
if (source != null) {
source = String(source); if (!this._sources.has(source)) { this._sources.add(source);
}
}
if (name != null) {
name = String(name); if (!this._names.has(name)) { this._names.add(name);
}
}
this._mappings.add({
generatedLine: generated.line,
generatedColumn: generated.column,
originalLine: original != null && original.line,
originalColumn: original != null && original.column,
source,
name
});
}
/** *Setthesourcecontentforasourcefile.
*/
setSourceContent(aSourceFile, aSourceContent) {
let source = aSourceFile; if (this._sourceRoot != null) {
source = util.relative(this._sourceRoot, source);
}
if (aSourceContent != null) { // Add the source content to the _sourcesContents map. // Create a new _sourcesContents map if the property is null. if (!this._sourcesContents) { this._sourcesContents = Object.create(null);
} this._sourcesContents[util.toSetString(source)] = aSourceContent;
} elseif (this._sourcesContents) { // Remove the source file from the _sourcesContents map. // If the _sourcesContents map is empty, set the property to null. deletethis._sourcesContents[util.toSetString(source)]; if (Object.keys(this._sourcesContents).length === 0) { this._sourcesContents = null;
}
}
}
/** *Appliesthemappingsofasub-source-mapforaspecificsourcefiletothe *sourcemapbeinggenerated.Eachmappingtothesuppliedsourcefileis *rewrittenusingthesuppliedsourcemap.Note:Theresolutionforthe *resultingmappingsistheminimiumofthismapandthesuppliedmap. * *@paramaSourceMapConsumerThesourcemaptobeapplied. *@paramaSourceFileOptional.Thefilenameofthesourcefile. *Ifomitted,SourceMapConsumer'sfilepropertywillbeused. *@paramaSourceMapPathOptional.Thedirnameofthepathtothesourcemap *tobeapplied.Ifrelative,itisrelativetotheSourceMapConsumer. *Thisparameterisneededwhenthetwosourcemapsaren'tinthesame *directory,andthesourcemaptobeappliedcontainsrelativesource *paths.Ifso,thoserelativesourcepathsneedtoberewritten *relativetotheSourceMapGenerator.
*/
applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
let sourceFile = aSourceFile; // If aSourceFile is omitted, we will use the file property of the SourceMap if (aSourceFile == null) { if (aSourceMapConsumer.file == null) { thrownew Error( "SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+ 'or the source map\'s "file" property. Both were omitted.'
);
}
sourceFile = aSourceMapConsumer.file;
} const sourceRoot = this._sourceRoot; // Make "sourceFile" relative if an absolute Url is passed. if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
} // Applying the SourceMap can add and remove items from the sources and // the names array. const newSources = this._mappings.toArray().length > 0
? new ArraySet()
: this._sources; const newNames = new ArraySet();
// Find mappings for the "sourceFile" this._mappings.unsortedForEach(function(mapping) { if (mapping.source === sourceFile && mapping.originalLine != null) { // Check if it can be mapped by the source map, then update the mapping. const original = aSourceMapConsumer.originalPositionFor({
line: mapping.originalLine,
column: mapping.originalColumn
}); if (original.source != null) { // Copy mapping
mapping.source = original.source; if (aSourceMapPath != null) {
mapping.source = util.join(aSourceMapPath, mapping.source);
} if (sourceRoot != null) {
mapping.source = util.relative(sourceRoot, mapping.source);
}
mapping.originalLine = original.line;
mapping.originalColumn = original.column; if (original.name != null) {
mapping.name = original.name;
}
}
}
/** *Amappingcanhaveoneofthethreelevelsofdata: * *1.Justthegeneratedposition. *2.TheGeneratedposition,originalposition,andoriginalsource. *3.Generatedandoriginalposition,originalsource,aswellasaname *token. * *Tomaintainconsistency,wevalidatethatanynewmappingbeingaddedfalls *intooneofthesecategories.
*/
_validateMapping(aGenerated, aOriginal, aSource, aName) { // When aOriginal is truthy but has empty values for .line and .column, // it is most likely a programmer error. In this case we throw a very // specific error message to try to guide them the right way. // For example: https://github.com/Polymer/polymer-bundler/pull/519 if (aOriginal && typeof aOriginal.line !== "number" && typeof aOriginal.column !== "number") { thrownew Error( "original.line and original.column are not numbers -- you probably meant to omit " + "the original mapping entirely and only map the generated position. If so, pass " + "null for the original mapping instead of an object with empty or null values."
);
}
/** *Serializetheaccumulatedmappingsintothestreamofbase64VLQs *specifiedbythesourcemapformat.
*/
_serializeMappings() {
let previousGeneratedColumn = 0;
let previousGeneratedLine = 1;
let previousOriginalColumn = 0;
let previousOriginalLine = 0;
let previousName = 0;
let previousSource = 0;
let result = "";
let next;
let mapping;
let nameIdx;
let sourceIdx;
const mappings = this._mappings.toArray(); for (let i = 0, len = mappings.length; i < len; i++) {
mapping = mappings[i];
next = "";
if (mapping.generatedLine !== previousGeneratedLine) {
previousGeneratedColumn = 0; while (mapping.generatedLine !== previousGeneratedLine) {
next += ";";
previousGeneratedLine++;
}
} elseif (i > 0) { if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { continue;
}
next += ",";
}
next += base64VLQ.encode(mapping.generatedColumn
- previousGeneratedColumn);
previousGeneratedColumn = mapping.generatedColumn;
if (mapping.source != null) {
sourceIdx = this._sources.indexOf(mapping.source);
next += base64VLQ.encode(sourceIdx - previousSource);
previousSource = sourceIdx;
// lines are stored 0-based in SourceMap spec version 3
next += base64VLQ.encode(mapping.originalLine - 1
- previousOriginalLine);
previousOriginalLine = mapping.originalLine - 1;
next += base64VLQ.encode(mapping.originalColumn
- previousOriginalColumn);
previousOriginalColumn = mapping.originalColumn;
if (mapping.name != null) {
nameIdx = this._names.indexOf(mapping.name);
next += base64VLQ.encode(nameIdx - previousName);
previousName = nameIdx;
}
}
/** *Recursiveimplementationofbinarysearch. * *@paramaLowIndiceshereandlowerdonotcontaintheneedle. *@paramaHighIndiceshereandhigherdonotcontaintheneedle. *@paramaNeedleTheelementbeingsearchedfor. *@paramaHaystackThenon-emptyarraybeingsearched. *@paramaCompareFunctionwhichtakestwoelementsandreturns-1,0,or1. *@paramaBiasEither'binarySearch.GREATEST_LOWER_BOUND'or *'binarySearch.LEAST_UPPER_BOUND'.Specifieswhethertoreturnthe *closestelementthatissmallerthanorgreaterthantheoneweare *searchingfor,respectively,iftheexactelementcannotbefound.
*/
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { // This function terminates when one of the following is true: // // 1. We find the exact element we are looking for. // // 2. We did not find the exact element, but we can return the index of // the next-closest element. // // 3. We did not find the exact element, and there is no next-closest // element than the one we are searching for, so we return -1. const mid = Math.floor((aHigh - aLow) / 2) + aLow; const cmp = aCompare(aNeedle, aHaystack[mid], true); if (cmp === 0) { // Found the element we are looking for. return mid;
} elseif (cmp > 0) { // Our needle is greater than aHaystack[mid]. if (aHigh - mid > 1) { // The element is in the upper half. return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
}
// The exact needle element was not found in this haystack. Determine if // we are in termination case (3) or (2) and return the appropriate thing. if (aBias == exports.LEAST_UPPER_BOUND) { return aHigh < aHaystack.length ? aHigh : -1;
} return mid;
}
// Our needle is less than aHaystack[mid]. if (mid - aLow > 1) { // The element is in the lower half. return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
}
// we are in termination case (3) or (2) and return the appropriate thing. if (aBias == exports.LEAST_UPPER_BOUND) { return mid;
} return aLow < 0 ? -1 : aLow;
}
// We have found either the exact element, or the next-closest element than // the one we are searching for. However, there may be more than one such // element. Make sure we always return the smallest of these. while(index-1>=0){ if(aCompare(aHaystack[index],aHaystack[index-1],true)!==0){ break; } --index; }
varempty$1= var empty$1 = /*#__PURE__*/Object.freeze({
__proto__: null, default: empty
});
var require$$0 = /*@__PURE__*/getAugmentedNamespace(empty$1);
// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE.
// resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0
var up = 0; for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i]; if (last === '.') {
parts.splice(i, 1);
} elseif (last === '..') {
parts.splice(i, 1);
up++;
} elseif (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to) // posix version
function resolve() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : '/';
// Skip empty and invalid entries if (typeof path !== 'string') { thrownew TypeError('Arguments to path.resolve must be strings');
} elseif (!path) { continue;
}
if (!path && !isPathAbsolute) {
path = '.';
} if (path && trailingSlash) {
path += '/';
}
return (isPathAbsolute ? '/' : '') + path;
} // posix version
function isAbsolute(path) { return path.charAt(0) === '/';
}
// posix version
function join() {
var paths = Array.prototype.slice.call(arguments, 0); return normalize(filter(paths, function(p, index) { if (typeof p !== 'string') { thrownew TypeError('Arguments to path.join must be strings');
} return p;
}).join('/'));
}
// path.relative(from, to) // posix version
function relative(from, to) {
from = resolve(from).substr(1);
to = resolve(to).substr(1);
function trim(arr) {
var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break;
}
var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break;
}
if (start > end) return []; return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) {
samePartsLength = i; break;
}
}
var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
function dirname(path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) { // No dirname whatsoever return'.';
}
if (dir) { // It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
}
function basename(path, ext) {
var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
} return f;
}
function extname(path) { return splitPath(path)[3];
}
var path = {
extname: extname,
basename: basename,
dirname: dirname,
sep: sep,
delimiter: delimiter,
relative: relative,
join: join,
isAbsolute: isAbsolute,
normalize: normalize,
resolve: resolve
};
function filter (xs, f) { if (xs.filter) return xs.filter(f);
var res = []; for (var i = 0; i < xs.length; i++) { if (f(xs[i], i, xs)) res.push(xs[i]);
} return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b' ?
function (str, start, len) { return str.substr(start, len) } :
function (str, start, len) { if (start < 0) start = str.length + start; return str.substr(start, len);
}
;
class SourceMapConsumer {
constructor(aSourceMap, aSourceMapURL) { // If the constructor was called by super(), just return Promise<this>. // Yes, this is a hack to retain the pre-existing API of the base-class // constructor also being an async factory function. if (aSourceMap == INTERNAL) { return Promise.resolve(this);
}
/** *Constructanew`SourceMapConsumer`from`rawSourceMap`and`sourceMapUrl` *(seethe`SourceMapConsumer`constructorfordetails.Then,invokethe`async *functionf(SourceMapConsumer)->T`withthenewlyconstructedconsumer,wait *for`f`tocomplete,call`destroy`ontheconsumer,andreturn`f`'sreturn *value. * *Youmustnotusetheconsumerafter`f`completes! * *Byusing`with`,youdonothavetoremembertomanuallycall`destroy`on *theconsumer,sinceitwillbecalledautomaticallyonce`f`completes. * *```js *constxSquared=awaitSourceMapConsumer.with( *myRawSourceMap, *null, *asyncfunction(consumer){ *// Use `consumer` inside here and don't worry about remembering *// to call `destroy`. * *constx=awaitwhatever(consumer); *returnx*x; *} *); * *// You may not use that `consumer` anymore out here; it has *// been destroyed. But you can use `xSquared`. *console.log(xSquared); *```
*/ static async with(rawSourceMap, sourceMapUrl, f) { const consumer = await new SourceMapConsumer(rawSourceMap, sourceMapUrl); try { return await f(consumer);
} finally {
consumer.destroy();
}
}
const version = util.getArg(sourceMap, "version");
let sources = util.getArg(sourceMap, "sources"); // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which // requires the array) to play nice here. const names = util.getArg(sourceMap, "names", []);
let sourceRoot = util.getArg(sourceMap, "sourceRoot", null); const sourcesContent = util.getArg(sourceMap, "sourcesContent", null); const mappings = util.getArg(sourceMap, "mappings"); const file = util.getArg(sourceMap, "file", null);
// Once again, Sass deviates from the spec and supplies the version as a // string rather than a number, so we use loose equality checking here. if (version != that._version) { thrownew Error("Unsupported version: " + version);
}
if (sourceRoot) {
sourceRoot = util.normalize(sourceRoot);
}
sources = sources
.map(String) // Some source maps produce relative source paths like "./foo.js" instead of // "foo.js". Normalize these first so that future comparisons will succeed. // See bugzil.la/1090768.
.map(util.normalize) // Always ensure that absolute sources are internally stored relative to // the source root, if the source root is absolute. Not doing this would // be particularly problematic when the source root is a prefix of the // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
.map(function(source) { return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
? util.relative(sourceRoot, source)
: source;
});
// Pass `true` below to allow duplicate names and sources. While source maps // are intended to be compressed and deduplicated, the TypeScript compiler // sometimes generates source maps with duplicates in them. See Github issue // #72 and bugzil.la/889492.
that._names = ArraySet.fromArray(names.map(String), true);
that._sources = ArraySet.fromArray(sources, true);
/** *Utilityfunctiontofindtheindexofasource.Returns-1ifnot *found.
*/
_findSourceIndex(aSource) {
let relativeSource = aSource; if (this.sourceRoot != null) {
relativeSource = util.relative(this.sourceRoot, relativeSource);
}
if (this._sources.has(relativeSource)) { returnthis._sources.indexOf(relativeSource);
}
// Maybe aSource is an absolute URL as returned by |sources|. In // this case we can't simply undo the transform. for (let i = 0; i < this._absoluteSources.length; ++i) { if (this._absoluteSources[i] == aSource) { return i;
}
}
if (!mappingsPtr) { const error = this._wasm.exports.get_last_error();
let msg = `Error parsing mappings (code ${error}): `;
// XXX: keep these error codes in sync with `fitzgen/source-map-mappings`. switch (error) { case1:
msg += "the mappings contained a negative line, column, source index, or name index"; break; case2:
msg += "the mappings contained a number larger than 2**32"; break; case3:
msg += "reached EOF while in the middle of parsing a VLQ"; break; case4:
msg += "invalid base 64 character while parsing a VLQ"; break; default:
msg += "unknown error code"; break;
}
const index = this._findSourceIndex(aSource); if (index >= 0) { returnthis.sourcesContent[index];
}
let relativeSource = aSource; if (this.sourceRoot != null) {
relativeSource = util.relative(this.sourceRoot, relativeSource);
}
let url; if (this.sourceRoot != null
&& (url = util.urlParse(this.sourceRoot))) { // XXX: file:// URIs and absolute paths lead to unexpected behavior for // many users. We can help them out when they expect file:// URIs to // behave like it would if they were running a local HTTP server. See // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. const fileUriAbsPath = relativeSource.replace(/^file:\/\//, ""); if (url.scheme == "file"
&& this._sources.has(fileUriAbsPath)) { returnthis.sourcesContent[this._sources.indexOf(fileUriAbsPath)];
}
// This function is used recursively from // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we // don't want to throw if we can't find the source - we just want to // return null, so we provide a flag to exit gracefully. if (nullOnMissing) { return null;
}
thrownew Error('"' + relativeSource + '" is not in the SourceMap.');
}
that._sources = new ArraySet();
that._names = new ArraySet();
that.__generatedMappings = null;
that.__originalMappings = null;
that.__generatedMappingsUnsorted = null;
that.__originalMappingsUnsorted = null;
let lastOffset = {
line: -1,
column: 0
}; return Promise.all(sections.map(s => { if (s.url) { // The url field will require support for asynchronicity. // See https://github.com/mozilla/source-map/issues/16 thrownew Error("Support for url field in sections not implemented.");
} const offset = util.getArg(s, "offset"); const offsetLine = util.getArg(offset, "line"); const offsetColumn = util.getArg(offset, "column");
if (offsetLine < lastOffset.line ||
(offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { thrownew Error("Section offsets must be ordered and non-overlapping.");
}
lastOffset = offset;
const cons = new SourceMapConsumer(util.getArg(s, "map"), aSourceMapURL); return cons.then(consumer => { return {
generatedOffset: { // The offset fields are 0-based, but we use 1-based indices when // encoding/decoding from VLQ.
generatedLine: offsetLine + 1,
generatedColumn: offsetColumn + 1
},
consumer
};
});
})).then(s => {
that._sections = s; return that;
});
});
}
// `__generatedMappings` and `__originalMappings` are arrays that hold the // parsed mapping coordinates from the source map's "mappings" attribute. They // are lazily instantiated, accessed via the `_generatedMappings` and // `_originalMappings` getters respectively, and we only parse the mappings // and create these arrays once queried for a source location. We jump through // these hoops because there can be many thousands of mappings, and parsing // them is expensive, so we only want to do it if we must. // // Each object in the arrays is of the form: // // { // generatedLine: The line number in the generated code, // generatedColumn: The column number in the generated code, // source: The path to the original source file that generated this // chunk of code, // originalLine: The line number in the original source that // corresponds to this chunk of generated code, // originalColumn: The column number in the original source that // corresponds to this chunk of generated code, // name: The name of the original symbol which generated this chunk of // code. // } // // All properties except for `generatedLine` and `generatedColumn` can be // `null`. // // `_generatedMappings` is ordered by the generated positions. // // `_originalMappings` is ordered by the original positions.
get _generatedMappings() { if (!this.__generatedMappings) { this._sortGeneratedMappings();
}
returnthis.__generatedMappings;
}
get _originalMappings() { if (!this.__originalMappings) { this._sortOriginalMappings();
}
returnthis.__originalMappings;
}
get _generatedMappingsUnsorted() { if (!this.__generatedMappingsUnsorted) { this._parseMappings(this._mappings, this.sourceRoot);
}
returnthis.__generatedMappingsUnsorted;
}
get _originalMappingsUnsorted() { if (!this.__originalMappingsUnsorted) { this._parseMappings(this._mappings, this.sourceRoot);
}
// Find the section containing the generated position we're trying to map // to an original position. const sectionIndex = binarySearch.search(needle, this._sections,
function(aNeedle, section) { const cmp = aNeedle.generatedLine - section.generatedOffset.generatedLine; if (cmp) { return cmp;
}
// Only consider this section if the requested source is in the list of // sources of the consumer. if (section.consumer._findSourceIndex(util.getArg(aArgs, "source")) === -1) { continue;
} const generatedPosition = section.consumer.generatedPositionFor(aArgs); if (generatedPosition) { const ret = {
line: generatedPosition.line +
(section.generatedOffset.generatedLine - 1),
column: generatedPosition.column +
(section.generatedOffset.generatedLine === generatedPosition.line
? section.generatedOffset.generatedColumn - 1
: 0)
}; return ret;
}
}
// TODO: test if null is correct here. The original code used // `source`, which would actually have gotten used as null because // var's get hoisted. // See: https://github.com/mozilla/source-map/issues/333
let source = util.computeSourceURL(section.consumer.sourceRoot, null, this._sourceMapURL); this._sources.add(source);
source = this._sources.indexOf(source);
let name = null; if (mapping.name) { this._names.add(mapping.name);
name = this._names.indexOf(mapping.name);
}
// The mappings coming from the consumer for the section have // generated positions relative to the start of the section, so we // need to offset them to be relative to the start of the concatenated // generated file. const adjustedMapping = {
source,
generatedLine: mapping.generatedLine +
(section.generatedOffset.generatedLine - 1),
generatedColumn: mapping.generatedColumn +
(section.generatedOffset.generatedLine === mapping.generatedLine
? section.generatedOffset.generatedColumn - 1
: 0),
originalLine: mapping.originalLine,
originalColumn: mapping.originalColumn,
name
};
let mappings; switch (order) { case SourceMapConsumer.GENERATED_ORDER:
mappings = this._generatedMappings; break; case SourceMapConsumer.ORIGINAL_ORDER:
mappings = this._originalMappings; break; default: thrownew Error("Unknown order of iteration.");
}
/** *Findthemappingthatbestmatchesthehypothetical"needle"mappingthat *wearesearchingforinthegiven"haystack"ofmappings.
*/
_findMapping(aNeedle, aMappings, aLineName,
aColumnName, aComparator, aBias) { // To return the position we are searching for, we must first find the // mapping for the given position and then return the opposite position it // points to. Because the mappings are sorted, we can use binary search to // find the best mapping.
if (aNeedle[aLineName] <= 0) { thrownew TypeError("Line must be greater than or equal to 1, got "
+ aNeedle[aLineName]);
} if (aNeedle[aColumnName] < 0) { thrownew TypeError("Column must be greater than or equal to 0, got "
+ aNeedle[aColumnName]);
}
allGeneratedPositionsFor(aArgs) { const line = util.getArg(aArgs, "line");
// When there is no exact match, BasicSourceMapConsumer.prototype._findMapping // returns the index of the closest mapping less than the needle. By // setting needle.originalColumn to 0, we thus find the last mapping for // the given line, provided such a mapping exists. const needle = {
source: util.getArg(aArgs, "source"),
originalLine: line,
originalColumn: util.getArg(aArgs, "column", 0)
};
if (needle.originalLine < 1) { thrownew Error("Line numbers must be >= 1");
}
if (needle.originalColumn < 0) { thrownew Error("Column numbers must be >= 0");
}
const mappings = [];
let index = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn",
util.compareByOriginalPositions,
binarySearch.LEAST_UPPER_BOUND); if (index >= 0) {
let mapping = this._originalMappings[index];
if (aArgs.column === undefined) { const originalLine = mapping.originalLine;
// Iterate until either we run out of mappings, or we run into // a mapping for a different line than the one we found. Since // mappings are sorted, this is guaranteed to find all mappings for // the line we found. while (mapping && mapping.originalLine === originalLine) {
let lastColumn = mapping.lastGeneratedColumn; if (this._computedColumnSpans && lastColumn === null) {
lastColumn = Infinity;
}
mappings.push({
line: util.getArg(mapping, "generatedLine", null),
column: util.getArg(mapping, "generatedColumn", null),
lastColumn,
});
// Iterate until either we run out of mappings, or we run into // a mapping for a different line than the one we were searching for. // Since mappings are sorted, this is guaranteed to find all mappings for // the line we are searching for. while (mapping &&
mapping.originalLine === line &&
mapping.originalColumn == originalColumn) {
let lastColumn = mapping.lastGeneratedColumn; if (this._computedColumnSpans && lastColumn === null) {
lastColumn = Infinity;
}
mappings.push({
line: util.getArg(mapping, "generatedLine", null),
column: util.getArg(mapping, "generatedColumn", null),
lastColumn,
});
mapping = this._originalMappings[++index];
}
}
}
return mappings;
}
destroy() { for (let i = 0; i < this._sections.length; i++) { this._sections[i].consumer.destroy();
}
}
}
sourceMapConsumer.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
/* *Cheattogetaroundinter-twingledclasses.`factory()`canbeattheend *whereithasaccesstonon-hoistedclasses,butitgetshoisteditself.
*/
function _factory(aSourceMap, aSourceMapURL) {
let sourceMap = aSourceMap; if (typeof aSourceMap === "string") {
sourceMap = util.parseSourceMapInput(aSourceMap);
}
const consumer = sourceMap.sections != null
? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL)
: new BasicSourceMapConsumer(sourceMap, aSourceMapURL); return Promise.resolve(consumer);
}
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). const REGEX_NEWLINE = /(\r?\n)/;
// Newline character code for charCodeAt() comparisons const NEWLINE_CODE = 10;
// Private symbol for identifying `SourceNode`s when multiple versions of // the source-map library are loaded. This MUST NOT CHANGE across // versions! const isSourceNode = "$$$isSourceNode$$$";
/** *CreatesaSourceNodefromgeneratedcodeandaSourceMapConsumer. * *@paramaGeneratedCodeThegeneratedcode *@paramaSourceMapConsumerTheSourceMapforthegeneratedcode *@paramaRelativePathOptional.Thepaththatrelativesourcesinthe *SourceMapConsumershouldberelativeto.
*/ static fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { // The SourceNode we want to fill with the generated code // and the SourceMap const node = new SourceNode();
// All even indices of this array are one line of the generated code, // while all odd indices are the newlines between two adjacent lines // (since `REGEX_NEWLINE` captures its match). // Processed fragments are accessed by calling `shiftNextLine`. const remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
let remainingLinesIndex = 0; const shiftNextLine = function() { const lineContents = getNextLine(); // The last line of a file might not have a newline. const newLine = getNextLine() || ""; return lineContents + newLine;
// We need to remember the position of "remainingLines"
let lastGeneratedLine = 1, lastGeneratedColumn = 0;
// The generate SourceNodes we need a code range. // To extract it current and last mapping is used. // Here we store the last mapping.
let lastMapping = null;
let nextLine;
aSourceMapConsumer.eachMapping(function(mapping) { if (lastMapping !== null) { // We add the code from "lastMapping" to "mapping": // First check if there is a new line in between. if (lastGeneratedLine < mapping.generatedLine) { // Associate first line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
lastGeneratedLine++;
lastGeneratedColumn = 0; // The remaining code is added without mapping
} else { // There is no new line in between. // Associate the code between "lastGeneratedColumn" and // "mapping.generatedColumn" with "lastMapping"
nextLine = remainingLines[remainingLinesIndex] || ""; const code = nextLine.substr(0, mapping.generatedColumn -
lastGeneratedColumn);
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -
lastGeneratedColumn);
lastGeneratedColumn = mapping.generatedColumn;
addMappingWithCode(lastMapping, code); // No more remaining code, continue
lastMapping = mapping; return;
}
} // We add the generated code until the first mapping // to the SourceNode without any mapping. // Each line is added as separate string. while (lastGeneratedLine < mapping.generatedLine) {
node.add(shiftNextLine());
lastGeneratedLine++;
} if (lastGeneratedColumn < mapping.generatedColumn) {
nextLine = remainingLines[remainingLinesIndex] || "";
node.add(nextLine.substr(0, mapping.generatedColumn));
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);
lastGeneratedColumn = mapping.generatedColumn;
}
lastMapping = mapping;
}, this); // We have processed all mappings. if (remainingLinesIndex < remainingLines.length) { if (lastMapping) { // Associate the remaining code in the current line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
} // and add the remaining lines without any mapping
node.add(remainingLines.splice(remainingLinesIndex).join(""));
}
// Copy sourcesContent into SourceNode
aSourceMapConsumer.sources.forEach(function(sourceFile) { const content = aSourceMapConsumer.sourceContentFor(sourceFile); if (content != null) { if (aRelativePath != null) {
sourceFile = util.join(aRelativePath, sourceFile);
}
node.setSourceContent(sourceFile, content);
}
});
function requireWorkerUtils () { if (hasRequiredWorkerUtils) return workerUtils.exports;
hasRequiredWorkerUtils = 1;
(function (module) {
class WorkerDispatcher { #msgId = 1; #worker = null; // Map of message ids -> promise resolution functions, for dispatching worker responses #pendingCalls = new Map(); #url = "";
constructor(url) { this.#url = url;
}
start() { // When running in debugger jest test, we don't have access to ChromeWorker if (typeof ChromeWorker == "function") { this.#worker = new ChromeWorker(this.#url);
} else { this.#worker = new Worker(this.#url);
} this.#worker.onerror = err => {
console.error(`Error in worker ${this.#url}`, err.message);
}; this.#worker.addEventListener("message", this.#onMessage);
}
function asErrorMessage(error) { if (typeof error === "object" && error && "message" in error) { // Error can't be sent via postMessage, so be sure to convert to // string. return {
error: true,
message:
error.message +
(error.stack ? "\nStack in the worker:" + error.stack : ""),
metadata: error.metadata,
};
}
// This file was generated. Do not modify manually!
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
// This file was generated. Do not modify manually!
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
// These are a run-length and offset encoded representation of the
// Reserved word lists for various dialects of the language
var reservedWords = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum",
strict: "implements interface let package private protected public static yield",
strictBind: "eval arguments"
};
// And the keywords
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
var keywordRelationalOperator = /^in(stanceof)?$/;
// ## Character categories
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
// This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare.
function isInAstralSet(code, set) {
var pos = 0x10000; for (var i = 0; i < set.length; i += 2) {
pos += set[i]; if (pos > code) { returnfalse }
pos += set[i + 1]; if (pos >= code) { returntrue }
} returnfalse
}
// Test whether a given character code starts an identifier.
function isIdentifierStart(code, astral) { if (code < 65) { return code === 36 } if (code < 91) { returntrue } if (code < 97) { return code === 95 } if (code < 123) { returntrue } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } if (astral === false) { returnfalse } return isInAstralSet(code, astralIdentifierStartCodes)
}
// Test whether a given character is part of an identifier.
function isIdentifierChar(code, astral) { if (code < 48) { return code === 36 } if (code < 58) { returntrue } if (code < 65) { returnfalse } if (code < 91) { returntrue } if (code < 97) { return code === 95 } if (code < 123) { returntrue } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } if (astral === false) { returnfalse } return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
}
// ## Token types
// The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up.
// All token type variables start with an underscore, to make them // easy to recognize.
// The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // The `startsExpr` property is used to check if the token ends a // `yield` expression. It is set on all token types that either can // directly start an expression (like a quotation mark) or can // continue an expression (like the body of a string). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label.
var TokenType = function TokenType(label, conf) { if ( conf === void0 ) conf = {};
function binop(name, prec) { returnnew TokenType(name, {beforeExpr: true, binop: prec})
}
var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};
// Map keyword names to token types.
var keywords = {};
// Succinct definitions of keyword token types
function kw(name, options) { if ( options === void0 ) options = {};
options.keyword = name; return keywords[name] = new TokenType(name, options)
}
var types$1 = {
num: new TokenType("num", startsExpr),
regexp: new TokenType("regexp", startsExpr),
string: new TokenType("string", startsExpr),
name: new TokenType("name", startsExpr),
privateId: new TokenType("privateId", startsExpr),
eof: new TokenType("eof"),
// Punctuation token types.
bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
bracketR: new TokenType("]"),
braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
braceR: new TokenType("}"),
parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
parenR: new TokenType(")"),
comma: new TokenType(",", beforeExpr),
semi: new TokenType(";", beforeExpr),
colon: new TokenType(":", beforeExpr),
dot: new TokenType("."),
question: new TokenType("?", beforeExpr),
questionDot: new TokenType("?."),
arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"),
invalidTemplate: new TokenType("invalidTemplate"),
ellipsis: new TokenType("...", beforeExpr),
backQuote: new TokenType("`", startsExpr),
dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
// Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes.
function nextLineBreak(code, from, end) { if ( end === void0 ) end = code.length;
for (var i = from; i < end; i++) {
var next = code.charCodeAt(i); if (isNewLine(next))
{ return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 }
} return -1
}
var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
var ref = Object.prototype;
var hasOwnProperty = ref.hasOwnProperty;
var toString = ref.toString;
var SourceLocation = function SourceLocation(p, start, end) { this.start = start; this.end = end; if (p.sourceFile !== null) { this.source = p.sourceFile; }
};
// The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into.
function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) {
var nextBreak = nextLineBreak(input, cur, offset); if (nextBreak < 0) { returnnew Position(line, offset - cur) }
++line;
cur = nextBreak;
}
}
// A second argument must be given to configure the parser process. // These options are recognized (only `ecmaVersion` is required):
var defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must be // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` // (the latest version the library supports). This influences // support for strict mode, the set of reserved words, and support // for new syntax features.
ecmaVersion: null, // `sourceType` indicates the mode the code should be parsed in. // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations.
sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called // when a semicolon is automatically inserted. It will be passed // the position of the comma as an offset, and if `locations` is // enabled, it is given the location as a `{line, column}` object // as second argument.
onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas.
onTrailingComma: null, // By default, reserved words are only enforced if ecmaVersion >= 5. // Set `allowReserved` to a boolean value to explicitly turn this on // an off. When this option has the value "never", reserved words // and keywords can also not be used as property names.
allowReserved: null, // When enabled, a return at the top level is not considered an // error.
allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program, and an import.meta expression // in a script isn't considered an error.
allowImportExportEverywhere: false, // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. // When enabled, await identifiers are allowed to appear at the top-level scope, // but they are still not allowed in non-async functions.
allowAwaitOutsideFunction: null, // When enabled, super identifiers are not constrained to // appearing in methods and do not raise an error when they appear elsewhere.
allowSuperOutsideMethod: null, // When enabled, hashbang directive in the beginning of file is // allowed and treated as a line comment. Enabled by default when // `ecmaVersion` >= 2023.
allowHashBang: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes.
locations: false, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same // format as tokens returned from `tokenizer().getToken()`. Note // that you are not allowed to call the parser from the // callback—that will corrupt its internal state.
onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, // end)` parameters whenever a comment is skipped. `block` is a // boolean indicating whether this is a block (`/* */`) comment, // `text` is the content of the comment, and `start` and `end` are // character offsets that denote the start and end of the comment. // When the `locations` option is on, two more parameters are // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state.
onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than // the `loc` object, which holds line/column data. To also add a // [semi-standardized][range] `range` property holding a `[start, // end]` array with the same numbers, set the `ranges` option to // `true`. // // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
ranges: false, // It is possible to parse multiple files into a single AST by // passing the tree produced by parsing the first file as // `program` option in subsequent parses. This will add the // toplevel forms of the parsed file to the `Program` (top) node // of an existing parse tree.
program: null, // When `locations` is on, you can pass this to record the source // file in every node's `loc` object.
sourceFile: null, // This value, if given, is stored in every node, whether // `locations` is on or off.
directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes
preserveParens: false
};
// Interpret and default an options object
var warnedAboutEcmaVersion = false;
function getOptions(opts) {
var options = {};
for (var opt in defaultOptions)
{ options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; }
if (options.ecmaVersion === "latest") {
options.ecmaVersion = 1e8;
} elseif (options.ecmaVersion == null) { if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
warnedAboutEcmaVersion = true;
console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.");
}
options.ecmaVersion = 11;
} elseif (options.ecmaVersion >= 2015) {
options.ecmaVersion -= 2009;
}
// Used in checkLVal* and declareName to determine the type of a binding
var
BIND_NONE = 0, // Not a binding
BIND_VAR = 1, // Var-style binding
BIND_LEXICAL = 2, // Let- or const-style binding
BIND_FUNCTION = 3, // Function declaration
BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
// Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. this.containsEsc = false;
// Set up token state
// The current position of the tokenizer in the input. if (startPos) { this.pos = startPos; this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
} else { this.pos = this.lineStart = 0; this.curLine = 1;
}
// Properties of the current token: // Its type this.type = types$1.eof; // For tokens that include more information than their type, the value this.value = null; // Its start and end offset this.start = this.end = this.pos; // And, if locations are used, the {line, column} object // corresponding to those offsets this.startLoc = this.endLoc = this.curPosition();
// Position information for the previous token this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos;
// The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. this.context = this.initialContext(); this.exprAllowed = true;
// Figure out if it's a module code. this.inModule = options.sourceType === "module"; this.strict = this.inModule || this.strictDirective(this.pos);
// Used to signify the start of a potential arrow function this.potentialArrowAt = -1; this.potentialArrowInForAwait = false;
// Positions to delayed-check that yield/await does not exist in default parameters. this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; // Labels in scope. this.labels = []; // Thus-far undefined exports. this.undefinedExports = Object.create(null);
// If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
{ this.skipLineComment(2); }
// Scope tracking for duplicate variable names (see scope.js) this.scopeStack = []; this.enterScope(SCOPE_TOP);
// For RegExp validation this.regexpState = null;
// The stack of private names. // Each element has two properties: 'declared' and 'used'. // When it exited from the outermost class definition, all used private names must be declared. this.privateNameStack = [];
};
// Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node.
pp$8.isLet=function(context){ if(this.options.ecmaVersion<6||!this.isContextual("let")){returnfalse} skipWhiteSpace.lastIndex=this.pos; varskip=skipWhiteSpace.exec(this.input); varnext=this.pos+skip[0].length,nextCh=this.input.charCodeAt(next); // For ambiguous cases, determine if a LexicalDeclaration (or only a // Statement) is allowed here. If context is not empty then only a Statement // is allowed. However, `let [` is an explicit negative lookahead for // ExpressionStatement, so special-case it first. if(nextCh===91||nextCh===92){returntrue}// '[', '/' if(context){returnfalse}
// Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help.
// Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity.
switch(starttype){ casetypes$1._break:casetypes$1._continue:returnthis.parseBreakContinueStatement(node,starttype.keyword) casetypes$1._debugger:returnthis.parseDebuggerStatement(node) casetypes$1._do:returnthis.parseDoStatement(node) casetypes$1._for:returnthis.parseForStatement(node) casetypes$1._function: // Function as sole body of either an if statement or a labeled statement // works, but not when it is part of a labeled statement that is the sole // body of an if statement. if((context&&(this.strict||context!=="if"&&context!=="label"))&&this.options.ecmaVersion>=6){this.unexpected();} returnthis.parseFunctionStatement(node,false,!context) casetypes$1._class: if(context){this.unexpected();} returnthis.parseClass(node,true) casetypes$1._if:returnthis.parseIfStatement(node) casetypes$1._return:returnthis.parseReturnStatement(node) casetypes$1._switch:returnthis.parseSwitchStatement(node) casetypes$1._throw:returnthis.parseThrowStatement(node) casetypes$1._try:returnthis.parseTryStatement(node) casetypes$1._const:casetypes$1._var: kind=kind||this.value; if(context&&kind!=="var"){this.unexpected();} returnthis.parseVarStatement(node,kind) casetypes$1._while:returnthis.parseWhileStatement(node) casetypes$1._with:returnthis.parseWithStatement(node) casetypes$1.braceL:returnthis.parseBlock(true,node) casetypes$1.semi:returnthis.parseEmptyStatement(node) casetypes$1._export: casetypes$1._import: if(this.options.ecmaVersion>10&&starttype===types$1._import){ skipWhiteSpace.lastIndex=this.pos; varskip=skipWhiteSpace.exec(this.input); varnext=this.pos+skip[0].length,nextCh=this.input.charCodeAt(next); if(nextCh===40||nextCh===46)// '(' or '.' {returnthis.parseExpressionStatement(node,this.parseExpression())} }
// If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: if(this.isAsyncFunction()){ if(context){this.unexpected();} this.next(); returnthis.parseFunctionStatement(node,true,!context) }
// Verify that there is an actual destination to break or // continue to. vari=0; for(;i<this.labels.length;++i){ varlab=this.labels[i]; if(node.label==null||lab.name===node.label.name){ if(lab.kind!=null&&(isBreak||lab.kind==="loop")){break} if(node.label&&isBreak){break} } } if(i===this.labels.length){this.raise(node.start,"Unsyntactic"+keyword);} returnthis.finishNode(node,isBreak?"BreakStatement":"ContinueStatement") };
// Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop.
pp$8.parseIfStatement=function(node){ this.next(); node.test=this.parseParenExpression(); // allow function declarations in branches, but only in non-strict mode node.consequent=this.parseStatement("if"); node.alternate=this.eat(types$1._else)?this.parseStatement("if"):null; returnthis.finishNode(node,"IfStatement") };
// Parse a function declaration or literal (depending on the // `statement & FUNC_STATEMENT`).
// Remove `allowExpressionBody` for 7.0.0, as it is only called with false pp$8.parseFunction=function(node,statement,allowExpressionBody,isAsync,forInit){ this.initFunction(node); if(this.options.ecmaVersion>=9||this.options.ecmaVersion>=6&&!isAsync){ if(this.type===types$1.star&&(statement&FUNC_HANGING_STATEMENT)) {this.unexpected();} node.generator=this.eat(types$1.star); } if(this.options.ecmaVersion>=8) {node.async=!!isAsync;}
if(statement&FUNC_STATEMENT){ node.id=(statement&FUNC_NULLABLE_ID)&&this.type!==types$1.name?null:this.parseIdent(); if(node.id&&!(statement&FUNC_HANGING_STATEMENT)) // If it is a regular function declaration in sloppy mode, then it is // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding // mode depends on properties of the current scope (see // treatFunctionsAsVar). {this.checkLValSimple(node.id,(this.strict||node.generator||node.async)?this.treatFunctionsAsVar?BIND_VAR:BIND_LEXICAL:BIND_FUNCTION);} }
// Parse element name if(keyName){ // 'async', 'get', 'set', or 'static' were not a keyword contextually. // The last token is any of those. Make it the element name. node.computed=false; node.key=this.startNodeAt(this.lastTokStart,this.lastTokStartLoc); node.key.name=keyName; this.finishNode(node.key,"Identifier"); }else{ this.parseClassElementName(node); }
// Parse element value if(ecmaVersion<13||this.type===types$1.parenL||kind!=="method"||isGenerator||isAsync){ varisConstructor=!node.static&&checkKeyName(node,"constructor"); varallowsDirectSuper=isConstructor&&constructorAllowsSuper; // Couldn't move this check into the 'parseClassMethod' method for backward compatibility. if(isConstructor&&kind!=="method"){this.raise(node.key.start,"Constructorcan'thaveget/setmodifier");} node.kind=isConstructor?"constructor":kind; this.parseClassMethod(node,isGenerator,isAsync,allowsDirectSuper); }else{ this.parseClassField(node); }
if(this.eat(types$1.eq)){ // To raise SyntaxError if 'arguments' exists in the initializer. varscope=this.currentThisScope(); varinClassFieldInit=scope.inClassFieldInit; scope.inClassFieldInit=true; field.value=this.parseMaybeAssign(); scope.inClassFieldInit=inClassFieldInit; }else{ field.value=null; } this.semicolon();
this.toAssignable(prop,isBinding); // Early error: // AssignmentRestProperty[Yield, Await] : // `...` DestructuringAssignmentTarget[Yield, Await] // // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. if( prop.type==="RestElement"&& (prop.argument.type==="ArrayPattern"||prop.argument.type==="ObjectPattern") ){ this.raise(prop.argument.start,"Unexpectedtoken"); } } break
case"Property": // AssignmentProperty has type === "Property" if(node.kind!=="init"){this.raise(node.key.start,"Objectpatterncan'tcontaingetterorsetter");} this.toAssignable(node.value,isBinding); break
// The following three functions all verify that a node is an lvalue — // something that can be bound, or assigned to. In order to do so, they perform // a variety of checks: // // - Check that none of the bound/assigned-to identifiers are reserved words. // - Record name declarations for bindings in the appropriate scope. // - Check duplicate argument names, if checkClashes is set. // // If a complex binding pattern is encountered (e.g., object and array // destructuring), the entire pattern is recursively checked. // // There are three versions of checkLVal*() appropriate for different // circumstances: // // - checkLValSimple() shall be used if the syntactic construct supports // nothing other than identifiers and member expressions. Parenthesized // expressions are also correctly handled. This is generally appropriate for // constructs for which the spec says // // > It is a Syntax Error if AssignmentTargetType of [the production] is not // > simple. // // It is also appropriate for checking if an identifier is valid and not // defined elsewhere, like import declarations or function/class identifiers. // // Examples where this is used include: // a += …; // import a from '…'; // where a is the node to be checked. // // - checkLValPattern() shall be used if the syntactic construct supports // anything checkLValSimple() supports, as well as object and array // destructuring patterns. This is generally appropriate for constructs for // which the spec says // // > It is a Syntax Error if [the production] is neither an ObjectLiteral nor // > an ArrayLiteral and AssignmentTargetType of [the production] is not // > simple. // // Examples where this is used include: // (a = …); // const a = …; // try { … } catch (a) { … } // where a is the node to be checked. // // - checkLValInnerPattern() shall be used if the syntactic construct supports // anything checkLValPattern() supports, as well as default assignment // patterns, rest elements, and other constructs that may appear within an // object or array destructuring pattern. // //Asaspecialcase,functionparametersalsousecheckLValInnerPattern(), //astheyalsosupportdefaultsandrestconstructs. // //Thesefunctionsdeliberatelysupportbothassignmentandbindingconstructs, //asthelogicforbothisexceedinglysimilar.Ifthenodeisthetargetof //anassignment,thenbindingTypeshouldbesettoBIND_NONE.Otherwise,it //shouldbesettotheappropriateBIND_*constant,likeBIND_VARor //BIND_LEXICAL. // //Ifthefunctioniscalledwithanon-BIND_NONEbindingType,then //additionallyacheckClashesobjectmaybespecifiedtoallowcheckingfor //duplicateargumentnames.checkClashesisignorediftheprovidedconstruct //isanassignment(i.e.,bindingTypeisBIND_NONE).
if(isExpression){ node.body=this.parseMaybeAssign(forInit); node.expression=true; this.checkParams(node,false); }else{ varnonSimple=this.options.ecmaVersion>=7&&!this.isSimpleParamList(node.params); if(!oldStrict||nonSimple){ useStrict=this.strictDirective(this.end); // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` // or `arguments`. if(useStrict&&nonSimple) {this.raiseRecoverable(node.start,"Illegal'usestrict'directiveinfunctionwithnon-simpleparameterlist");} } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). varoldLabels=this.labels; this.labels=[]; if(useStrict){this.strict=true;}
// Add the params to varDeclaredNames to ensure that an error is thrown // if a let/const declaration in the function clashes with one of the params. this.checkParams(node,!oldStrict&&!useStrict&&!isArrowFunction&&!isMethod&&this.isSimpleParamList(node.params)); // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' if(this.strict&&node.id){this.checkLValSimple(node.id,BIND_OUTSIDE);} node.body=this.parseBlock(false,undefined,useStrict&&!oldStrict); node.expression=false; this.adaptDirectivePrologue(node.body.body); this.labels=oldLabels; } this.exitScope(); };
// Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with // nothing in between them to be parsed as `null` (which is needed // for array literals).
if(state.eat(0x5C if (state.eat(0x5C /* \ */)) { if (this.regexp_eatClassEscape(state)) { returntrue
} if (state.switchU) { // Make the same message as V8.
var ch$1 = state.current(); if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
state.raise("Invalid class escape");
}
state.raise("Invalid escape");
}
state.pos = start;
}
var ch = state.current(); if (ch !== 0x5D /* ] */) {
state.lastIntValue = ch;
state.advance(); returntrue
}
// Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer.
var Token = function Token(p) { this.type = p.type; this.value = p.value; this.start = p.start; this.end = p.end; if (p.options.locations)
{ this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } if (p.options.ranges)
{ this.range = [p.start, p.end]; }
};
// ## Tokenizer
var pp = Parser.prototype;
// Move to the next token
pp.next = function(ignoreEscapeSequenceInKeyword) { if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
{ this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } if (this.options.onToken)
{ this.options.onToken(new Token(this)); }
pp.readToken = function(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92/* '\' */)
{ returnthis.readWord() }
returnthis.getTokenFromCode(code)
};
pp.fullCharCodeAtPos = function() {
var code = this.input.charCodeAt(this.pos); if (code <= 0xd7ff || code >= 0xdc00) { return code }
var next = this.input.charCodeAt(this.pos + 1); return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00
};
pp.skipBlockComment = function() {
var startLoc = this.options.onComment && this.curPosition();
var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } this.pos = end + 2; if (this.options.locations) { for (var nextBreak = (void0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) {
++this.curLine;
pos = this.lineStart = nextBreak;
}
} if (this.options.onComment)
{ this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
startLoc, this.curPosition()); }
};
pp.skipLineComment = function(startSkip) {
var start = this.pos;
var startLoc = this.options.onComment && this.curPosition();
var ch = this.input.charCodeAt(this.pos += startSkip); while (this.pos < this.input.length && !isNewLine(ch)) {
ch = this.input.charCodeAt(++this.pos);
} if (this.options.onComment)
{ this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
startLoc, this.curPosition()); }
};
// Called at the start of the parse and after every token. Skips // whitespace and comments, and.
// Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position.
// This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. //
pp.readToken_dot = function() {
var next = this.input.charCodeAt(this.pos + 1); if (next >= 48 && next <= 57) { returnthis.readNumber(true) }
var next2 = this.input.charCodeAt(this.pos + 2); if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' this.pos += 3; returnthis.finishToken(types$1.ellipsis)
} else {
++this.pos; returnthis.finishToken(types$1.dot)
}
};
pp.readToken_slash = function() { // '/'
var next = this.input.charCodeAt(this.pos + 1); if (this.exprAllowed) { ++this.pos; returnthis.readRegexp() } if (next === 61) { returnthis.finishOp(types$1.assign, 2) } returnthis.finishOp(types$1.slash, 1)
};
pp.readToken_mult_modulo_exp = function(code) { // '%*'
var next = this.input.charCodeAt(this.pos + 1);
var size = 1;
var tokentype = code === 42 ? types$1.star : types$1.modulo;
// exponentiation operator ** and **= if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
++size;
tokentype = types$1.starstar;
next = this.input.charCodeAt(this.pos + 2);
}
pp.readToken_question = function() { // '?'
var ecmaVersion = this.options.ecmaVersion; if (ecmaVersion >= 11) {
var next = this.input.charCodeAt(this.pos + 1); if (next === 46) {
var next2 = this.input.charCodeAt(this.pos + 2); if (next2 < 48 || next2 > 57) { returnthis.finishOp(types$1.questionDot, 2) }
} if (next === 63) { if (ecmaVersion >= 12) {
var next2$1 = this.input.charCodeAt(this.pos + 2); if (next2$1 === 61) { returnthis.finishOp(types$1.assign, 3) }
} returnthis.finishOp(types$1.coalesce, 2)
}
} returnthis.finishOp(types$1.question, 1)
};
pp.readToken_numberSign = function() { // '#'
var ecmaVersion = this.options.ecmaVersion;
var code = 35; // '#' if (ecmaVersion >= 13) {
++this.pos;
code = this.fullCharCodeAtPos(); if (isIdentifierStart(code, true) || code === 92/* '\' */) { returnthis.finishToken(types$1.privateId, this.readWord1())
}
}
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};
pp.getTokenFromCode = function(code) { switch (code) { // The interpretation of a dot depends on whether it is followed // by a digit or another two dots. case46: // '.' returnthis.readToken_dot()
case48: // '0'
var next = this.input.charCodeAt(this.pos + 1); if (next === 120 || next === 88) { returnthis.readRadixNumber(16) } // '0x', '0X' - hex number if (this.options.ecmaVersion >= 6) { if (next === 111 || next === 79) { returnthis.readRadixNumber(8) } // '0o', '0O' - octal number if (next === 98 || next === 66) { returnthis.readRadixNumber(2) } // '0b', '0B' - binary number
}
// Anything else beginning with a digit is an integer, octal // number, or float. case49: case50: case51: case52: case53: case54: case55: case56: case57: // 1-9 returnthis.readNumber(false)
// Quotes produce strings. case34: case39: // '"', "'" returnthis.readString(code)
// Operators are parsed inline in tiny state machines. '=' (61) is // often referred to. `finishOp` simply skips the amount of // characters it is given as second argument, and returns a token // of the type given by its first argument. case47: // '/' returnthis.readToken_slash()
// Read an integer in the given radix. Return null if zero digits // were read, the integer value otherwise. When `len` is given, this // will return `null` unless the integer has exactly `len` digits.
pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) { // `len` is used for character escape sequences. In that case, disallow separators.
var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined;
// `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b) // and isn't fraction part nor exponent part. In that case, if the first digit // is zero then disallow separators.
var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;
var start = this.pos, total = 0, lastCode = 0; for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
var code = this.input.charCodeAt(this.pos), val = (void0);
if (allowSeparators && code === 95) { if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); } if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); } if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); }
lastCode = code; continue
}
if (code >= 97) { val = code - 97 + 10; } // a elseif (code >= 65) { val = code - 65 + 10; } // A elseif (code >= 48 && code <= 57) { val = code - 48; } // 0-9 else { val = Infinity; } if (val >= radix) { break }
lastCode = code;
total = total * radix + val;
}
if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); } if (this.pos === start || len != null && this.pos - start !== len) { return null }
return total
};
function stringToNumber(str, isLegacyOctalNumericLiteral) { if (isLegacyOctalNumericLiteral) { return parseInt(str, 8)
}
// `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value. return parseFloat(str.replace(/_/g, ""))
}
function stringToBigInt(str) { if (typeof BigInt !== "function") { return null
}
// `BigInt(value)` throws syntax error if the string contains numeric separators. return BigInt(str.replace(/_/g, ""))
}
pp.readRadixNumber = function(radix) {
var start = this.pos; this.pos += 2; // 0x
var val = this.readInt(radix); if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
val = stringToBigInt(this.input.slice(start, this.pos));
++this.pos;
} elseif (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } returnthis.finishToken(types$1.num, val)
};
// Read an integer, octal integer, or floating-point number.
pp.readNumber = function(startsWithDot) {
var start = this.pos; if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); }
var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; if (octal && this.strict) { this.raise(start, "Invalid number"); }
var next = this.input.charCodeAt(this.pos); if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
var val$1 = stringToBigInt(this.input.slice(start, this.pos));
++this.pos; if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } returnthis.finishToken(types$1.num, val$1)
} if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } if (next === 46 && !octal) { // '.'
++this.pos; this.readInt(10);
next = this.input.charCodeAt(this.pos);
} if ((next === 69 || next === 101) && !octal) { // 'eE'
next = this.input.charCodeAt(++this.pos); if (next === 43 || next === 45) { ++this.pos; } // '+-' if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
} if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
var val = stringToNumber(this.input.slice(start, this.pos), octal); returnthis.finishToken(types$1.num, val)
};
// Read a string value, interpreting backslash-escapes.
pp.readCodePoint = function() {
var ch = this.input.charCodeAt(this.pos), code;
if (ch === 123) { // '{' if (this.options.ecmaVersion < 6) { this.unexpected(); }
var codePos = ++this.pos;
code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
++this.pos; if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
} else {
code = this.readHexChar(4);
} return code
};
pp.readString = function(quote) {
var out = "", chunkStart = ++this.pos; for (;;) { if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
var ch = this.input.charCodeAt(this.pos); if (ch === quote) { break } if (ch === 92) { // '\'
out += this.input.slice(chunkStart, this.pos);
out += this.readEscapedChar(false);
chunkStart = this.pos;
} elseif (ch === 0x2028 || ch === 0x2029) { if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); }
++this.pos; if (this.options.locations) { this.curLine++; this.lineStart = this.pos;
}
} else { if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); }
++this.pos;
}
}
out += this.input.slice(chunkStart, this.pos++); returnthis.finishToken(types$1.string, out)
};
pp.readTmplToken = function() {
var out = "", chunkStart = this.pos; for (;;) { if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
var ch = this.input.charCodeAt(this.pos); if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) { if (ch === 36) { this.pos += 2; returnthis.finishToken(types$1.dollarBraceL)
} else {
++this.pos; returnthis.finishToken(types$1.backQuote)
}
}
out += this.input.slice(chunkStart, this.pos); returnthis.finishToken(types$1.template, out)
} if (ch === 92) { // '\'
out += this.input.slice(chunkStart, this.pos);
out += this.readEscapedChar(true);
chunkStart = this.pos;
} elseif (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.pos);
++this.pos; switch (ch) { case13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } case10:
out += "\n"; break default:
out += String.fromCharCode(ch); break
} if (this.options.locations) {
++this.curLine; this.lineStart = this.pos;
}
chunkStart = this.pos;
} else {
++this.pos;
}
}
};
// Reads a template token to search for the end, without validating any escape sequences
pp.readInvalidTemplateToken = function() { for (; this.pos < this.input.length; this.pos++) { switch (this.input[this.pos]) { case"\\":
++this.pos; break
case"$": if (this.input[this.pos + 1] !== "{") { break
}
// falls through case"`": returnthis.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos))
// no default
}
} this.raise(this.start, "Unterminated template");
};
this.invalidStringToken(
codePos, "Invalid escape sequence in template string"
);
} default: if (ch >= 48 && ch <= 55) {
var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
var octal = parseInt(octalStr, 8); if (octal > 255) {
octalStr = octalStr.slice(0, -1);
octal = parseInt(octalStr, 8);
} this.pos += octalStr.length - 1;
ch = this.input.charCodeAt(this.pos); if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { this.invalidStringToken( this.pos - 1 - octalStr.length,
inTemplate
? "Octal literal in template string"
: "Octal literal in strict mode"
);
} return String.fromCharCode(octal)
} if (isNewLine(ch)) { // Unicode new line characters after \ get removed from output in both // template literals and strings return""
} return String.fromCharCode(ch)
}
};
// Used to read character escape sequences ('\x', '\u', '\U').
pp.readHexChar = function(len) {
var codePos = this.pos;
var n = this.readInt(16, len); if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } return n
};
// Read an identifier, and return it as a string. Sets `this.containsEsc` // to whether the word contained a '\u' escape. // // Incrementally adds only escaped chars, adding other chunks as-is // as a micro-optimization.
pp.readWord1 = function() { this.containsEsc = false;
var word = "", first = true, chunkStart = this.pos;
var astral = this.options.ecmaVersion >= 6; while (this.pos < this.input.length) {
var ch = this.fullCharCodeAtPos(); if (isIdentifierChar(ch, astral)) { this.pos += ch <= 0xffff ? 1 : 2;
} elseif (ch === 92) { // "\" this.containsEsc = true;
word += this.input.slice(chunkStart, this.pos);
var escStart = this.pos; if (this.input.charCodeAt(++this.pos) !== 117) // "u"
{ this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
++this.pos;
var esc = this.readCodePoint(); if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
{ this.invalidStringToken(escStart, "Invalid Unicode escape"); }
word += codePointToString(esc);
chunkStart = this.pos;
} else { break
}
first = false;
} return word + this.input.slice(chunkStart, this.pos)
};
// Read an identifier or keyword token. Will check for reserved // words when necessary.
pp.readWord = function() {
var word = this.readWord1();
var type = types$1.name; if (this.keywords.test(word)) {
type = keywords[word];
} returnthis.finishToken(type, word)
};
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
// The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and // returns an abstract syntax tree as specified by [Mozilla parser // API][api]. // // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
function parse(input, options) { return Parser.parse(input, options)
}
// This function tries to parse a single expression at a given // offset in a string. Useful for parsing mixed-language formats // that embed JavaScript expressions.
function parseExpressionAt(input, pos, options) { return Parser.parseExpressionAt(input, pos, options)
}
// Acorn is organized as a tokenizer and a recursive-descent parser. // The `tokenizer` export provides an interface to the tokenizer.
function tokenizer(input, options) { return Parser.tokenizer(input, options)
}
var acorn = requireAcorn();
var sourceMap = requireSourceMap(); const NEWLINE_CODE = 10;
function prettyFast(input, options) { returnnew PrettyFast(options).getPrettifiedCodeAndSourceMap(input);
}
// If any of these tokens are seen before a "[" token, we know that "[" token // is the start of an array literal, rather than a property access. // // The only exception is "}", which would need to be disambiguated by // parsing. The majority of the time, an open bracket following a closing // curly is going to be an array literal, so we brush the complication under // the rug, and handle the ambiguity by always assuming that it will be an // array literal. const PRE_ARRAY_LITERAL_TOKENS = new Set([ "typeof", "void", "delete", "case", "do", "=", "in", "of", "...", "{", "*", "/", "%", "else", ";", "++", "--", "+", "-", "~", "!", ":", "?", ">>", ">>>", "<<", "||", "&&", "<", ">", "<=", ">=", "instanceof", "&", "^", "|", "==", "!=", "===", "!==", ",", "}",
]);
// If any of these tokens are seen before a "{" token, we know that "{" token // is the start of an object literal, rather than the start of a block. const PRE_OBJECT_LITERAL_TOKENS = new Set([ "typeof", "void", "delete", "=", "in", "of", "...", "*", "/", "%", "++", "--", "+", "-", "~", "!", ">>", ">>>", "<<", "<", ">", "<=", ">=", "instanceof", "&", "^", "|", "==", "!=", "===", "!==",
]);
class PrettyFast { /** *@param{Object}options:Providesconfigurabilityoftheprettyprinting. *@param{String}options.url:TheURLstringoftheuglyJScode. *@param{String}options.indent:Thestringtoindentcodeby. *@param{SourceMapGenerator}options.sourceMapGenerator:AnoptionalsourceMapGenerator *themappingswillbeaddedto. *@param{Boolean}options.prefixWithNewLine:Whentrue,theprettyprintedcodewillstart *withalinebreak *@param{Integer}options.originalStartLine:Thelinethepassedscriptstartsat(1-based). *Thisisusedforinlinescriptswhereweneedtoaccountforthelines *beforethescripttag *@param{Integer}options.originalStartColumn:Thecolumnthepassedscriptstartsat(1-based). *Thisisusedforinlinescriptswhereweneedtoaccountfortheposition *ofthescripttagwithintheline. *@param{Integer}options.generatedStartLine:Thelinewheretheprettyprintedscript *willstartat(1-based).ThisisusedforprettyprintingHTMLfile, *wherewemighthavehandlepreviousinlinescriptsthatimpactthe *positionofthisscript.
*/
constructor(options = {}) { // The level of indents deep we are. this.#indentLevel = 0; this.#indentChar = options.indent;
// We will handle mappings between ugly and pretty printed code in this SourceMapGenerator. this.#sourceMapGenerator =
options.sourceMapGenerator || new sourceMap.SourceMapGenerator({
file: options.url,
});
// Whether or not we added a newline on after we added the previous token.
#addedNewline = false; // Whether or not we added a space after we added the previous token.
#addedSpace = false;
#currentCode = "";
#currentLine = 1;
#currentColumn = 0; // The tokens parsed by acorn.
#tokenQueue; // The index of the current token in this.#tokenQueue.
#currentTokenIndex; // The previous token we added to the pretty printed code.
#previousToken; // Stack of token types/keywords that can affect whether we want to add a // newline or a space. We can make that decision based on what token type is // on the top of the stack. For example, a comma in a parameter list should // be followed by a space, while a comma in an object literal should be // followed by a newline. // // Strings that go on the stack: // // - "{" // - "{\n" // - "(" // - "(\n" // - "[" // - "[\n" // - "do" // - "?" // - "switch" // - "case" // - "default" // // The difference between "[" and "[\n" (as well as "{" and "{\n", and "(" and "(\n") // is that "\n" is used when we are treating (curly) brackets/parens as line delimiters // and should increment and decrement the indent level when we find them. // "[" can represent either a property access (e.g. `x["hi"]`), or an empty array literal // "{" only represents an empty object literals // "(" can represent lots of different things (wrapping expression, if/loop condition, function call, …)
#stack = [];
/** *@param{String}input:TheuglyJScodewewanttoprettyprint. *@returns{Object} *Anobjectwiththefollowingproperties: *-code:Theprettyprintedcodestring. *-map:ASourceMapGeneratorinstance.
*/
getPrettifiedCodeAndSourceMap(input) { // Add the initial new line if needed if (this.#prefixWithNewLine) { this.#write("\n");
}
// Pass through acorn's tokenizer and append tokens and comments into a // single queue to process. For example, the source file: // // foo // // a // // b // bar // // After this process, tokenQueue has the following token stream: // // [ foo, '// a', '// b', bar] this.#tokenQueue = this.#getTokens(input);
for (let i = 0, len = this.#tokenQueue.length; i < len; i++) { this.#currentTokenIndex = i; const token = this.#tokenQueue[i]; const nextToken = this.#tokenQueue[i + 1]; this.#handleToken(token, nextToken);
// Acorn's tokenizer re-uses tokens, so we have to copy the previous token on // every iteration. We follow acorn's lead here, and reuse the previousToken // object the same way that acorn reuses the token object. This allows us // to avoid allocations and minimize GC pauses. if (!this.#previousToken) { this.#previousToken = { loc: { start: {}, end: {} } };
} this.#previousToken.start = token.start; this.#previousToken.end = token.end; this.#previousToken.loc.start.line = token.loc.start.line; this.#previousToken.loc.start.column = token.loc.start.column; this.#previousToken.loc.end.line = token.loc.end.line; this.#previousToken.loc.end.column = token.loc.end.column; this.#previousToken.type = token.type; this.#previousToken.value = token.value;
}
/** *Writeaprettyprintedstringtotheprettifiedstringandfortokens,addtheir *mappingtotheSourceMapGenerator. * *@paramStringstr *Thestringtobeaddedtotheresult. *@paramNumberline *Thelinenumberthestringcamefromintheuglysource. *@paramNumbercolumn *Thecolumnnumberthestringcamefromintheuglysource. *@paramBooleanisToken *Settotruewhenwritingtokens,sowecandifferentiatethemfromthe *whitespaceweadd.
*/
#write(str, line, column, isToken) { this.#currentCode += str; if (isToken) { this.#sourceMapGenerator.addMapping({
source: this.#file, // We need to swap original and generated locations, as the prettified text should // be seen by the sourcemap service as the "original" one.
generated: { // originalStartLine is 1-based, and here we just want to offset by a number of // lines, so we need to decrement it
line: this.#hasOriginalStartLine
? line + (this.#originalStartLine - 1)
: line, // We only need to adjust the column number if we're looking at the first line, to // account for the html text before the opening <script> tag.
column:
line == 1 && this.#hasOriginalStartColumn
? column + this.#originalStartColumn
: column,
},
original: { // generatedStartLine is 1-based, and here we just want to offset by a number of // lines, so we need to decrement it.
line: this.#hasGeneratedStartLine
? this.#currentLine + (this.#generatedStartLine - 1)
: this.#currentLine,
column: this.#currentColumn,
},
name: null,
});
}
// If the next token is going to be a comment starting on the same line, // then no need to add a new line here if (
!nextToken ||
!nextToken.comment ||
token.loc.end.line != nextToken.loc.start.line
) { this.#maybeAppendNewline(token);
}
// Handle whitespace and newlines after "}" here instead of in // `isLineDelimiter` because it is only a line delimiter some of the // time. For example, we don't want to put "else if" on a new line after // the first if's block. if (this.#previousToken && ltt == "}") { if (
(ttk == "while" && this.#stack.at(-1) == "do") ||
needsSpaceBeforeClosingCurlyBracket(ttk)
) { this.#write(" ");
spaceAdded = true;
} elseif (needsLineBreakBeforeClosingCurlyBracket(ttl)) { this.#write("\n");
newlineAdded = true;
}
}
/** *Determinesifwethinkthatthegiventokenstartsanarrayliteral. * *@paramObjecttoken *Thetokenwewanttodetermineifitisanarrayliteral. *@paramObjectpreviousToken *Theprevioustokenweaddedtotheprettyprintedresults. * *@returnsBoolean *Trueifwebelieveitisanarrayliteral,falseotherwise.
*/
function isArrayLiteral(token, previousToken) { if (token.type.label != "[") { returnfalse;
} if (!previousToken) { returntrue;
} if (previousToken.type.isAssign) { returntrue;
}
return PRE_ARRAY_LITERAL_TOKENS.has(
previousToken.type.keyword || // Some tokens ('of', 'yield', …) have a `token.type.keyword` of 'name' and their // actual value in `token.value`
(previousToken.type.label == "name"
? previousToken.value
: previousToken.type.label)
);
}
/** *Determinesifwethinkthatthegiventokenstartsanobjectliteral. * *@paramObjecttoken *Thetokenwewanttodetermineifitisanobjectliteral. *@paramObjectpreviousToken *Theprevioustokenweaddedtotheprettyprintedresults. * *@returnsBoolean *Trueifwebelieveitisanobjectliteral,falseotherwise.
*/
function isObjectLiteral(token, previousToken) { if (token.type.label != "{") { returnfalse;
} if (!previousToken) { returnfalse;
} if (previousToken.type.isAssign) { returntrue;
} return PRE_OBJECT_LITERAL_TOKENS.has(
previousToken.type.keyword || previousToken.type.label
);
}
// If we're just wrapping an object, we'll have a new line right after if (tokenQueue[currentTokenIndex + 1].type.label == "{") { returnfalse;
}
// We're going to iterate through the following tokens until : // - we find the closing parent // - or we reached the maximum character we think should be in parenthesis const longParentContentLength = 60;
// Keep track of other parens so we know when we get the closing one for `token`
let parenCount = 0;
let parenContentLength = 0; for (let i = currentTokenIndex + 1, len = tokenQueue.length; i < len; i++) { const currToken = tokenQueue[i]; const ttl = currToken.type.label;
if (ttl == "(") {
parenCount++;
} elseif (ttl == ")") { if (parenCount == 0) { // Matching closing paren, if we got here, we didn't reach the length limit, // as we return when parenContentLength is greater than the limit. returnfalse;
}
parenCount--;
}
// Aside block comments, all tokens start and end location are on the same line, so // we can use `start` and `end` to deduce the token length. const tokenLength = currToken.comment
? currToken.text.length
: currToken.end - currToken.start;
parenContentLength += tokenLength;
// If we didn't find the matching closing paren yet and the characters from the // tokens we evaluated so far are longer than the limit, so consider the token // a long paren. if (parenContentLength > longParentContentLength) { returntrue;
}
}
// if we get to here, we didn't found a closing paren, which shouldn't happen // (scripts with syntax error are not displayed in the debugger), but just to // be safe, return false. returnfalse;
}
// If any of these tokens are followed by a token on a new line, we know that // ASI cannot happen. const PREVENT_ASI_AFTER_TOKENS = new Set([ // Binary operators "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", ">", "<=", ">=", "instanceof", "in", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", ",", ".", "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", // Unary operators "delete", "void", "typeof", "~", "!", "new", // Function calls and grouped expressions "(",
]);
// If any of these tokens are on a line after the token before it, we know // that ASI cannot happen. const PREVENT_ASI_BEFORE_TOKENS = new Set([ // Binary operators "*", "/", "%", "<<", ">>", ">>>", "<", ">", "<=", ">=", "instanceof", "in", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", ",", ".", "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", // Function calls "(",
]);
const stringEscapeCharactersRegExp = new RegExp(stringRegExpString, "g"); const templateEscapeCharactersRegExp = new RegExp(templateRegExpString, "g");
function stringSanitizerReplaceFunc(_, c) { return stringEscapeCharacters[c];
}
function templateSanitizerReplaceFunc(_, c) { return templateEscapeCharacters[c];
}
/** *Makesurethatweoutputtheescapedcharactercombinationinsidestring *literalsinsteadofvariousproblematiccharacters.
*/
function stringSanitize(str) { return str.replace(stringEscapeCharactersRegExp, stringSanitizerReplaceFunc);
}
function templateSanitize(str) { return str.replace(
templateEscapeCharactersRegExp,
templateSanitizerReplaceFunc
);
}
// When a taskId was passed, we only return the pretty printed text.
// The source map should be retrieved with getSourceMapForTask.
return code;
}
/**
* Get the source map for a pretty-print task
*
* @param {Integer} taskId: The taskId that was used to call prettyPrint
* @returns {Object} A source map object
*/
function getSourceMapForTask(taskId) {
if (!sourceMapGeneratorByTaskId.has(taskId)) {
return null;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.2.47Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.