mirror of https://github.com/sveltejs/svelte
chore: source maps for preprocessors + tests (#10459)
Add source map merging for preprocessors and get tests passing. - fixed some issues around the `sources` array where they weren't calculated relative to the input correctly - adjusted some CSS tests because due to our own CSS parser the AST is less granular, so there are less mappings now. Don't think this is a problem, but worth thinking about - removed enableSourcemap but only log a warning, the reason this was introduced was to mitigate a bug in Vite which occured when having the source map inlined into the SSR'd output. Since SSR doesn't contain inlined CSS anymore (and if it did, we would omit the source map) the reason for which it was introduced no longer exists - files without js mapping in it have no source mappings yet (originally added in Svelte 4 for #6092)pull/10479/head
parent
4b274dd00d
commit
f8ff2b6ea3
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: add proper source map support
|
@ -1,424 +0,0 @@
|
||||
// @ts-nocheck TODO this has a bunch of type errors in strict mode which may or may not hint at bugs - check at some point
|
||||
|
||||
import remapping from '@ampproject/remapping';
|
||||
import { push_array } from './push_array.js';
|
||||
|
||||
/** @param {string} s */
|
||||
function last_line_length(s) {
|
||||
return s.length - s.lastIndexOf('\n') - 1;
|
||||
}
|
||||
|
||||
// mutate map in-place
|
||||
|
||||
/**
|
||||
* @param {import('@ampproject/remapping').DecodedSourceMap} map
|
||||
* @param {SourceLocation} offset
|
||||
* @param {number} source_index
|
||||
*/
|
||||
export function sourcemap_add_offset(map, offset, source_index) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @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(
|
||||
/**
|
||||
* @param {any} val
|
||||
* @param {any} idx
|
||||
*/ (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;
|
||||
|
||||
export class MappedCode {
|
||||
/** @type {string} */
|
||||
string;
|
||||
|
||||
/** @type {import('@ampproject/remapping').DecodedSourceMap} */
|
||||
map;
|
||||
|
||||
/**
|
||||
* @param {any} string
|
||||
* @param {import('@ampproject/remapping').DecodedSourceMap} map
|
||||
*/
|
||||
constructor(string = '', map = null) {
|
||||
this.string = string;
|
||||
if (map) {
|
||||
this.map = /** @type {import('@ampproject/remapping').DecodedSourceMap} */ (map);
|
||||
} else {
|
||||
this.map = {
|
||||
version: 3,
|
||||
mappings: [],
|
||||
sources: [],
|
||||
names: []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* concat in-place (mutable), return this (chainable)
|
||||
* will also mutate the `other` object
|
||||
* @param {MappedCode} other
|
||||
* @returns {import("C:/repos/svelte/svelte-octane/mapped_code.ts-to-jsdoc").MappedCode}
|
||||
*/
|
||||
concat(other) {
|
||||
// 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
|
||||
* @param {string} string
|
||||
* @param {import('@ampproject/remapping').DecodedSourceMap} [map]
|
||||
* @returns {import("C:/repos/svelte/svelte-octane/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 {import('../preprocess/types.js').Source}params_0
|
||||
* @returns {import("C:/repos/svelte/svelte-octane/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 {import('@ampproject/remapping').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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filename
|
||||
* @param {Array<import('@ampproject/remapping').DecodedSourceMap | import('@ampproject/remapping').RawSourceMap>} sourcemap_list
|
||||
* @returns {import('@ampproject/remapping').RawSourceMap}
|
||||
*/
|
||||
export function combine_sourcemaps(filename, sourcemap_list) {
|
||||
if (sourcemap_list.length === 0) return null;
|
||||
|
||||
let map_idx = 1;
|
||||
|
||||
/** @type {import('@ampproject/remapping').RawSourceMap} */
|
||||
const map =
|
||||
sourcemap_list.slice(0, -1).find(/** @param {any} m */ (m) => m.sources.length !== 1) ===
|
||||
undefined
|
||||
? remapping(
|
||||
// use array interface
|
||||
// only the oldest sourcemap can have multiple sources
|
||||
sourcemap_list,
|
||||
() => null,
|
||||
true // skip optional field `sourcesContent`
|
||||
)
|
||||
: remapping(
|
||||
// use loader interface
|
||||
sourcemap_list[0], // last map
|
||||
|
||||
/** @type {import('@ampproject/remapping').SourceMapLoader} */ (
|
||||
(sourcefile) => {
|
||||
if (sourcefile === filename && sourcemap_list[map_idx]) {
|
||||
return sourcemap_list[map_idx++]; // idx 1, 2, ...
|
||||
// bundle file = branch node
|
||||
} else {
|
||||
return null; // source file = leaf node
|
||||
}
|
||||
}
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
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.
|
||||
// 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
|
||||
if (!map.sources.length) map.sources = [filename];
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
// browser vs node.js
|
||||
const b64enc =
|
||||
typeof btoa === 'function'
|
||||
? btoa /** @param {any} b */
|
||||
: (b) => Buffer.from(b).toString('base64');
|
||||
const b64dec =
|
||||
typeof atob === 'function'
|
||||
? atob /** @param {any} a */
|
||||
: (a) => Buffer.from(a, 'base64').toString();
|
||||
|
||||
/**
|
||||
* @param {string} filename
|
||||
* @param {import('magic-string').SourceMap} svelte_map
|
||||
* @param {string | import('@ampproject/remapping').DecodedSourceMap | import('@ampproject/remapping').RawSourceMap} preprocessor_map_input
|
||||
* @returns {import('magic-string').SourceMap}
|
||||
*/
|
||||
export function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
|
||||
if (!svelte_map || !preprocessor_map_input) return svelte_map;
|
||||
|
||||
const preprocessor_map =
|
||||
typeof preprocessor_map_input === 'string'
|
||||
? JSON.parse(preprocessor_map_input)
|
||||
: preprocessor_map_input;
|
||||
|
||||
const result_map = /** @type {import('@ampproject/remapping').RawSourceMap} */ (
|
||||
combine_sourcemaps(filename, [
|
||||
/** @type {import('@ampproject/remapping').RawSourceMap} */ (svelte_map),
|
||||
preprocessor_map
|
||||
])
|
||||
);
|
||||
|
||||
// Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
|
||||
// we just tack on the extra properties.
|
||||
Object.defineProperties(result_map, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
value: function toString() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
},
|
||||
toUrl: {
|
||||
enumerable: false,
|
||||
value: function toUrl() {
|
||||
return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return /** @type {import('magic-string').SourceMap} */ (result_map);
|
||||
}
|
||||
|
||||
const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/;
|
||||
|
||||
// parse attached sourcemap in processed.code
|
||||
|
||||
/**
|
||||
* @param {import('../preprocess/types.js').Processed} processed
|
||||
* @param {'script' | 'style'} tag_name
|
||||
* @returns {void}
|
||||
*/
|
||||
export function parse_attached_sourcemap(processed, tag_name) {
|
||||
const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)';
|
||||
const regex =
|
||||
tag_name === 'script'
|
||||
? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$')
|
||||
: new RegExp('/\\*' + r_in + '\\s*\\*/$');
|
||||
|
||||
/** @param {any} message */
|
||||
function log_warning(message) {
|
||||
// code_start: help to find preprocessor
|
||||
const code_start =
|
||||
processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]';
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`);
|
||||
}
|
||||
processed.code = processed.code.replace(
|
||||
regex,
|
||||
/**
|
||||
* @param {any} _
|
||||
* @param {any} match1
|
||||
* @param {any} match2
|
||||
*/ (_, match1, match2) => {
|
||||
const map_url = tag_name === 'script' ? match1 || match2 : match1;
|
||||
const map_data = (map_url.match(regex_data_uri) || [])[1];
|
||||
if (map_data) {
|
||||
// sourceMappingURL is data URL
|
||||
if (processed.map) {
|
||||
log_warning(
|
||||
'Not implemented. ' +
|
||||
'Found sourcemap in both processed.code and processed.map. ' +
|
||||
'Please update your preprocessor to return only one sourcemap.'
|
||||
);
|
||||
// ignore attached sourcemap
|
||||
return '';
|
||||
}
|
||||
processed.map = b64dec(map_data); // use attached sourcemap
|
||||
return ''; // remove from processed.code
|
||||
}
|
||||
// sourceMappingURL is path or URL
|
||||
if (!processed.map) {
|
||||
log_warning(
|
||||
`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
|
||||
return ''; // remove from processed.code
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* line: number;
|
||||
* column: number;
|
||||
* }} SourceLocation
|
||||
*/
|
@ -1,44 +0,0 @@
|
||||
import * as assert from 'node:assert';
|
||||
|
||||
const get_line_column = (obj) => ({ line: obj.line, column: obj.column });
|
||||
|
||||
export function test({ input, css, js }) {
|
||||
let out_obj, loc_output, actual, loc_input, expected;
|
||||
|
||||
out_obj = js;
|
||||
// we need the second occurrence of 'done_replace_script_2' in output.js
|
||||
// the first occurrence is mapped back to markup '{done_replace_script_2}'
|
||||
loc_output = out_obj.locate_1('done_replace_script_2');
|
||||
loc_output = out_obj.locate_1('done_replace_script_2', loc_output.character + 1);
|
||||
actual = out_obj.mapConsumer.originalPositionFor(loc_output);
|
||||
loc_input = input.locate_1('replace_me_script');
|
||||
expected = {
|
||||
source: 'input.svelte',
|
||||
name: 'replace_me_script',
|
||||
...get_line_column(loc_input)
|
||||
};
|
||||
assert.deepEqual(actual, expected);
|
||||
|
||||
out_obj = css;
|
||||
loc_output = out_obj.locate_1('.done_replace_style_2');
|
||||
actual = out_obj.mapConsumer.originalPositionFor(loc_output);
|
||||
loc_input = input.locate_1('.replace_me_style');
|
||||
expected = {
|
||||
source: 'input.svelte',
|
||||
name: '.replace_me_style',
|
||||
...get_line_column(loc_input)
|
||||
};
|
||||
assert.deepEqual(actual, expected);
|
||||
|
||||
assert.equal(
|
||||
js.code.indexOf('\n/*# sourceMappingURL=data:application/json;base64,'),
|
||||
-1,
|
||||
'magic-comment attachments were NOT removed'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
css.code.indexOf('\n/*# sourceMappingURL=data:application/json;base64,'),
|
||||
-1,
|
||||
'magic-comment attachments were NOT removed'
|
||||
);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true
|
||||
client: ['foo.bar.baz'],
|
||||
server: ['foo.bar.baz']
|
||||
});
|
||||
|
@ -1,34 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('foo.bar.baz');
|
||||
|
||||
let start;
|
||||
let actual;
|
||||
|
||||
start = js.locate('ctx[0].bar.baz');
|
||||
|
||||
actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
|
||||
start = js.locate('ctx[0].bar.baz', start.character + 1);
|
||||
|
||||
actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,3 +1,10 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({ skip: true });
|
||||
export default test({
|
||||
skip: true, // No source map for binding in template because there's no loc property for it; skipped in Svelte 4, too
|
||||
client: [
|
||||
'potato',
|
||||
{ str: 'potato', idxOriginal: 1, idxGenerated: 3 },
|
||||
{ str: 'potato', idxOriginal: 1, idxGenerated: 5 }
|
||||
]
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import Widget from 'wherever';
|
||||
|
||||
export let potato;
|
||||
</script>
|
||||
|
||||
{potato}
|
||||
<Widget bind:potato/>
|
||||
|
@ -1,22 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('potato');
|
||||
|
||||
let start;
|
||||
|
||||
start = js.locate('potato');
|
||||
start = js.locate('potato', start.character + 1);
|
||||
start = js.locate('potato', start.character + 1);
|
||||
// we need the third instance of 'potato'
|
||||
|
||||
const actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
client: ['bar.baz'],
|
||||
server: ['bar.baz']
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('bar.baz');
|
||||
|
||||
let start;
|
||||
let actual;
|
||||
|
||||
start = js.locate('bar.baz');
|
||||
|
||||
actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
|
||||
start = js.locate('bar.baz', start.character + 1);
|
||||
|
||||
actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
import MagicString from 'magic-string';
|
||||
import { test } from '../../test';
|
||||
import { magic_string_preprocessor_result, magic_string_replace_all } from '../../helpers.js';
|
||||
|
||||
export default test({
|
||||
skip: true,
|
||||
compileOptions: {
|
||||
dev: true
|
||||
},
|
||||
preprocess: [
|
||||
{
|
||||
style: ({ content, filename = '' }) => {
|
||||
const src = new MagicString(content);
|
||||
magic_string_replace_all(src, '--replace-me-once', '\n --done-replace-once');
|
||||
magic_string_replace_all(src, '--replace-me-twice', '\n--almost-done-replace-twice');
|
||||
return magic_string_preprocessor_result(filename, src);
|
||||
}
|
||||
},
|
||||
{
|
||||
style: ({ content, filename = '' }) => {
|
||||
const src = new MagicString(content);
|
||||
magic_string_replace_all(src, '--almost-done-replace-twice', '\n --done-replace-twice');
|
||||
return magic_string_preprocessor_result(filename, src);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
@ -1,40 +0,0 @@
|
||||
import { SourceMapConsumer } from 'source-map';
|
||||
|
||||
const b64dec = (s) => Buffer.from(s, 'base64').toString();
|
||||
|
||||
export async function test({ assert, css, js }) {
|
||||
// We check that the css source map embedded in the js is accurate
|
||||
const match = js.code.match(
|
||||
/\tappend_styles\(target, "svelte-.{6}", "(.*?)(?:\\n\/\*# sourceMappingURL=data:(.*?);charset=(.*?);base64,(.*?) \*\/)?"\);\n/
|
||||
);
|
||||
|
||||
assert.notEqual(match, null);
|
||||
|
||||
const [mime_type, encoding, css_map_base64] = match.slice(2);
|
||||
assert.equal(mime_type, 'application/json');
|
||||
assert.equal(encoding, 'utf-8');
|
||||
|
||||
const css_map_json = b64dec(css_map_base64);
|
||||
css.mapConsumer = await new SourceMapConsumer(css_map_json);
|
||||
|
||||
// TODO make util fn + move to test index.js
|
||||
const sourcefile = 'input.svelte';
|
||||
[
|
||||
// TODO: get line and col num from input.svelte rather than hardcoding here
|
||||
[css, '--keep-me', 13, 2],
|
||||
[css, '--keep-me', null, 13, 2],
|
||||
[css, '--done-replace-once', '--replace-me-once', 7, 2],
|
||||
[css, '--done-replace-twice', '--replace-me-twice', 10, 2]
|
||||
].forEach(([where, content, name, line, column]) => {
|
||||
assert.deepEqual(
|
||||
where.mapConsumer.originalPositionFor(where.locate_1(content)),
|
||||
{
|
||||
source: sourcefile,
|
||||
name,
|
||||
line,
|
||||
column
|
||||
},
|
||||
`failed to locate "${content}" from "${sourcefile}"`
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
import MagicString from 'magic-string';
|
||||
import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping';
|
||||
import { test } from '../../test';
|
||||
import { magic_string_preprocessor_result, magic_string_replace_all } from '../../helpers.js';
|
||||
import { getLocator } from 'locate-character';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true,
|
||||
css: 'injected'
|
||||
},
|
||||
preprocess: [
|
||||
{
|
||||
style: ({ content, filename = '' }) => {
|
||||
const src = new MagicString(content);
|
||||
magic_string_replace_all(src, '--replace-me-once', '\n --done-replace-once');
|
||||
magic_string_replace_all(src, '--replace-me-twice', '\n--almost-done-replace-twice');
|
||||
return magic_string_preprocessor_result(filename, src);
|
||||
}
|
||||
},
|
||||
{
|
||||
style: ({ content, filename = '' }) => {
|
||||
const src = new MagicString(content);
|
||||
magic_string_replace_all(src, '--almost-done-replace-twice', '\n --done-replace-twice');
|
||||
return magic_string_preprocessor_result(filename, src);
|
||||
}
|
||||
}
|
||||
],
|
||||
async test({ assert, code_client }) {
|
||||
// Check that the css source map embedded in the js is accurate
|
||||
const match = code_client.match(
|
||||
/append_styles\(\$\$anchor, "svelte-.{6}", "(.*?)(?:\\n\/\*# sourceMappingURL=data:(.*?);charset=(.*?);base64,(.*?) \*\/)?"\);/
|
||||
);
|
||||
|
||||
assert.notEqual(match, null);
|
||||
|
||||
const [css, mime_type, encoding, css_map_base64] = /** @type {RegExpMatchArray} */ (
|
||||
match
|
||||
).slice(1);
|
||||
assert.equal(mime_type, 'application/json');
|
||||
assert.equal(encoding, 'utf-8');
|
||||
|
||||
const css_map_json = Buffer.from(css_map_base64, 'base64').toString();
|
||||
const map = new TraceMap(css_map_json);
|
||||
const sourcefile = '../../input.svelte';
|
||||
const locate = getLocator(
|
||||
css.replace(/\\r/g, '\r').replace(/\\n/g, '\n').replace(/\\t/g, '\t'),
|
||||
{ offsetLine: 1 }
|
||||
);
|
||||
|
||||
/** @type {const} */ ([
|
||||
['--keep-me: blue', null, 13, 2],
|
||||
['--done-replace-once: red', '--replace-me-once', 7, 2],
|
||||
['--done-replace-twice: green', '--replace-me-twice', 10, 2]
|
||||
]).forEach(([content, name, line, column]) => {
|
||||
assert.deepEqual(
|
||||
originalPositionFor(
|
||||
map,
|
||||
/** @type {import('locate-character').Location_1} */ (locate(content))
|
||||
),
|
||||
{
|
||||
source: sourcefile,
|
||||
name,
|
||||
line,
|
||||
column
|
||||
},
|
||||
`failed to locate "${content}" from "${sourcefile}"`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true
|
||||
css: [{ str: '.foo', strGenerated: '.foo.svelte-sg04hs' }]
|
||||
});
|
||||
|
@ -1,17 +0,0 @@
|
||||
export function test({ assert, input, css }) {
|
||||
const expected = input.locate('.foo');
|
||||
|
||||
const start = css.locate('.foo');
|
||||
|
||||
const actual = css.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
export function test({ assert, input, preprocessed }) {
|
||||
const expected = input.locate('replace me');
|
||||
|
||||
const start = preprocessed.locate('success');
|
||||
|
||||
const actualbar = preprocessed.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actualbar, {
|
||||
source: 'input.svelte',
|
||||
name: 'replace me',
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true
|
||||
client: ['foo', 'bar', { str: 'bar', idxGenerated: 1, idxOriginal: 1 }]
|
||||
});
|
||||
|
@ -1,18 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const start_index = js.code.indexOf('create_main_fragment');
|
||||
|
||||
const expected = input.locate('each');
|
||||
const start = js.locate('length', start_index);
|
||||
|
||||
const actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import { assert_mapped } from '../../helpers.js';
|
||||
import { COMMON, STYLES } from './_config';
|
||||
|
||||
export function test({ input, preprocessed }) {
|
||||
// Transformed script, main file
|
||||
assert_mapped({
|
||||
filename: 'input.svelte',
|
||||
code: 'Divs ftw!',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// External files
|
||||
assert_mapped({
|
||||
filename: 'common.scss',
|
||||
code: 'height: 100%;',
|
||||
input: COMMON,
|
||||
preprocessed
|
||||
});
|
||||
assert_mapped({
|
||||
filename: 'styles.scss',
|
||||
code: 'color: orange;',
|
||||
input: STYLES,
|
||||
preprocessed
|
||||
});
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true
|
||||
skip: true, // TODO no source maps here; Svelte 4 added some for static templates due to https://github.com/sveltejs/svelte/issues/6092
|
||||
client: []
|
||||
});
|
||||
|
@ -1,9 +0,0 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true,
|
||||
compileOptions: {
|
||||
// @ts-expect-error
|
||||
enableSourcemap: false
|
||||
}
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
<p>{foo}</p>
|
||||
|
||||
<style>
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
@ -1,4 +0,0 @@
|
||||
export function test({ assert, js, css }) {
|
||||
assert.equal(js.map, null);
|
||||
assert.equal(css.map, null);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true,
|
||||
compileOptions: {
|
||||
// @ts-expect-error
|
||||
enableSourcemap: { css: true }
|
||||
}
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
<p>{foo}</p>
|
||||
|
||||
<style>
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
@ -1,4 +0,0 @@
|
||||
export function test({ assert, js, css }) {
|
||||
assert.equal(js.map, null);
|
||||
assert.notEqual(css.map, null);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true,
|
||||
compileOptions: {
|
||||
// @ts-expect-error
|
||||
enableSourcemap: { js: true }
|
||||
}
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
<p>{foo}</p>
|
||||
|
||||
<style>
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
@ -1,4 +0,0 @@
|
||||
export function test({ assert, js, css }) {
|
||||
assert.notEqual(js.map, null);
|
||||
assert.equal(css.map, null);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected_bar = input.locate('baritone.baz');
|
||||
const expected_baz = input.locate('.baz');
|
||||
|
||||
let start = js.locate('bar.baz');
|
||||
|
||||
const actualbar = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actualbar, {
|
||||
source: 'input.svelte',
|
||||
name: 'baritone',
|
||||
line: expected_bar.line + 1,
|
||||
column: expected_bar.column
|
||||
});
|
||||
|
||||
start = js.locate('.baz');
|
||||
|
||||
const actualbaz = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actualbaz, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected_baz.line + 1,
|
||||
column: expected_baz.column
|
||||
});
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
export function test({ assert, input, js, css }) {
|
||||
const expected_bar = input.locate('baritone');
|
||||
const expected_baz = input.locate('--bazitone');
|
||||
|
||||
let start = js.locate('bar');
|
||||
|
||||
const actualbar = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actualbar, {
|
||||
source: 'input.svelte',
|
||||
name: 'baritone',
|
||||
line: expected_bar.line + 1,
|
||||
column: expected_bar.column
|
||||
});
|
||||
|
||||
start = css.locate('--baz');
|
||||
|
||||
const actualbaz = css.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actualbaz, {
|
||||
source: 'input.svelte',
|
||||
name: '--bazitone',
|
||||
line: expected_baz.line + 1,
|
||||
column: expected_baz.column
|
||||
});
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import { assert_mapped, assert_not_mapped } from '../../helpers.js';
|
||||
|
||||
export function test({ input, preprocessed }) {
|
||||
// markup (start)
|
||||
assert_mapped({
|
||||
code: '<script>',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// script content (preprocessed without map, content not changed)
|
||||
assert_mapped({
|
||||
code: 'console.log(name);',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// markup (middle)
|
||||
assert_mapped({
|
||||
code: '<div>{name}</div>',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// style content (preprocessed without map, content changed)
|
||||
assert_not_mapped({
|
||||
code: 'font-weight: bold;',
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// markup (end)
|
||||
assert_mapped({
|
||||
code: '</style>',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected_bar = input.locate('baritone:');
|
||||
const expected_baz = input.locate('baz:');
|
||||
|
||||
let start = js.locate('bar:');
|
||||
|
||||
const actualbar = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
actualbar,
|
||||
{
|
||||
source: 'input.svelte',
|
||||
name: 'baritone',
|
||||
line: expected_bar.line + 1,
|
||||
column: expected_bar.column
|
||||
},
|
||||
"couldn't find bar: in source"
|
||||
);
|
||||
|
||||
start = js.locate('baz:');
|
||||
|
||||
const actualbaz = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
actualbaz,
|
||||
{
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected_baz.line + 1,
|
||||
column: expected_baz.column
|
||||
},
|
||||
"couldn't find baz: in source"
|
||||
);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
export function test({ assert, input, css }) {
|
||||
const expected_bar = input.locate('--baritone');
|
||||
const expected_baz = input.locate('--baz');
|
||||
|
||||
let start = css.locate('--bar');
|
||||
|
||||
const actualbar = css.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
actualbar,
|
||||
{
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected_bar.line + 1,
|
||||
column: expected_bar.column
|
||||
},
|
||||
"couldn't find bar in source"
|
||||
);
|
||||
|
||||
start = css.locate('--baz');
|
||||
|
||||
const actualbaz = css.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
actualbaz,
|
||||
{
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected_baz.line + 1,
|
||||
column: expected_baz.column
|
||||
},
|
||||
"couldn't find baz in source"
|
||||
);
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({ client: ['assertThisLine'] });
|
@ -1,16 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('assertThisLine');
|
||||
const start = js.locate('assertThisLine');
|
||||
|
||||
const actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
client: ['42']
|
||||
});
|
@ -1,16 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('42');
|
||||
const start = js.locate('42');
|
||||
|
||||
const actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import { component_filepath, component_file_basename, external_relative_filename } from './_config';
|
||||
|
||||
export function test({ assert, preprocessed }) {
|
||||
assert.notEqual(
|
||||
preprocessed.locate(`/* Filename from preprocess: ${component_filepath} */`),
|
||||
undefined,
|
||||
'Preprocessor should receive same value for filename as passed to preprocess function'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
preprocessed.map.sources.slice().sort(),
|
||||
[external_relative_filename, component_file_basename].sort(),
|
||||
'Preprocessed map should contain sources relative to filepath'
|
||||
);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { assert_mapped } from '../../helpers.js';
|
||||
|
||||
export function test({ input, preprocessed }) {
|
||||
assert_mapped({
|
||||
code: 'Target',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
}
|
@ -1,20 +1,19 @@
|
||||
import { test } from '../../test';
|
||||
import { magic_string_bundle } from '../../helpers.js';
|
||||
|
||||
export const EXTERNAL = 'span { --external-var: 1px; }';
|
||||
const EXTERNAL = 'span { --external-var: 1px; }';
|
||||
|
||||
export default test({
|
||||
skip: true,
|
||||
js_map_sources: ['input.svelte'],
|
||||
css_map_sources: ['input.svelte', 'external.css'],
|
||||
preprocess: [
|
||||
{
|
||||
style: ({ content, filename = '' }) => {
|
||||
style: ({ content }) => {
|
||||
return magic_string_bundle([
|
||||
{ code: EXTERNAL, filename: 'external.css' },
|
||||
{ code: content, filename }
|
||||
{ code: content, filename: 'input.svelte' }
|
||||
]);
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
preprocessed: [{ str: '--component-var: 2px' }, { code: EXTERNAL, str: '--external-var: 1px' }]
|
||||
});
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { assert_mapped } from '../../helpers.js';
|
||||
import { EXTERNAL } from './_config';
|
||||
|
||||
export function test({ input, preprocessed }) {
|
||||
// Part from component, should be with offset
|
||||
assert_mapped({
|
||||
code: '--component-var',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// Part from external file, should be without offset
|
||||
assert_mapped({
|
||||
filename: 'external.css',
|
||||
code: '--external-var',
|
||||
input: EXTERNAL,
|
||||
preprocessed
|
||||
});
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<script>
|
||||
export let name;
|
||||
</script>
|
||||
<h1>sourcemap-sources</h1>
|
||||
<h1>sourcemap-sources {name}</h1>
|
||||
|
@ -1,23 +0,0 @@
|
||||
export function test({ assert, preprocessed, js }) {
|
||||
assert.equal(preprocessed.error, undefined);
|
||||
|
||||
// sourcemap stores location only for 'answer = 42;'
|
||||
// not for 'var answer = 42;'
|
||||
[
|
||||
[js, 'foo.js', 'answer = 42;', 4],
|
||||
[js, 'bar.js', 'console.log(answer);', 0],
|
||||
[js, 'foo2.js', 'answer2 = 84;', 4],
|
||||
[js, 'bar2.js', 'console.log(answer2);', 0]
|
||||
].forEach(([where, sourcefile, content, column]) => {
|
||||
assert.deepEqual(
|
||||
where.mapConsumer.originalPositionFor(where.locate_1(content)),
|
||||
{
|
||||
source: sourcefile,
|
||||
name: null,
|
||||
line: 1,
|
||||
column
|
||||
},
|
||||
`failed to locate "${content}" from "${sourcefile}"`
|
||||
);
|
||||
});
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true
|
||||
test({ assert, map_client }) {
|
||||
assert.deepEqual(map_client.sources, ['../../input.svelte']);
|
||||
// TODO do we need to set sourcesContent? We did it in Svelte 4, but why?
|
||||
// assert.deepEqual(js.map.sourcesContent, [
|
||||
// fs.readFileSync(path.join(__dirname, 'input.svelte'), 'utf-8')
|
||||
// ]);
|
||||
}
|
||||
});
|
||||
|
@ -1,9 +0,0 @@
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
|
||||
export function test({ assert, js }) {
|
||||
assert.deepEqual(js.map.sources, ['input.svelte']);
|
||||
assert.deepEqual(js.map.sourcesContent, [
|
||||
fs.readFileSync(path.join(__dirname, 'input.svelte'), 'utf-8')
|
||||
]);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
client: ['first', 'assertThisLine']
|
||||
});
|
@ -1,16 +0,0 @@
|
||||
export function test({ assert, input, js }) {
|
||||
const expected = input.locate('assertThisLine');
|
||||
const start = js.locate('assertThisLine');
|
||||
|
||||
const actual = js.mapConsumer.originalPositionFor({
|
||||
line: start.line + 1,
|
||||
column: start.column
|
||||
});
|
||||
|
||||
assert.deepEqual(actual, {
|
||||
source: 'input.svelte',
|
||||
name: null,
|
||||
line: expected.line + 1,
|
||||
column: expected.column
|
||||
});
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import { assert_mapped, assert_not_located } from '../../helpers.js';
|
||||
|
||||
export function test({ input, preprocessed }) {
|
||||
// TS => JS code
|
||||
assert_mapped({
|
||||
code: 'let count = 0;',
|
||||
input_code: 'let count: number = 0;',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// Markup, not touched
|
||||
assert_mapped({
|
||||
code: '<h1>Hello world!</h1>',
|
||||
input: input.locate,
|
||||
preprocessed
|
||||
});
|
||||
|
||||
// TS types, removed
|
||||
assert_not_located('ITimeoutDestroyer', preprocessed.locate_1);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue