(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@jridgewell/resolve-uri'), require('sourcemap-codec')) :
    typeof define === 'function' && define.amd ? define(['exports', '@jridgewell/resolve-uri', 'sourcemap-codec'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.traceMapping = {}, global.resolveURI, global.sourcemapCodec));
})(this, (function (exports, resolveUri, sourcemapCodec) { 'use strict';

    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

    var resolveUri__default = /*#__PURE__*/_interopDefaultLegacy(resolveUri);

    function resolve(input, base) {
        // The base is always treated as a directory, if it's not empty.
        // https://github.com/mozilla/source-map/blob/8cb3ee57/lib/util.js#L327
        // https://github.com/chromium/chromium/blob/da4adbb3/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js#L400-L401
        if (base && !base.endsWith('/'))
            base += '/';
        return resolveUri__default["default"](input, base);
    }

    /**
     * Removes everything after the last "/", but leaves the slash.
     */
    function stripFilename(path) {
        if (!path)
            return '';
        const index = path.lastIndexOf('/');
        return path.slice(0, index + 1);
    }

    /**
     * A binary search implementation that returns the index if a match is found,
     * or the negated index of where the `needle` should be inserted.
     *
     * The `comparator` callback receives both the `item` under comparison and the
     * needle we are searching for. It must return `0` if the `item` is a match,
     * any negative number if `item` is too small (and we must search after it), or
     * any positive number if the `item` is too large (and we must search before
     * it).
     *
     * The `len` param allows you to treat contiguous blocks of memory as a single item. Eg, a 5-length
     * tuple (with values at indices 0-4) would only test index 0.
     *
     * If no match is found, then the left-index (the index associated with the item that comes just
     * before the desired index) is returned. To maintain proper sort order, a splice would happen at
     * the next index:
     *
     * ```js
     * const array = [1, 3];
     * const needle = 2;
     * const index = binarySearch(array, needle, (item, needle) => item - needle);
     *
     * assert.equal(index, 0);
     * array.splice(index + 1, 0, needle);
     * assert.deepEqual(array, [1, 2, 3]);
     * ```
     */
    function binarySearch(haystack, needle, comparator, low, high, len) {
        low /= len;
        high /= len;
        while (low <= high) {
            const mid = low + ((high - low) >> 1);
            const index = mid * len;
            const cmp = comparator(haystack[index], needle);
            if (cmp === 0) {
                return index;
            }
            if (cmp < 0) {
                low = mid + 1;
            }
            else {
                high = mid - 1;
            }
        }
        return (low - 1) * len;
    }
    /**
     * This overly complicated beast is just to record the last tested line/column and the resulting
     * index, allowing us to skip a few tests if mappings are monotonically increasing.
     */
    function memoizedBinarySearch(haystack, needle, comparator, low, high, len, state, line, column) {
        const { _lastLine: lastLine, _lastColumn: lastColumn, _lastIndex: lastIndex } = state;
        if (line === lastLine) {
            if (column === lastColumn) {
                return lastIndex;
            }
            if (column >= lastColumn) {
                low = Math.max(lastIndex, 0);
            }
            else {
                high = lastIndex;
            }
        }
        state._lastLine = line;
        state._lastColumn = column;
        return (state._lastIndex = binarySearch(haystack, needle, comparator, low, high, len));
    }

    const ITEM_LENGTH$1 = 1;
    class DecodedSourceMapImpl {
        constructor(map, owned) {
            this._lastIndex = -ITEM_LENGTH$1;
            this._lastLine = -1;
            this._lastColumn = -1;
            this._mappings = maybeSort(map.mappings, owned);
        }
        encodedMappings() {
            return sourcemapCodec.encode(this._mappings);
        }
        decodedMappings() {
            return this._mappings;
        }
        map(fn) {
            const mapOut = [];
            const mappings = this._mappings;
            for (let i = 0; i < mappings.length; i++) {
                const line = mappings[i];
                const lineOut = [];
                mapOut.push(lineOut);
                for (let j = 0; j < line.length; j++) {
                    const seg = line[j];
                    const { length } = seg;
                    let segOut;
                    if (length === 4)
                        segOut = fn(i, seg[0], seg[1], seg[2], seg[3], -1);
                    else if (length === 5)
                        segOut = fn(i, seg[0], seg[1], seg[2], seg[3], seg[4]);
                    else
                        segOut = fn(i, seg[0], -1, -1, -1, -1);
                    if (segOut != null)
                        lineOut.push(segOut);
                }
            }
            return mapOut;
        }
        traceSegment(line, column) {
            const mappings = this._mappings;
            // It's common for parent source maps to have pointers to lines that have no
            // mapping (like a "//# sourceMappingURL=") at the end of the child file.
            if (line >= mappings.length)
                return null;
            const segments = mappings[line];
            const index = memoizedBinarySearch(segments, column, searchComparator$1, 0, segments.length - ITEM_LENGTH$1, ITEM_LENGTH$1, this, line, column);
            // we come before any mapped segment
            if (index < 0)
                return null;
            return segments[index];
        }
    }
    function maybeSort(mappings, owned) {
        const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
        if (unsortedIndex === mappings.length)
            return mappings;
        // If we own the array (meaning we parsed it from JSON), then we're free to directly mutate it. If
        // not, we do not want to modify the consumer's input array.
        if (!owned)
            mappings = mappings.slice();
        for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) {
            mappings[i] = sortSegments(mappings[i], owned);
        }
        return mappings;
    }
    function nextUnsortedSegmentLine(mappings, start) {
        for (let i = start; i < mappings.length; i++) {
            if (!isSorted(mappings[i]))
                return i;
        }
        return mappings.length;
    }
    function isSorted(line) {
        for (let j = 1; j < line.length; j++) {
            if (line[j][0] < line[j - 1][0]) {
                return false;
            }
        }
        return true;
    }
    function sortSegments(line, owned) {
        if (!owned)
            line = line.slice();
        return line.sort(sortComparator$1);
    }
    function sortComparator$1(a, b) {
        return a[0] - b[0];
    }
    function searchComparator$1(segment, needle) {
        return segment[0] - needle;
    }

    const base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    const base64Index = new Uint8Array(128);
    for (let i = 0; i < base64.length; i++) {
        base64Index[base64.charCodeAt(i)] = i;
    }
    const ITEM_LENGTH = 5;
    function decode(encoded, lines) {
        let generatedColumn = 0;
        // 0 is used as a "not found" marker (because TypedArrays are 0 by default, so we don't need to
        // manually set any missing VLQ numbers), so these start at 1. Public APIs will decrement the
        // values so they are correct before returning to consumers.
        let sourcesIndex = 1;
        let sourceLine = 1;
        let sourceColumn = 1;
        let namesIndex = 1;
        let lastGenColumn = 0;
        let lineSorted = true;
        let index = 0;
        // lastLineStart tracks the index of the segment that started the current line, so that we may
        // sort the line after it's complete.
        let lastLineStart = 0;
        let decoded = new Uint32Array(1000);
        // The first line starts with segment 0. If there are no mappings on this line, then the next
        // line will also start with segment 0 (meaning the first line ends with segment 0).
        lines.push(0);
        for (let pos = 0; pos < encoded.length;) {
            switch (encoded.charCodeAt(pos)) {
                // Commas separate segements on a line.
                case 44: // ','
                    pos++;
                    continue;
                // Semicolons separates lines.
                case 59: // ';'
                    lines.push(index);
                    if (!lineSorted)
                        easySort(decoded, lastLineStart, index);
                    lineSorted = true;
                    lastLineStart = index;
                    // generatedColumn is reset when the next line starts, per the spec.
                    generatedColumn = 0;
                    pos++;
                    continue;
                default:
                    // Ensure that we have at least 5 items left in the decoded buffer, so we can push this
                    // segment on.
                    decoded = reserve(decoded, index, ITEM_LENGTH);
                    // Segments are guaranteed to have at least the generatedColumn VLQ.
                    lastGenColumn = generatedColumn;
                    pos = decodeInteger(encoded, pos, decoded, index, generatedColumn);
                    generatedColumn = decoded[index];
                    lineSorted && (lineSorted = generatedColumn >= lastGenColumn);
                    index++;
                    if (!hasMoreMappings(encoded, pos)) {
                        index += 4;
                        continue;
                    }
                    // If there are more VLQ, then we're guaranteed to have sourcesIndex, sourceLine, and
                    // sourceColumn.
                    pos = decodeInteger(encoded, pos, decoded, index, sourcesIndex);
                    sourcesIndex = decoded[index];
                    index++;
                    pos = decodeInteger(encoded, pos, decoded, index, sourceLine);
                    sourceLine = decoded[index];
                    index++;
                    pos = decodeInteger(encoded, pos, decoded, index, sourceColumn);
                    sourceColumn = decoded[index];
                    index++;
                    if (!hasMoreMappings(encoded, pos)) {
                        index += 1;
                        continue;
                    }
                    // Finally, namesIndex.
                    pos = decodeInteger(encoded, pos, decoded, index, namesIndex);
                    namesIndex = decoded[index];
                    index++;
            }
        }
        // Cap the lines, so that we can always look at index and index+1 for the start and end indices.
        lines.push(index);
        if (!lineSorted)
            easySort(decoded, lastLineStart, index);
        return decoded.subarray(0, index);
    }
    function reserve(buf, pos, count) {
        if (buf.length > pos + count)
            return buf;
        const swap = new Uint32Array(buf.length * 2);
        swap.set(buf);
        return swap;
    }
    function hasMoreMappings(encoded, pos) {
        if (pos === encoded.length)
            return false;
        const c = encoded.charCodeAt(pos);
        return c !== 44 /* ',' */ && c !== 59 /* ';' */;
    }
    function decodeInteger(encoded, pos, state, index, relative) {
        let value = 0;
        let shift = 0;
        let integer = 0;
        // VLQ is a variable-length quantity (duh). The low 5 bits encode are integer data, with the 6th
        // bit being the "continue" bit signaling more data in the VLQ.
        do {
            const c = encoded.charCodeAt(pos++);
            integer = base64Index[c];
            value |= (integer & 0b011111) << shift;
            shift += 5;
        } while (integer & 0b100000);
        // The lowest bit encodes whether the VLQ was originally negative.
        const shouldNegate = value & 1;
        value >>>= 1;
        // Nomally, -x produces a negative value like you would expect. But what does `-0` represent? In
        // VLQ, it should represent -2,147,483,648 (the smallest 32bit signed int). But -0 is just 0 in
        // JS, so we have to bitwise-OR with -0x80000000. This won't affect any other value, eg
        // `-1 | -0x80000000` is still `-1`.
        if (shouldNegate)
            value = -0x80000000 | -value;
        state[index] = relative + value;
        return pos;
    }
    function easySort(state, start, end) {
        // This isn't a fast algorithm, but I believe it's exceedingly rare for a mapping to be unsorted.
        const segments = [];
        for (let i = start; i < end; i += ITEM_LENGTH) {
            segments.push(state.slice(i, i + ITEM_LENGTH));
        }
        segments.sort(sortComparator);
        for (let i = start, j = 0; i < end; i += ITEM_LENGTH, j++) {
            state.set(segments[j], i);
        }
    }
    function sortComparator(a, b) {
        return a[0] - b[0];
    }

    class EncodedSourceMapImpl {
        constructor(map) {
            this._lastIndex = -ITEM_LENGTH;
            this._lastLine = -1;
            this._lastColumn = -1;
            this._lineIndices = [];
            this._encoded = map.mappings;
            this._mappings = decode(this._encoded, this._lineIndices);
        }
        encodedMappings() {
            return this._encoded;
        }
        decodedMappings() {
            return this.map(segmentify);
        }
        map(fn) {
            const { _mappings: mappings, _lineIndices: lineIndices } = this;
            const mapOut = [];
            let lineOut = [];
            let generatedLine = 0;
            let lineIndex = lineIndices[generatedLine + 1];
            for (let i = 0; i < mappings.length;) {
                while (i < lineIndex) {
                    const segOut = fn(generatedLine, mappings[i + 0], mappings[i + 1] - 1, mappings[i + 2] - 1, mappings[i + 3] - 1, mappings[i + 4] - 1);
                    if (segOut != null)
                        lineOut.push(segOut);
                    i += ITEM_LENGTH;
                }
                do {
                    mapOut.push(lineOut);
                    lineOut = [];
                    generatedLine++;
                    lineIndex = lineIndices[generatedLine + 1];
                } while (i === lineIndex);
            }
            return mapOut;
        }
        traceSegment(line, column) {
            const { _mappings: mappings, _lineIndices: lineIndices } = this;
            // It's common for parent source maps to have pointers to lines that have no
            // mapping (like a "//# sourceMappingURL=") at the end of the child file.
            if (line >= lineIndices.length - 1)
                return null;
            const low = lineIndices[line];
            const high = lineIndices[line + 1] - 1;
            const index = memoizedBinarySearch(mappings, column, searchComparator, low, high, ITEM_LENGTH, this, line, column);
            // we come before any mapped segment
            if (index < low)
                return null;
            return segmentify(line, mappings[index + 0], mappings[index + 1] - 1, mappings[index + 2] - 1, mappings[index + 3] - 1, mappings[index + 4] - 1);
        }
    }
    function segmentify(_genLine, genCol, source, line, col, name) {
        // If the sourcesIndex is -1, then the VLQ segment didn't specify 2-5 values.
        if (source === -1)
            return [genCol];
        // If the namesIndex is -1, then the VLQ segment didn't specify 5th value.
        if (name === -1)
            return [genCol, source, line, col];
        return [genCol, source, line, col, name];
    }
    function searchComparator(column, needle) {
        return column - needle;
    }

    const INVALID_MAPPING = Object.freeze({
        source: null,
        line: null,
        column: null,
        name: null,
    });
    class TraceMap {
        constructor(map, mapUrl) {
            const isString = typeof map === 'string';
            const parsed = isString ? JSON.parse(map) : map;
            const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
            this.version = version;
            this.file = file;
            this.names = names;
            this.sourceRoot = sourceRoot;
            this.sources = sources;
            this.sourcesContent = sourcesContent;
            const from = resolve(sourceRoot || '', stripFilename(mapUrl));
            this.resolvedSources = sources.map((s) => resolve(s || '', from));
            if (typeof parsed.mappings === 'string') {
                this._impl = new EncodedSourceMapImpl(parsed);
            }
            else {
                this._impl = new DecodedSourceMapImpl(parsed, isString);
            }
        }
        /**
         * Returns the encoded (VLQ string) form of the SourceMap's mappings field.
         */
        encodedMappings() {
            return this._impl.encodedMappings();
        }
        /**
         * Returns the decoded (array of lines of segments) form of the SourceMap's mappings field.
         */
        decodedMappings() {
            return this._impl.decodedMappings();
        }
        /**
         * Similar to Array.p.map, maps each segment into a new  segment. Passes -1 for any values that do
         * not exist in the SourceMapSegment. Both generatedLine and generatedColumn are 0-based.
         */
        map(fn) {
            return this._impl.map(fn);
        }
        /**
         * A low-level API to find the segment associated with a generated line/column (think, from a
         * stack trace). Line and column here are 0-based, unlike `originalPositionFor`.
         */
        traceSegment(line, column) {
            return this._impl.traceSegment(line, column);
        }
        /**
         * A higher-level API to find the source/line/column associated with a generated line/column
         * (think, from a stack trace). Line is 1-based, but column is 0-based, due to legacy behavior in
         * `source-map` library.
         */
        originalPositionFor({ line, column }) {
            if (line < 1)
                throw new Error('`line` must be greater than 0 (lines start at line 1)');
            if (column < 0) {
                throw new Error('`column` must be greater than or equal to 0 (columns start at column 0)');
            }
            const segment = this.traceSegment(line - 1, column);
            if (segment == null)
                return INVALID_MAPPING;
            if (segment.length == 1)
                return INVALID_MAPPING;
            const { names, resolvedSources } = this;
            return {
                source: resolvedSources[segment[1]],
                line: segment[2] + 1,
                column: segment[3],
                name: segment.length === 5 ? names[segment[4]] : null,
            };
        }
    }

    exports.TraceMap = TraceMap;
    exports["default"] = TraceMap;

    Object.defineProperty(exports, '__esModule', { value: true });

}));
//# sourceMappingURL=trace-mapping.umd.js.map
