Lint and format src/compiler/utils/mapped_code.js

pull/8569/head
Simon Holthausen 3 years ago
parent 09ca9333a8
commit 6b92b39a16

@ -2,7 +2,7 @@ import remapping from '@ampproject/remapping';
import { push_array } from './push_array.js'; import { push_array } from './push_array.js';
/** /**
* @param {string} s * @param {string} s
*/ */
function last_line_length(s) { function last_line_length(s) {
return s.length - s.lastIndexOf('\n') - 1; return s.length - s.lastIndexOf('\n') - 1;
@ -15,8 +15,7 @@ function last_line_length(s) {
* @param {number} source_index * @param {number} source_index
*/ */
export function sourcemap_add_offset(map, offset, source_index) { export function sourcemap_add_offset(map, offset, source_index) {
if (map.mappings.length == 0) if (map.mappings.length == 0) return;
return;
for (let line = 0; line < map.mappings.length; line++) { for (let line = 0; line < map.mappings.length; line++) {
const segment_list = map.mappings[line]; const segment_list = map.mappings[line];
for (let segment = 0; segment < segment_list.length; segment++) { for (let segment = 0; segment < segment_list.length; segment++) {
@ -49,8 +48,7 @@ function merge_tables(this_table, other_table) {
const this_idx = this_table.indexOf(other_val); const this_idx = this_table.indexOf(other_val);
if (this_idx >= 0) { if (this_idx >= 0) {
idx_map[other_idx] = this_idx; idx_map[other_idx] = this_idx;
} } else {
else {
const new_idx = new_table.length; const new_idx = new_table.length;
new_table[new_idx] = other_val; new_table[new_idx] = other_val;
idx_map[other_idx] = new_idx; idx_map[other_idx] = new_idx;
@ -69,7 +67,6 @@ function merge_tables(this_table, other_table) {
const regex_line_token = /([^\d\w\s]|\s+)/g; const regex_line_token = /([^\d\w\s]|\s+)/g;
/** */ /** */
export class MappedCode { export class MappedCode {
/** /**
* @type {string} * @type {string}
*/ */
@ -83,8 +80,7 @@ export class MappedCode {
this.string = string; this.string = string;
if (map) { if (map) {
this.map = map; this.map = map;
} } else {
else {
this.map = { this.map = {
version: 3, version: 3,
mappings: [], mappings: [],
@ -101,8 +97,7 @@ export class MappedCode {
*/ */
concat(other) { concat(other) {
// noop: if one is empty, return the other // noop: if one is empty, return the other
if (other.string == '') if (other.string == '') return this;
return this;
if (this.string == '') { if (this.string == '') {
this.string = other.string; this.string = other.string;
this.map = other.map; this.map = other.map;
@ -113,45 +108,42 @@ export class MappedCode {
this.string += other.string; this.string += other.string;
const m1 = this.map; const m1 = this.map;
const m2 = other.map; const m2 = other.map;
if (m2.mappings.length == 0) if (m2.mappings.length == 0) return this;
return this;
// combine sources and names // combine sources and names
const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(m1.sources, m2.sources); const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(
const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(m1.names, m2.names); m1.sources,
if (sources_changed) m2.sources
m1.sources = sources; );
if (names_changed) const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(
m1.names = names; m1.names,
m2.names
);
if (sources_changed) m1.sources = sources;
if (names_changed) m1.names = names;
// unswitched loops are faster // unswitched loops are faster
if (sources_idx_changed && names_idx_changed) { if (sources_idx_changed && names_idx_changed) {
for (let line = 0; line < m2.mappings.length; line++) { for (let line = 0; line < m2.mappings.length; line++) {
const segment_list = m2.mappings[line]; const segment_list = m2.mappings[line];
for (let segment = 0; segment < segment_list.length; segment++) { for (let segment = 0; segment < segment_list.length; segment++) {
const seg = segment_list[segment]; const seg = segment_list[segment];
if (seg[1] >= 0) if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
seg[1] = new_source_idx[seg[1]]; if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
if (seg[4] >= 0)
seg[4] = new_name_idx[seg[4]];
}
} }
} }
else if (sources_idx_changed) { } else if (sources_idx_changed) {
for (let line = 0; line < m2.mappings.length; line++) { for (let line = 0; line < m2.mappings.length; line++) {
const segment_list = m2.mappings[line]; const segment_list = m2.mappings[line];
for (let segment = 0; segment < segment_list.length; segment++) { for (let segment = 0; segment < segment_list.length; segment++) {
const seg = segment_list[segment]; const seg = segment_list[segment];
if (seg[1] >= 0) if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
seg[1] = new_source_idx[seg[1]];
}
} }
} }
else if (names_idx_changed) { } else if (names_idx_changed) {
for (let line = 0; line < m2.mappings.length; line++) { for (let line = 0; line < m2.mappings.length; line++) {
const segment_list = m2.mappings[line]; const segment_list = m2.mappings[line];
for (let segment = 0; segment < segment_list.length; segment++) { for (let segment = 0; segment < segment_list.length; segment++) {
const seg = segment_list[segment]; const seg = segment_list[segment];
if (seg[4] >= 0) if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
seg[4] = new_name_idx[seg[4]];
} }
} }
} }
@ -191,12 +183,10 @@ export class MappedCode {
} }
return new MappedCode(string, map); return new MappedCode(string, map);
} }
if (string == '') if (string == '') return new MappedCode();
return new MappedCode();
map = { version: 3, names: [], sources: [], mappings: [] }; map = { version: 3, names: [], sources: [], mappings: [] };
// add empty SourceMapSegment[] for every line // add empty SourceMapSegment[] for every line
for (let i = 0; i < line_count; i++) for (let i = 0; i < line_count; i++) map.mappings.push([]);
map.mappings.push([]);
return new MappedCode(string, map); return new MappedCode(string, map);
} }
@ -206,20 +196,17 @@ export class MappedCode {
* @returns {import("C:/repos/svelte/svelte/mapped_code.ts-to-jsdoc").MappedCode} * @returns {import("C:/repos/svelte/svelte/mapped_code.ts-to-jsdoc").MappedCode}
*/ */
static from_source({ source, file_basename, get_location }) { static from_source({ source, file_basename, get_location }) {
/** /**
* @type {SourceLocation} * @type {SourceLocation}
*/ */
let offset = get_location(0); let offset = get_location(0);
if (!offset) if (!offset) offset = { line: 0, column: 0 };
offset = { line: 0, column: 0 };
/** /**
* @type {DecodedSourceMap} * @type {DecodedSourceMap}
*/ */
const map = { version: 3, names: [], sources: [file_basename], mappings: [] }; const map = { version: 3, names: [], sources: [file_basename], mappings: [] };
if (source == '') if (source == '') return new MappedCode(source, map);
return new MappedCode(source, map);
// we create a high resolution identity map here, // we create a high resolution identity map here,
// we know that it will eventually be merged with svelte's map, // we know that it will eventually be merged with svelte's map,
// at which stage the resolution will decrease. // at which stage the resolution will decrease.
@ -228,8 +215,7 @@ export class MappedCode {
map.mappings.push([]); map.mappings.push([]);
const token_list = line_list[line].split(regex_line_token); const token_list = line_list[line].split(regex_line_token);
for (let token = 0, column = 0; token < token_list.length; token++) { for (let token = 0, column = 0; token < token_list.length; token++) {
if (token_list[token] == '') if (token_list[token] == '') continue;
continue;
map.mappings[line].push([column, 0, offset.line + line, column]); map.mappings[line].push([column, 0, offset.line + line, column]);
column += token_list[token].length; column += token_list[token].length;
} }
@ -248,34 +234,35 @@ export class MappedCode {
* @param {Array<DecodedSourceMap | RawSourceMap>} sourcemap_list * @param {Array<DecodedSourceMap | RawSourceMap>} sourcemap_list
*/ */
export function combine_sourcemaps(filename, sourcemap_list) { export function combine_sourcemaps(filename, sourcemap_list) {
if (sourcemap_list.length == 0) if (sourcemap_list.length == 0) return null;
return null;
let map_idx = 1; let map_idx = 1;
const map = 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, () => null, true // skip optional field `sourcesContent` sourcemap_list,
() => null,
true // skip optional field `sourcesContent`
) )
: remapping( : remapping(
// use loader interface // use loader interface
sourcemap_list[0], // last map sourcemap_list[0], // last map
function loader(sourcefile) { (sourcefile) => {
if (sourcefile === filename && sourcemap_list[map_idx]) { if (sourcefile === filename && sourcemap_list[map_idx]) {
return sourcemap_list[map_idx++]; // idx 1, 2, ... return sourcemap_list[map_idx++]; // idx 1, 2, ...
// bundle file = branch node // bundle file = branch node
} } else {
else {
return null; // source file = leaf node return null; // source file = leaf node
} }
}, true); },
if (!map.file) true
delete map.file; // skip optional field `file` );
if (!map.file) delete map.file; // skip optional field `file`
// When source maps are combined and the leading map is empty, sources is not set. // 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. // Add the filename to the empty array in this case.
// Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116 // Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116
if (!map.sources.length) if (!map.sources.length) map.sources = [filename];
map.sources = [filename];
return map; return map;
} }
// browser vs node.js // browser vs node.js
@ -289,15 +276,12 @@ const b64dec = typeof atob == 'function' ? atob : (a) => Buffer.from(a, 'base64'
* @returns {SourceMap} * @returns {SourceMap}
*/ */
export function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) { export function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
if (!svelte_map || !preprocessor_map_input) if (!svelte_map || !preprocessor_map_input) return svelte_map;
return svelte_map; const preprocessor_map =
const preprocessor_map = typeof preprocessor_map_input === 'string' typeof preprocessor_map_input === 'string'
? JSON.parse(preprocessor_map_input) ? JSON.parse(preprocessor_map_input)
: preprocessor_map_input; : preprocessor_map_input;
const result_map = combine_sourcemaps(filename, [ const result_map = combine_sourcemaps(filename, [svelte_map, preprocessor_map]);
svelte_map,
preprocessor_map
]);
// 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, {
@ -326,7 +310,8 @@ const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?bas
*/ */
export function parse_attached_sourcemap(processed, tag_name) { export function parse_attached_sourcemap(processed, tag_name) {
const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)'; const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)';
const regex = tag_name == 'script' const regex =
tag_name == 'script'
? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$') ? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$')
: new RegExp('/\\*' + r_in + '\\s*\\*/$'); : new RegExp('/\\*' + r_in + '\\s*\\*/$');
@ -335,7 +320,8 @@ export function parse_attached_sourcemap(processed, tag_name) {
*/ */
function log_warning(message) { function log_warning(message) {
// code_start: help to find preprocessor // code_start: help to find preprocessor
const code_start = processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]'; const code_start =
processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]';
console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`); console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`);
} }
processed.code = processed.code.replace(regex, (_, match1, match2) => { processed.code = processed.code.replace(regex, (_, match1, match2) => {
@ -344,9 +330,11 @@ export function parse_attached_sourcemap(processed, tag_name) {
if (map_data) { if (map_data) {
// sourceMappingURL is data URL // sourceMappingURL is data URL
if (processed.map) { if (processed.map) {
log_warning('Not implemented. ' + log_warning(
'Not implemented. ' +
'Found sourcemap in both processed.code and processed.map. ' + 'Found sourcemap in both processed.code and processed.map. ' +
'Please update your preprocessor to return only one sourcemap.'); 'Please update your preprocessor to return only one sourcemap.'
);
// ignore attached sourcemap // ignore attached sourcemap
return ''; return '';
} }
@ -355,19 +343,21 @@ export function parse_attached_sourcemap(processed, tag_name) {
} }
// sourceMappingURL is path or URL // sourceMappingURL is path or URL
if (!processed.map) { if (!processed.map) {
log_warning(`Found sourcemap path ${JSON.stringify(map_url)} in processed.code, but no sourcemap data. ` + log_warning(
'Please update your preprocessor to return sourcemap data directly.'); `Found sourcemap path ${JSON.stringify(
map_url
)} in processed.code, but no sourcemap data. ` +
'Please update your preprocessor to return sourcemap data directly.'
);
} }
// ignore sourcemap path // ignore sourcemap path
return ''; // remove from processed.code return ''; // remove from processed.code
}); });
} }
/** /**
* @typedef {{ * @typedef {{
* line: number; * line: number;
* column: number; * column: number;
* }} SourceLocation * }} SourceLocation
*/ */

Loading…
Cancel
Save