mirror of https://github.com/sveltejs/svelte
parent
e86fb16402
commit
b684833126
@ -1,350 +1,373 @@
|
|||||||
import type { DecodedSourceMap, RawSourceMap, SourceMapLoader } from '@ampproject/remapping';
|
|
||||||
import remapping from '@ampproject/remapping';
|
import remapping from '@ampproject/remapping';
|
||||||
import { SourceMap } from 'magic-string';
|
import { push_array } from './push_array.js';
|
||||||
import { Source, Processed } from '../preprocess/types';
|
|
||||||
import { push_array } from './push_array';
|
|
||||||
|
|
||||||
export type SourceLocation = {
|
/**
|
||||||
line: number;
|
* @param {string} s
|
||||||
column: number;
|
*/
|
||||||
};
|
function last_line_length(s) {
|
||||||
|
return s.length - s.lastIndexOf('\n') - 1;
|
||||||
function last_line_length(s: string) {
|
|
||||||
return s.length - s.lastIndexOf('\n') - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutate map in-place
|
// mutate map in-place
|
||||||
export function sourcemap_add_offset(
|
|
||||||
map: DecodedSourceMap,
|
|
||||||
offset: SourceLocation,
|
|
||||||
source_index: number
|
|
||||||
) {
|
|
||||||
if (map.mappings.length == 0) return;
|
|
||||||
for (let line = 0; line < map.mappings.length; line++) {
|
|
||||||
const segment_list = map.mappings[line];
|
|
||||||
for (let segment = 0; segment < segment_list.length; segment++) {
|
|
||||||
const seg = segment_list[segment];
|
|
||||||
// shift only segments that belong to component source file
|
|
||||||
if (seg[1] === source_index) {
|
|
||||||
// also ensures that seg.length >= 4
|
|
||||||
// shift column if it points at the first line
|
|
||||||
if (seg[2] === 0) {
|
|
||||||
seg[3] += offset.column;
|
|
||||||
}
|
|
||||||
// shift line
|
|
||||||
seg[2] += offset.line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function merge_tables<T>(this_table: T[], other_table: T[]): [T[], number[], boolean, boolean] {
|
/**
|
||||||
const new_table = this_table.slice();
|
* @param {DecodedSourceMap} map
|
||||||
const idx_map = [];
|
* @param {SourceLocation} offset
|
||||||
other_table = other_table || [];
|
* @param {number} source_index
|
||||||
let val_changed = false;
|
*/
|
||||||
for (const [other_idx, other_val] of other_table.entries()) {
|
export function sourcemap_add_offset(map, offset, source_index) {
|
||||||
const this_idx = this_table.indexOf(other_val);
|
if (map.mappings.length == 0)
|
||||||
if (this_idx >= 0) {
|
return;
|
||||||
idx_map[other_idx] = this_idx;
|
for (let line = 0; line < map.mappings.length; line++) {
|
||||||
} else {
|
const segment_list = map.mappings[line];
|
||||||
const new_idx = new_table.length;
|
for (let segment = 0; segment < segment_list.length; segment++) {
|
||||||
new_table[new_idx] = other_val;
|
const seg = segment_list[segment];
|
||||||
idx_map[other_idx] = new_idx;
|
// shift only segments that belong to component source file
|
||||||
val_changed = true;
|
if (seg[1] === source_index) {
|
||||||
}
|
// also ensures that seg.length >= 4
|
||||||
}
|
// shift column if it points at the first line
|
||||||
let idx_changed = val_changed;
|
if (seg[2] === 0) {
|
||||||
if (val_changed) {
|
seg[3] += offset.column;
|
||||||
if (idx_map.find((val, idx) => val != idx) === undefined) {
|
}
|
||||||
// idx_map is identity map [0, 1, 2, 3, 4, ....]
|
// shift line
|
||||||
idx_changed = false;
|
seg[2] += offset.line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [new_table, idx_map, val_changed, idx_changed];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {T[]} this_table
|
||||||
|
* @param {T[]} other_table
|
||||||
|
* @returns {[T[], number[], boolean, boolean]}
|
||||||
|
*/
|
||||||
|
function merge_tables(this_table, other_table) {
|
||||||
|
const new_table = this_table.slice();
|
||||||
|
const idx_map = [];
|
||||||
|
other_table = other_table || [];
|
||||||
|
let val_changed = false;
|
||||||
|
for (const [other_idx, other_val] of other_table.entries()) {
|
||||||
|
const this_idx = this_table.indexOf(other_val);
|
||||||
|
if (this_idx >= 0) {
|
||||||
|
idx_map[other_idx] = this_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const new_idx = new_table.length;
|
||||||
|
new_table[new_idx] = other_val;
|
||||||
|
idx_map[other_idx] = new_idx;
|
||||||
|
val_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let idx_changed = val_changed;
|
||||||
|
if (val_changed) {
|
||||||
|
if (idx_map.find((val, idx) => val != idx) === undefined) {
|
||||||
|
// idx_map is identity map [0, 1, 2, 3, 4, ....]
|
||||||
|
idx_changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [new_table, idx_map, val_changed, idx_changed];
|
||||||
|
}
|
||||||
const regex_line_token = /([^\d\w\s]|\s+)/g;
|
const regex_line_token = /([^\d\w\s]|\s+)/g;
|
||||||
|
/** */
|
||||||
export class MappedCode {
|
export class MappedCode {
|
||||||
string: string;
|
|
||||||
map: DecodedSourceMap;
|
|
||||||
|
|
||||||
constructor(string = '', map: DecodedSourceMap = null) {
|
|
||||||
this.string = string;
|
|
||||||
if (map) {
|
|
||||||
this.map = map as DecodedSourceMap;
|
|
||||||
} else {
|
|
||||||
this.map = {
|
|
||||||
version: 3,
|
|
||||||
mappings: [],
|
|
||||||
sources: [],
|
|
||||||
names: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* concat in-place (mutable), return this (chainable)
|
|
||||||
* will also mutate the `other` object
|
|
||||||
*/
|
|
||||||
concat(other: MappedCode): MappedCode {
|
|
||||||
// noop: if one is empty, return the other
|
|
||||||
if (other.string == '') return this;
|
|
||||||
if (this.string == '') {
|
|
||||||
this.string = other.string;
|
|
||||||
this.map = other.map;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute last line length before mutating
|
|
||||||
const column_offset = last_line_length(this.string);
|
|
||||||
|
|
||||||
this.string += other.string;
|
|
||||||
|
|
||||||
const m1 = this.map;
|
|
||||||
const m2 = other.map;
|
|
||||||
|
|
||||||
if (m2.mappings.length == 0) return this;
|
|
||||||
|
|
||||||
// combine sources and names
|
|
||||||
const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(
|
|
||||||
m1.sources,
|
|
||||||
m2.sources
|
|
||||||
);
|
|
||||||
const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(
|
|
||||||
m1.names,
|
|
||||||
m2.names
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sources_changed) m1.sources = sources;
|
|
||||||
if (names_changed) m1.names = names;
|
|
||||||
|
|
||||||
// unswitched loops are faster
|
|
||||||
if (sources_idx_changed && names_idx_changed) {
|
|
||||||
for (let line = 0; line < m2.mappings.length; line++) {
|
|
||||||
const segment_list = m2.mappings[line];
|
|
||||||
for (let segment = 0; segment < segment_list.length; segment++) {
|
|
||||||
const seg = segment_list[segment];
|
|
||||||
if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
|
|
||||||
if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (sources_idx_changed) {
|
|
||||||
for (let line = 0; line < m2.mappings.length; line++) {
|
|
||||||
const segment_list = m2.mappings[line];
|
|
||||||
for (let segment = 0; segment < segment_list.length; segment++) {
|
|
||||||
const seg = segment_list[segment];
|
|
||||||
if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (names_idx_changed) {
|
|
||||||
for (let line = 0; line < m2.mappings.length; line++) {
|
|
||||||
const segment_list = m2.mappings[line];
|
|
||||||
for (let segment = 0; segment < segment_list.length; segment++) {
|
|
||||||
const seg = segment_list[segment];
|
|
||||||
if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// combine the mappings
|
|
||||||
|
|
||||||
// combine
|
|
||||||
// 1. last line of first map
|
|
||||||
// 2. first line of second map
|
|
||||||
// columns of 2 must be shifted
|
|
||||||
|
|
||||||
if (m2.mappings.length > 0 && column_offset > 0) {
|
|
||||||
const first_line = m2.mappings[0];
|
|
||||||
for (let i = 0; i < first_line.length; i++) {
|
|
||||||
first_line[i][0] += column_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// combine last line + first line
|
|
||||||
push_array(m1.mappings[m1.mappings.length - 1], m2.mappings.shift());
|
|
||||||
|
|
||||||
// append other lines
|
|
||||||
push_array(m1.mappings, m2.mappings);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
static from_processed(string: string, map?: DecodedSourceMap): MappedCode {
|
|
||||||
const line_count = string.split('\n').length;
|
|
||||||
|
|
||||||
if (map) {
|
/**
|
||||||
// ensure that count of source map mappings lines
|
* @type {string}
|
||||||
// is equal to count of generated code lines
|
*/
|
||||||
// (some tools may produce less)
|
string = undefined;
|
||||||
const missing_lines = line_count - map.mappings.length;
|
|
||||||
for (let i = 0; i < missing_lines; i++) {
|
/**
|
||||||
map.mappings.push([]);
|
* @type {DecodedSourceMap}
|
||||||
}
|
*/
|
||||||
return new MappedCode(string, map);
|
map = undefined;
|
||||||
}
|
constructor(string = '', map = null) {
|
||||||
|
this.string = string;
|
||||||
if (string == '') return new MappedCode();
|
if (map) {
|
||||||
map = { version: 3, names: [], sources: [], mappings: [] };
|
this.map = map;
|
||||||
|
}
|
||||||
// add empty SourceMapSegment[] for every line
|
else {
|
||||||
for (let i = 0; i < line_count; i++) map.mappings.push([]);
|
this.map = {
|
||||||
return new MappedCode(string, map);
|
version: 3,
|
||||||
}
|
mappings: [],
|
||||||
|
sources: [],
|
||||||
static from_source({ source, file_basename, get_location }: Source): MappedCode {
|
names: []
|
||||||
let offset: SourceLocation = get_location(0);
|
};
|
||||||
|
}
|
||||||
if (!offset) offset = { line: 0, column: 0 };
|
}
|
||||||
const map: DecodedSourceMap = { version: 3, names: [], sources: [file_basename], mappings: [] };
|
/**
|
||||||
if (source == '') return new MappedCode(source, map);
|
* concat in-place (mutable), return this (chainable)
|
||||||
|
* will also mutate the `other` object
|
||||||
// we create a high resolution identity map here,
|
* @param {MappedCode} other
|
||||||
// we know that it will eventually be merged with svelte's map,
|
* @returns {import("C:/repos/svelte/svelte/mapped_code.ts-to-jsdoc").MappedCode}
|
||||||
// at which stage the resolution will decrease.
|
*/
|
||||||
const line_list = source.split('\n');
|
concat(other) {
|
||||||
for (let line = 0; line < line_list.length; line++) {
|
// noop: if one is empty, return the other
|
||||||
map.mappings.push([]);
|
if (other.string == '')
|
||||||
const token_list = line_list[line].split(regex_line_token);
|
return this;
|
||||||
for (let token = 0, column = 0; token < token_list.length; token++) {
|
if (this.string == '') {
|
||||||
if (token_list[token] == '') continue;
|
this.string = other.string;
|
||||||
map.mappings[line].push([column, 0, offset.line + line, column]);
|
this.map = other.map;
|
||||||
column += token_list[token].length;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
// compute last line length before mutating
|
||||||
// shift columns in first line
|
const column_offset = last_line_length(this.string);
|
||||||
const segment_list = map.mappings[0];
|
this.string += other.string;
|
||||||
for (let segment = 0; segment < segment_list.length; segment++) {
|
const m1 = this.map;
|
||||||
segment_list[segment][3] += offset.column;
|
const m2 = other.map;
|
||||||
}
|
if (m2.mappings.length == 0)
|
||||||
return new MappedCode(source, map);
|
return this;
|
||||||
}
|
// combine sources and names
|
||||||
|
const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(m1.sources, m2.sources);
|
||||||
|
const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(m1.names, m2.names);
|
||||||
|
if (sources_changed)
|
||||||
|
m1.sources = sources;
|
||||||
|
if (names_changed)
|
||||||
|
m1.names = names;
|
||||||
|
// unswitched loops are faster
|
||||||
|
if (sources_idx_changed && names_idx_changed) {
|
||||||
|
for (let line = 0; line < m2.mappings.length; line++) {
|
||||||
|
const segment_list = m2.mappings[line];
|
||||||
|
for (let segment = 0; segment < segment_list.length; segment++) {
|
||||||
|
const seg = segment_list[segment];
|
||||||
|
if (seg[1] >= 0)
|
||||||
|
seg[1] = new_source_idx[seg[1]];
|
||||||
|
if (seg[4] >= 0)
|
||||||
|
seg[4] = new_name_idx[seg[4]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sources_idx_changed) {
|
||||||
|
for (let line = 0; line < m2.mappings.length; line++) {
|
||||||
|
const segment_list = m2.mappings[line];
|
||||||
|
for (let segment = 0; segment < segment_list.length; segment++) {
|
||||||
|
const seg = segment_list[segment];
|
||||||
|
if (seg[1] >= 0)
|
||||||
|
seg[1] = new_source_idx[seg[1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (names_idx_changed) {
|
||||||
|
for (let line = 0; line < m2.mappings.length; line++) {
|
||||||
|
const segment_list = m2.mappings[line];
|
||||||
|
for (let segment = 0; segment < segment_list.length; segment++) {
|
||||||
|
const seg = segment_list[segment];
|
||||||
|
if (seg[4] >= 0)
|
||||||
|
seg[4] = new_name_idx[seg[4]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// combine the mappings
|
||||||
|
// combine
|
||||||
|
// 1. last line of first map
|
||||||
|
// 2. first line of second map
|
||||||
|
// columns of 2 must be shifted
|
||||||
|
if (m2.mappings.length > 0 && column_offset > 0) {
|
||||||
|
const first_line = m2.mappings[0];
|
||||||
|
for (let i = 0; i < first_line.length; i++) {
|
||||||
|
first_line[i][0] += column_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// combine last line + first line
|
||||||
|
push_array(m1.mappings[m1.mappings.length - 1], m2.mappings.shift());
|
||||||
|
// append other lines
|
||||||
|
push_array(m1.mappings, m2.mappings);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @static
|
||||||
|
* @param {string} string
|
||||||
|
* @param {DecodedSourceMap} [map]
|
||||||
|
* @returns {import("C:/repos/svelte/svelte/mapped_code.ts-to-jsdoc").MappedCode}
|
||||||
|
*/
|
||||||
|
static from_processed(string, map) {
|
||||||
|
const line_count = string.split('\n').length;
|
||||||
|
if (map) {
|
||||||
|
// ensure that count of source map mappings lines
|
||||||
|
// is equal to count of generated code lines
|
||||||
|
// (some tools may produce less)
|
||||||
|
const missing_lines = line_count - map.mappings.length;
|
||||||
|
for (let i = 0; i < missing_lines; i++) {
|
||||||
|
map.mappings.push([]);
|
||||||
|
}
|
||||||
|
return new MappedCode(string, map);
|
||||||
|
}
|
||||||
|
if (string == '')
|
||||||
|
return new MappedCode();
|
||||||
|
map = { version: 3, names: [], sources: [], mappings: [] };
|
||||||
|
// add empty SourceMapSegment[] for every line
|
||||||
|
for (let i = 0; i < line_count; i++)
|
||||||
|
map.mappings.push([]);
|
||||||
|
return new MappedCode(string, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @static
|
||||||
|
* @param {Source}
|
||||||
|
* @returns {import("C:/repos/svelte/svelte/mapped_code.ts-to-jsdoc").MappedCode}
|
||||||
|
*/
|
||||||
|
static from_source({ source, file_basename, get_location }) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {SourceLocation}
|
||||||
|
*/
|
||||||
|
let offset = get_location(0);
|
||||||
|
if (!offset)
|
||||||
|
offset = { line: 0, column: 0 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {DecodedSourceMap}
|
||||||
|
*/
|
||||||
|
const map = { version: 3, names: [], sources: [file_basename], mappings: [] };
|
||||||
|
if (source == '')
|
||||||
|
return new MappedCode(source, map);
|
||||||
|
// we create a high resolution identity map here,
|
||||||
|
// we know that it will eventually be merged with svelte's map,
|
||||||
|
// at which stage the resolution will decrease.
|
||||||
|
const line_list = source.split('\n');
|
||||||
|
for (let line = 0; line < line_list.length; line++) {
|
||||||
|
map.mappings.push([]);
|
||||||
|
const token_list = line_list[line].split(regex_line_token);
|
||||||
|
for (let token = 0, column = 0; token < token_list.length; token++) {
|
||||||
|
if (token_list[token] == '')
|
||||||
|
continue;
|
||||||
|
map.mappings[line].push([column, 0, offset.line + line, column]);
|
||||||
|
column += token_list[token].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// shift columns in first line
|
||||||
|
const segment_list = map.mappings[0];
|
||||||
|
for (let segment = 0; segment < segment_list.length; segment++) {
|
||||||
|
segment_list[segment][3] += offset.column;
|
||||||
|
}
|
||||||
|
return new MappedCode(source, map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function combine_sourcemaps(
|
/**
|
||||||
filename: string,
|
* @param {string} filename
|
||||||
sourcemap_list: Array<DecodedSourceMap | RawSourceMap>
|
* @param {Array<DecodedSourceMap | RawSourceMap>} sourcemap_list
|
||||||
) {
|
*/
|
||||||
if (sourcemap_list.length == 0) return null;
|
export function combine_sourcemaps(filename, sourcemap_list) {
|
||||||
|
if (sourcemap_list.length == 0)
|
||||||
let map_idx = 1;
|
return null;
|
||||||
const map =
|
let map_idx = 1;
|
||||||
sourcemap_list.slice(0, -1).find((m) => m.sources.length !== 1) === undefined
|
const map = sourcemap_list.slice(0, -1).find((m) => m.sources.length !== 1) === undefined
|
||||||
? remapping(
|
? remapping(
|
||||||
// use array interface
|
// use array interface
|
||||||
// only the oldest sourcemap can have multiple sources
|
// only the oldest sourcemap can have multiple sources
|
||||||
sourcemap_list,
|
sourcemap_list, () => null, true // skip optional field `sourcesContent`
|
||||||
() => null,
|
)
|
||||||
true // skip optional field `sourcesContent`
|
: remapping(
|
||||||
)
|
// use loader interface
|
||||||
: remapping(
|
sourcemap_list[0], // last map
|
||||||
// use loader interface
|
function loader(sourcefile) {
|
||||||
sourcemap_list[0], // last map
|
if (sourcefile === filename && sourcemap_list[map_idx]) {
|
||||||
function loader(sourcefile) {
|
return sourcemap_list[map_idx++]; // idx 1, 2, ...
|
||||||
if (sourcefile === filename && sourcemap_list[map_idx]) {
|
// bundle file = branch node
|
||||||
return sourcemap_list[map_idx++]; // idx 1, 2, ...
|
}
|
||||||
// bundle file = branch node
|
else {
|
||||||
} else {
|
return null; // source file = leaf node
|
||||||
return null; // source file = leaf node
|
}
|
||||||
}
|
}, true);
|
||||||
} as SourceMapLoader,
|
if (!map.file)
|
||||||
true
|
delete map.file; // skip optional field `file`
|
||||||
);
|
// When source maps are combined and the leading map is empty, sources is not set.
|
||||||
|
// Add the filename to the empty array in this case.
|
||||||
if (!map.file) delete map.file; // skip optional field `file`
|
// Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116
|
||||||
|
if (!map.sources.length)
|
||||||
// When source maps are combined and the leading map is empty, sources is not set.
|
map.sources = [filename];
|
||||||
// Add the filename to the empty array in this case.
|
return map;
|
||||||
// Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116
|
|
||||||
if (!map.sources.length) map.sources = [filename];
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// browser vs node.js
|
// browser vs node.js
|
||||||
const b64enc = typeof btoa == 'function' ? btoa : (b) => Buffer.from(b).toString('base64');
|
const b64enc = typeof btoa == 'function' ? btoa : (b) => Buffer.from(b).toString('base64');
|
||||||
const b64dec = typeof atob == 'function' ? atob : (a) => Buffer.from(a, 'base64').toString();
|
const b64dec = typeof atob == 'function' ? atob : (a) => Buffer.from(a, 'base64').toString();
|
||||||
|
|
||||||
export function apply_preprocessor_sourcemap(
|
/**
|
||||||
filename: string,
|
* @param {string} filename
|
||||||
svelte_map: SourceMap,
|
* @param {SourceMap} svelte_map
|
||||||
preprocessor_map_input: string | DecodedSourceMap | RawSourceMap
|
* @param {string | DecodedSourceMap | RawSourceMap} preprocessor_map_input
|
||||||
): SourceMap {
|
* @returns {SourceMap}
|
||||||
if (!svelte_map || !preprocessor_map_input) return svelte_map;
|
*/
|
||||||
|
export function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
|
||||||
const preprocessor_map =
|
if (!svelte_map || !preprocessor_map_input)
|
||||||
typeof preprocessor_map_input === 'string'
|
return svelte_map;
|
||||||
? JSON.parse(preprocessor_map_input)
|
const preprocessor_map = typeof preprocessor_map_input === 'string'
|
||||||
: preprocessor_map_input;
|
? JSON.parse(preprocessor_map_input)
|
||||||
|
: preprocessor_map_input;
|
||||||
const result_map = combine_sourcemaps(filename, [
|
const result_map = combine_sourcemaps(filename, [
|
||||||
svelte_map as RawSourceMap,
|
svelte_map,
|
||||||
preprocessor_map
|
preprocessor_map
|
||||||
]) as RawSourceMap;
|
]);
|
||||||
|
// Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
|
||||||
// Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
|
// we just tack on the extra properties.
|
||||||
// we just tack on the extra properties.
|
Object.defineProperties(result_map, {
|
||||||
Object.defineProperties(result_map, {
|
toString: {
|
||||||
toString: {
|
enumerable: false,
|
||||||
enumerable: false,
|
value: function toString() {
|
||||||
value: function toString() {
|
return JSON.stringify(this);
|
||||||
return JSON.stringify(this);
|
}
|
||||||
}
|
},
|
||||||
},
|
toUrl: {
|
||||||
toUrl: {
|
enumerable: false,
|
||||||
enumerable: false,
|
value: function toUrl() {
|
||||||
value: function toUrl() {
|
return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
|
||||||
return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
return result_map;
|
||||||
|
|
||||||
return result_map as SourceMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/;
|
const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/;
|
||||||
|
|
||||||
// parse attached sourcemap in processed.code
|
// parse attached sourcemap in processed.code
|
||||||
export function parse_attached_sourcemap(processed: Processed, tag_name: 'script' | 'style'): void {
|
|
||||||
const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)';
|
/**
|
||||||
const regex =
|
* @param {Processed} processed
|
||||||
tag_name == 'script'
|
* @param {'script' | 'style'} tag_name
|
||||||
? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$')
|
* @returns {void}
|
||||||
: new RegExp('/\\*' + r_in + '\\s*\\*/$');
|
*/
|
||||||
function log_warning(message) {
|
export function parse_attached_sourcemap(processed, tag_name) {
|
||||||
// code_start: help to find preprocessor
|
const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)';
|
||||||
const code_start =
|
const regex = tag_name == 'script'
|
||||||
processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]';
|
? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$')
|
||||||
console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`);
|
: new RegExp('/\\*' + r_in + '\\s*\\*/$');
|
||||||
}
|
|
||||||
processed.code = processed.code.replace(regex, (_, match1, match2) => {
|
/**
|
||||||
const map_url = tag_name == 'script' ? match1 || match2 : match1;
|
* @param {any} message
|
||||||
const map_data = (map_url.match(regex_data_uri) || [])[1];
|
*/
|
||||||
if (map_data) {
|
function log_warning(message) {
|
||||||
// sourceMappingURL is data URL
|
// code_start: help to find preprocessor
|
||||||
if (processed.map) {
|
const code_start = processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]';
|
||||||
log_warning(
|
console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`);
|
||||||
'Not implemented. ' +
|
}
|
||||||
'Found sourcemap in both processed.code and processed.map. ' +
|
processed.code = processed.code.replace(regex, (_, match1, match2) => {
|
||||||
'Please update your preprocessor to return only one sourcemap.'
|
const map_url = tag_name == 'script' ? match1 || match2 : match1;
|
||||||
);
|
const map_data = (map_url.match(regex_data_uri) || [])[1];
|
||||||
// ignore attached sourcemap
|
if (map_data) {
|
||||||
return '';
|
// sourceMappingURL is data URL
|
||||||
}
|
if (processed.map) {
|
||||||
processed.map = b64dec(map_data); // use attached sourcemap
|
log_warning('Not implemented. ' +
|
||||||
return ''; // remove from processed.code
|
'Found sourcemap in both processed.code and processed.map. ' +
|
||||||
}
|
'Please update your preprocessor to return only one sourcemap.');
|
||||||
// sourceMappingURL is path or URL
|
// ignore attached sourcemap
|
||||||
if (!processed.map) {
|
return '';
|
||||||
log_warning(
|
}
|
||||||
`Found sourcemap path ${JSON.stringify(
|
processed.map = b64dec(map_data); // use attached sourcemap
|
||||||
map_url
|
return ''; // remove from processed.code
|
||||||
)} in processed.code, but no sourcemap data. ` +
|
}
|
||||||
'Please update your preprocessor to return sourcemap data directly.'
|
// sourceMappingURL is path or URL
|
||||||
);
|
if (!processed.map) {
|
||||||
}
|
log_warning(`Found sourcemap path ${JSON.stringify(map_url)} in processed.code, but no sourcemap data. ` +
|
||||||
// ignore sourcemap path
|
'Please update your preprocessor to return sourcemap data directly.');
|
||||||
return ''; // remove from processed.code
|
}
|
||||||
});
|
// ignore sourcemap path
|
||||||
|
return ''; // remove from processed.code
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* line: number;
|
||||||
|
* column: number;
|
||||||
|
* }} SourceLocation
|
||||||
|
*/
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in new issue