Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/shapecraft. flo-bit.dev/shapecraft
Something went wrong. Try again.
15 kB · 594 lines
JavaScript
at commit da69385e
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595/* -*- Mode: js; js-indent-level: 2; -*- *//* * Copyright 2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */
/** * This is a helper function for getting values from parameter/options * objects. * * @param args The object we are extracting values from * @param name The name of the property we are getting. * @param defaultValue An optional value to return if the property is missing * from the object. If this is not specified and the property is missing, an * error will be thrown. */function getArg(aArgs, aName, aDefaultValue) { if (aName in aArgs) { return aArgs[aName]; } else if (arguments.length === 3) { return aDefaultValue; } else { throw new Error('"' + aName + '" is a required argument.'); }}exports.getArg = getArg;
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var dataUrlRegexp = /^data:.+\,.+$/;
function urlParse(aUrl) { var match = aUrl.match(urlRegexp); if (!match) { return null; } return { scheme: match[1], auth: match[2], host: match[3], port: match[4], path: match[5] };}exports.urlParse = urlParse;
function urlGenerate(aParsedUrl) { var url = ''; if (aParsedUrl.scheme) { url += aParsedUrl.scheme + ':'; } url += '//'; if (aParsedUrl.auth) { url += aParsedUrl.auth + '@'; } if (aParsedUrl.host) { url += aParsedUrl.host; } if (aParsedUrl.port) { url += ":" + aParsedUrl.port } if (aParsedUrl.path) { url += aParsedUrl.path; } return url;}exports.urlGenerate = urlGenerate;
var MAX_CACHED_INPUTS = 32;
/** * Takes some function `f(input) -> result` and returns a memoized version of * `f`. * * We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The * memoization is a dumb-simple, linear least-recently-used cache. */function lruMemoize(f) { var cache = [];
return function(input) { for (var i = 0; i < cache.length; i++) { if (cache[i].input === input) { var temp = cache[0]; cache[0] = cache[i]; cache[i] = temp; return cache[0].result; } }
var result = f(input);
cache.unshift({ input, result, });
if (cache.length > MAX_CACHED_INPUTS) { cache.pop(); }
return result; };}
/** * Normalizes a path, or the path portion of a URL: * * - Replaces consecutive slashes with one slash. * - Removes unnecessary '.' parts. * - Removes unnecessary '<dir>/..' parts. * * Based on code in the Node.js 'path' core module. * * @param aPath The path or url to normalize. */var normalize = lruMemoize(function normalize(aPath) { var path = aPath; var url = urlParse(aPath); if (url) { if (!url.path) { return aPath; } path = url.path; } var isAbsolute = exports.isAbsolute(path); // Split the path into parts between `/` characters. This is much faster than // using `.split(/\/+/g)`. var parts = []; var start = 0; var 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++; } } }
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { part = parts[i]; if (part === '.') { parts.splice(i, 1); } else if (part === '..') { up++; } else if (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('/');
if (path === '') { path = isAbsolute ? '/' : '.'; }
if (url) { url.path = path; return urlGenerate(url); } return path;});exports.normalize = normalize;
/** * Joins two paths/URLs. * * @param aRoot The root path or URL. * @param aPath The path or URL to be joined with the root. * * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a * scheme-relative URL: Then the scheme of aRoot, if any, is prepended * first. * - Otherwise aPath is a path. If aRoot is a URL, then its path portion * is updated with the result and aRoot is returned. Otherwise the result * is returned. * - If aPath is absolute, the result is aPath. * - Otherwise the two paths are joined with a slash. * - Joining for example 'http://' and 'www.example.com' is also supported. */function join(aRoot, aPath) { if (aRoot === "") { aRoot = "."; } if (aPath === "") { aPath = "."; } var aPathUrl = urlParse(aPath); var aRootUrl = urlParse(aRoot); if (aRootUrl) { aRoot = aRootUrl.path || '/'; }
// `join(foo, '//www.example.org')` if (aPathUrl && !aPathUrl.scheme) { if (aRootUrl) { aPathUrl.scheme = aRootUrl.scheme; } return urlGenerate(aPathUrl); }
if (aPathUrl || aPath.match(dataUrlRegexp)) { return aPath; }
// `join('http://', 'www.example.com')` if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { aRootUrl.host = aPath; return urlGenerate(aRootUrl); }
var joined = aPath.charAt(0) === '/' ? aPath : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
if (aRootUrl) { aRootUrl.path = joined; return urlGenerate(aRootUrl); } return joined;}exports.join = join;
exports.isAbsolute = function (aPath) { return aPath.charAt(0) === '/' || urlRegexp.test(aPath);};
/** * Make a path relative to a URL or another path. * * @param aRoot The root path or URL. * @param aPath The path or URL to be made relative to aRoot. */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. var level = 0; while (aPath.indexOf(aRoot + '/') !== 0) { var 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(/^([^\/]+:\/)?\/*$/)) { return aPath; }
++level; }
// Make sure we add a "../" for each component we removed from the root. return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);}exports.relative = relative;
var supportsNullProto = (function () { var obj = Object.create(null); return !('__proto__' in obj);}());
function identity (s) { return s;}
/** * Because behavior goes wacky when you set `__proto__` on objects, we * have to prefix all the strings in our set with an arbitrary character. * * See https://github.com/mozilla/source-map/pull/31 and * https://github.com/mozilla/source-map/issues/30 * * @param String aStr */function toSetString(aStr) { if (isProtoString(aStr)) { return '$' + aStr; }
return aStr;}exports.toSetString = supportsNullProto ? identity : toSetString;
function fromSetString(aStr) { if (isProtoString(aStr)) { return aStr.slice(1); }
return aStr;}exports.fromSetString = supportsNullProto ? identity : fromSetString;
function isProtoString(s) { if (!s) { return false; }
var length = s.length;
if (length < 9 /* "__proto__".length */) { return false; }
if (s.charCodeAt(length - 1) !== 95 /* '_' */ || s.charCodeAt(length - 2) !== 95 /* '_' */ || s.charCodeAt(length - 3) !== 111 /* 'o' */ || s.charCodeAt(length - 4) !== 116 /* 't' */ || s.charCodeAt(length - 5) !== 111 /* 'o' */ || s.charCodeAt(length - 6) !== 114 /* 'r' */ || s.charCodeAt(length - 7) !== 112 /* 'p' */ || s.charCodeAt(length - 8) !== 95 /* '_' */ || s.charCodeAt(length - 9) !== 95 /* '_' */) { return false; }
for (var i = length - 10; i >= 0; i--) { if (s.charCodeAt(i) !== 36 /* '$' */) { return false; } }
return true;}
/** * Comparator between two mappings where the original positions are compared. * * Optionally pass in `true` as `onlyCompareGenerated` to consider two * mappings with the same original source/line/column, but different generated * line and column the same. Useful when searching for a mapping with a * stubbed out mapping. */function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { var cmp = strcmp(mappingA.source, mappingB.source); if (cmp !== 0) { return cmp; }
cmp = mappingA.originalLine - mappingB.originalLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.originalColumn - mappingB.originalColumn; if (cmp !== 0 || onlyCompareOriginal) { return cmp; }
cmp = mappingA.generatedColumn - mappingB.generatedColumn; if (cmp !== 0) { return cmp; }
cmp = mappingA.generatedLine - mappingB.generatedLine; if (cmp !== 0) { return cmp; }
return strcmp(mappingA.name, mappingB.name);}exports.compareByOriginalPositions = compareByOriginalPositions;
function compareByOriginalPositionsNoSource(mappingA, mappingB, onlyCompareOriginal) { var cmp
cmp = mappingA.originalLine - mappingB.originalLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.originalColumn - mappingB.originalColumn; if (cmp !== 0 || onlyCompareOriginal) { return cmp; }
cmp = mappingA.generatedColumn - mappingB.generatedColumn; if (cmp !== 0) { return cmp; }
cmp = mappingA.generatedLine - mappingB.generatedLine; if (cmp !== 0) { return cmp; }
return strcmp(mappingA.name, mappingB.name);}exports.compareByOriginalPositionsNoSource = compareByOriginalPositionsNoSource;
/** * Comparator between two mappings with deflated source and name indices where * the generated positions are compared. * * Optionally pass in `true` as `onlyCompareGenerated` to consider two * mappings with the same generated line and column, but different * source/name/original line and column the same. Useful when searching for a * mapping with a stubbed out mapping. */function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { var cmp = mappingA.generatedLine - mappingB.generatedLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.generatedColumn - mappingB.generatedColumn; if (cmp !== 0 || onlyCompareGenerated) { return cmp; }
cmp = strcmp(mappingA.source, mappingB.source); if (cmp !== 0) { return cmp; }
cmp = mappingA.originalLine - mappingB.originalLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.originalColumn - mappingB.originalColumn; if (cmp !== 0) { return cmp; }
return strcmp(mappingA.name, mappingB.name);}exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
function compareByGeneratedPositionsDeflatedNoLine(mappingA, mappingB, onlyCompareGenerated) { var cmp = mappingA.generatedColumn - mappingB.generatedColumn; if (cmp !== 0 || onlyCompareGenerated) { return cmp; }
cmp = strcmp(mappingA.source, mappingB.source); if (cmp !== 0) { return cmp; }
cmp = mappingA.originalLine - mappingB.originalLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.originalColumn - mappingB.originalColumn; if (cmp !== 0) { return cmp; }
return strcmp(mappingA.name, mappingB.name);}exports.compareByGeneratedPositionsDeflatedNoLine = compareByGeneratedPositionsDeflatedNoLine;
function strcmp(aStr1, aStr2) { if (aStr1 === aStr2) { return 0; }
if (aStr1 === null) { return 1; // aStr2 !== null }
if (aStr2 === null) { return -1; // aStr1 !== null }
if (aStr1 > aStr2) { return 1; }
return -1;}
/** * Comparator between two mappings with inflated source and name strings where * the generated positions are compared. */function compareByGeneratedPositionsInflated(mappingA, mappingB) { var cmp = mappingA.generatedLine - mappingB.generatedLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.generatedColumn - mappingB.generatedColumn; if (cmp !== 0) { return cmp; }
cmp = strcmp(mappingA.source, mappingB.source); if (cmp !== 0) { return cmp; }
cmp = mappingA.originalLine - mappingB.originalLine; if (cmp !== 0) { return cmp; }
cmp = mappingA.originalColumn - mappingB.originalColumn; if (cmp !== 0) { return cmp; }
return strcmp(mappingA.name, mappingB.name);}exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
/** * Strip any JSON XSSI avoidance prefix from the string (as documented * in the source maps specification), and then parse the string as * JSON. */function parseSourceMapInput(str) { return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));}exports.parseSourceMapInput = parseSourceMapInput;
/** * Compute the URL of a source given the the source root, the source's * URL, and the source map's URL. */function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) { sourceURL = sourceURL || '';
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) { var parsed = urlParse(sourceMapURL); if (!parsed) { throw new Error("sourceMapURL could not be parsed"); } if (parsed.path) { // Strip the last path component, but keep the "/". var index = parsed.path.lastIndexOf('/'); if (index >= 0) { parsed.path = parsed.path.substring(0, index + 1); } } sourceURL = join(urlGenerate(parsed), sourceURL); }
return normalize(sourceURL);}exports.computeSourceURL = computeSourceURL;