Skip to content

Commit

Permalink
Merge pull request #58 from cenfun/sourcemap-sections
Browse files Browse the repository at this point in the history
Support Indexed Sourcemaps
  • Loading branch information
cenfun authored Jul 13, 2024
2 parents dbaab32 + 773107e commit 57c3933
Show file tree
Hide file tree
Showing 12 changed files with 620 additions and 14 deletions.
60 changes: 51 additions & 9 deletions lib/converter/collect-source-maps.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const EC = require('eight-colors');
const { fileURLToPath, pathToFileURL } = require('url');
const Concurrency = require('../platform/concurrency.js');
const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
const { flattenSourceMaps } = require('./flatten-source-maps.js');

const Util = require('../utils/util.js');

Expand Down Expand Up @@ -100,27 +101,68 @@ const resolveSourcesContent = (data, url) => {
}
};

const checkSourcesContent = (data) => {
const { sourcesContent, sources } = data;

if (!sourcesContent) {
data.sourcesContent = [];
return false;
}

// all should be string, could be [null]
const contents = sourcesContent.filter((content) => typeof content === 'string');
if (contents.length === sources.length) {
return true;
}

return false;
};

const resolveSectionedSourceMap = (data, url, sections) => {

let hasSourceContent = false;
sections.forEach((item) => {
// offset: { line: 1, column: 0 },
// map: { sources, sourcesContent }

const map = item.map;

if (checkSourcesContent(map)) {
hasSourceContent = true;
return;
}

const done = resolveSourcesContent(map, url);
if (done) {
hasSourceContent = true;
}

});

if (hasSourceContent) {
return flattenSourceMaps(data);
}
};

const resolveSourceMap = (data, url) => {
if (!data) {
return;
}
const {
sources, sourcesContent, mappings
sections, sources, mappings
} = data;

if (sections) {
return resolveSectionedSourceMap(data, url, sections);
}

if (!sources || !mappings) {
return;
}

// check sources content
if (sourcesContent) {
// all should be string, could be [null]
const contents = sourcesContent.filter((content) => typeof content === 'string');
if (contents.length === sources.length) {
return data;
}
} else {
data.sourcesContent = [];
if (checkSourcesContent(data)) {
return data;
}

// load sources content by sources
Expand Down
8 changes: 6 additions & 2 deletions lib/converter/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,13 @@ const decodeSourceMappings = (state, originalDecodedMap) => {

const generatedLocator = state.locator;

const { sources, mappings } = state.sourceMap;
const {
sources, mappings, decodedMappings
} = state.sourceMap;

const decodedList = decodedMappings || decode(mappings);

const decodedList = decode(mappings);
// console.log(decodedList);

sources.forEach((source, i) => {
originalDecodedMap.set(i, []);
Expand Down
166 changes: 166 additions & 0 deletions lib/converter/flatten-source-maps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
const { decode } = require('@jridgewell/sourcemap-codec');

function getLine(arr, index) {
for (let i = arr.length; i <= index; i++) {
arr[i] = [];
}
return arr[index];
}

function addMappings(options, sourcesOffset) {

const {
input,
lineOffset,
columnOffset,
stopLine,
stopColumn
} = options;

const decoded = decode(input.mappings);
const COLUMN = 0;
const SOURCES_INDEX = 1;
const SOURCE_LINE = 2;
const SOURCE_COLUMN = 3;

for (let i = 0; i < decoded.length; i++) {
const lineI = lineOffset + i;

if (lineI > stopLine) {
return;
}

const out = getLine(options.decodedMappings, lineI);
const cOffset = i === 0 ? columnOffset : 0;

const line = decoded[i];
for (let j = 0; j < line.length; j++) {
const seg = line[j];
const column = cOffset + seg[COLUMN];

if (lineI === stopLine && column >= stopColumn) {
return;
}

if (seg.length === 1) {
out.push([column]);
continue;
}

const sourcesIndex = sourcesOffset + seg[SOURCES_INDEX];
const sourceLine = seg[SOURCE_LINE];
const sourceColumn = seg[SOURCE_COLUMN];
out.push([column, sourcesIndex, sourceLine, sourceColumn]);
}
}
}

function addSection(options) {

const { input } = options;

const { sections } = input;
if (sections) {
return flatten(options);
}

const sourcesOffset = options.sources.length;

if (!input.sourcesContent) {
input.sourcesContent = [];
}
input.sources.forEach((src, i) => {
options.sources.push(src);
options.sourcesContent.push(input.sourcesContent[i] || null);
});

addMappings(options, sourcesOffset);

}

function flatten(options) {

const {
input,
lineOffset,
columnOffset,
stopLine,
stopColumn
} = options;

const { sections } = input;

for (let i = 0, l = sections.length; i < l; i++) {
const { map, offset } = sections[i];

let sl = stopLine;
let sc = stopColumn;
if (i + 1 < sections.length) {
const nextOffset = sections[i + 1].offset;
sl = Math.min(stopLine, lineOffset + nextOffset.line);

if (sl === stopLine) {
sc = Math.min(stopColumn, columnOffset + nextOffset.column);
} else if (sl < stopLine) {
sc = columnOffset + nextOffset.column;
}
}

options.input = map;
options.lineOffset = lineOffset + offset.line;
options.columnOffset = columnOffset + offset.column;
options.stopLine = sl;
options.stopColumn = sc;

addSection(options);
}
}

const flattenSourceMaps = function(indexedMap, mapUrl) {

const sections = indexedMap.sections;
if (!sections) {
return indexedMap;
}

const decodedMappings = [];
const sources = [];
const sourcesContent = [];
const names = [];
const ignoreList = [];

const lineOffset = 0;
const columnOffset = 0;
const stopLine = Infinity;
const stopColumn = Infinity;

flatten({
input: indexedMap,

mapUrl,

decodedMappings,
sources,
sourcesContent,

names,
ignoreList,

lineOffset,
columnOffset,
stopLine,
stopColumn
});

indexedMap.sources = sources;
indexedMap.sourcesContent = sourcesContent;
indexedMap.decodedMappings = decodedMappings;

// console.log(decodedMappings);

return indexedMap;
};

module.exports = {
flattenSourceMaps
};
2 changes: 2 additions & 0 deletions lib/utils/source-path.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const filterPath = (str) => {
// src/images/icons/sync-.svg$

str = str.replace(/\\\\/g, '/');
str = str.replace(/\?/g, '/');

// decodeURI("%20") to space
str = decodeURI(str);
// remove / of start, end or double, ./ ../
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"test-minify": "node ./test/test-minify.js",
"test-esbuild": "node ./test/test-esbuild.js",
"test-rollup": "node ./test/test-rollup.js",
"test-sections": "node ./test/test-sections.js",
"test-swc": "node ./test/test-swc.js",
"test-v8-and-istanbul": "node ./test/test-v8-and-istanbul.js",
"test-browser": "node ./test/test.js --browser",
Expand Down Expand Up @@ -108,4 +109,4 @@
"tsx": "^4.16.2",
"ws": "^8.18.0"
}
}
}
Loading

0 comments on commit 57c3933

Please sign in to comment.