From c3e3ef219918c25d208e1ade95f45b7fa9856a82 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Mon, 11 May 2026 03:47:27 +0400 Subject: [PATCH] perf: inline base64VLQ.decode slow path in _parseMappings --- lib/source-map-consumer.js | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/source-map-consumer.js b/lib/source-map-consumer.js index f56ffcdb..d25b4944 100644 --- a/lib/source-map-consumer.js +++ b/lib/source-map-consumer.js @@ -8,7 +8,12 @@ var util = require('./util'); var binarySearch = require('./binary-search'); var ArraySet = require('./array-set').ArraySet; -var base64VLQ = require('./base64-vlq'); +// `base64DecodeTable` maps a base64 character code → its 6-bit decoded value, +// with `255` as the invalid-char sentinel. Imported directly so the inlined +// multi-byte VLQ slow path in `_parseMappings` can index it without going +// through a wrapper function — same direct-table pattern PR #67 applied to +// `_names._array`. +var base64DecodeTable = require('./base64').charToIntMap; function SourceMapConsumer(aSourceMap, aSourceMapURL) { var sourceMap = aSourceMap; @@ -697,7 +702,6 @@ BasicSourceMapConsumer.prototype._parseMappings = var previousName = 0; var length = aStr.length; var index = 0; - var temp = {}; var value, charCode; // Reuse segment array to avoid allocations per mapping var segment = [0, 0, 0, 0, 0]; @@ -738,10 +742,31 @@ BasicSourceMapConsumer.prototype._parseMappings = index++; segment[segmentLength++] = value; } else { - base64VLQ.decode(aStr, index, temp); - value = temp.value; - index = temp.rest; - segment[segmentLength++] = value; + // Multi-byte VLQ decode — inlined. Indirect-dispatched + // base64VLQ.decode + the temp output object's `.value`/`.rest` + // round trip is more cost than the body itself for typical + // small deltas. Bit layout: bit 0 = sign, bits 1-4 = value + // (chunked 5-bit groups across continuation digits), bit 5 = + // continuation. `base64DecodeTable[c] === 255` marks an + // invalid base64 char. + var vlqResult = 0; + var vlqShift = 0; + var vlqDigit; + do { + if (index >= length) { + throw new Error('Expected more digits in base 64 VLQ value.'); + } + var vlqC = aStr.charCodeAt(index++); + vlqDigit = vlqC < 128 ? base64DecodeTable[vlqC] : 255; + if (vlqDigit === 255) { + throw new Error('Invalid base64 digit: ' + aStr.charAt(index - 1)); + } + vlqResult = vlqResult + ((vlqDigit & 31) << vlqShift); + vlqShift += 5; + } while ((vlqDigit & 32) !== 0); + segment[segmentLength++] = (vlqResult & 1) === 1 + ? -(vlqResult >> 1) + : (vlqResult >> 1); } }