diff --git a/lib/source-map-consumer.js b/lib/source-map-consumer.js index 9b68e393..cfcbd09f 100644 --- a/lib/source-map-consumer.js +++ b/lib/source-map-consumer.js @@ -203,9 +203,11 @@ class BasicSourceMapConsumer extends SourceMapConsumer { that._names = ArraySet.fromArray(names.map(String), true); that._sources = ArraySet.fromArray(sources, true); + util.createUrlParser(); that._absoluteSources = ArraySet.fromArray(that._sources.toArray().map(function(s) { return util.computeSourceURL(sourceRoot, s, aSourceMapURL); }), true); + util.clearURLParser(); that.sourceRoot = sourceRoot; that.sourcesContent = sourcesContent; diff --git a/lib/util.js b/lib/util.js index 430ec4de..f6cee376 100644 --- a/lib/util.js +++ b/lib/util.js @@ -7,6 +7,44 @@ const URL = require("./url"); +function createUrlParser(url, base) { + const urlMap = new Map(); + parser = function(url, base) { + + let baseMap = urlMap.get(url); + + if (!baseMap) { + baseMap = new Map(); + urlMap.set(url, baseMap); + } + + if (!baseMap.has(base)) { + const parsedUrl = new URL(url, base); + baseMap.set(base, parsedUrl); + return parsedUrl; + } + + return baseMap.get(base); + } +} + +function clearURLParser() { + parser = undefined; +} + +let parser; + +function parseURL(url, base) { + if (parser) { + return parser(url, base) + } + + return new URL(url, base); +} + +exports.createUrlParser = createUrlParser +exports.clearURLParser = createUrlParser + /** * This is a helper function for getting values from parameter/options * objects. @@ -176,7 +214,7 @@ function createSafeHandler(cb) { return input => { const type = getURLType(input); const base = buildSafeBase(input); - const url = new URL(input, base); + const url = parseURL(input, base); cb(url); @@ -197,7 +235,7 @@ function createSafeHandler(cb) { } function withBase(url, base) { - return new URL(url, base).toString(); + return parseURL(url, base).toString(); } function buildUniqueSegment(prefix, str) { @@ -251,8 +289,8 @@ function getURLType(url) { * @return A rootURL-relative, normalized URL value. */ function computeRelativeURL(rootURL, targetURL) { - if (typeof rootURL === "string") rootURL = new URL(rootURL); - if (typeof targetURL === "string") targetURL = new URL(targetURL); + if (typeof rootURL === "string") rootURL = parseURL(rootURL); + if (typeof targetURL === "string") targetURL = parseURL(targetURL); const targetParts = targetURL.pathname.split("/"); const rootParts = rootURL.pathname.split("/"); @@ -297,7 +335,7 @@ const ensureDirectory = createSafeHandler(url => { * @return A normalized URL value. */ const trimFilename = createSafeHandler(url => { - url.href = new URL(".", url.toString()).toString(); + url.href = parseURL(".", url.toString()).toString(); }); /** @@ -376,11 +414,11 @@ function relativeIfPossible(rootURL, targetURL) { } const base = buildSafeBase(rootURL + targetURL); - const root = new URL(rootURL, base); - const target = new URL(targetURL, base); + const root = parseURL(rootURL, base); + const target = parseURL(targetURL, base); try { - new URL("", target.toString()); + parseURL("", target.toString()); } catch (err) { // Bail if the URL doesn't support things being relative to it, // For example, data: and blob: URLs.