Skip to content

Commit e238f04

Browse files
bmeurerantfu
andauthoredFeb 22, 2023
feat: add the ability to ignore-list sources (#243)
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
1 parent d4e9c31 commit e238f04

File tree

6 files changed

+94
-9
lines changed

6 files changed

+94
-9
lines changed
 

‎README.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,11 @@ You can pass an options argument:
6666

6767
```js
6868
const s = new MagicString(someCode, {
69-
// both these options will be used if you later
70-
// call `bundle.addSource( s )` - see below
69+
// these options will be used if you later call `bundle.addSource( s )` - see below
7170
filename: 'foo.js',
72-
indentExclusionRanges: [/*...*/]
71+
indentExclusionRanges: [/*...*/],
72+
// market source as ignore in DevTools, see below #Bundling
73+
ignoreList: false
7374
});
7475
```
7576

@@ -251,6 +252,15 @@ bundle.addSource({
251252
content: new MagicString('console.log( answer )')
252253
});
253254

255+
// Sources can be marked as ignore-listed, which provides a hint to debuggers
256+
// to not step into this code and also don't show the source files depending
257+
// on user preferences.
258+
bundle.addSource({
259+
filename: 'some-3rdparty-library.js',
260+
content: new MagicString('function myLib(){}'),
261+
ignoreList: false // <--
262+
})
263+
254264
// Advanced: a source can include an `indentExclusionRanges` property
255265
// alongside `filename` and `content`. This will be passed to `s.indent()`
256266
// - see documentation above

‎index.d.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,17 @@ export class SourceMap {
6565

6666
export class Bundle {
6767
constructor(options?: BundleOptions);
68-
addSource(source: MagicString | { filename?: string, content: MagicString }): Bundle;
68+
/**
69+
* Adds the specified source to the bundle, which can either be a `MagicString` object directly,
70+
* or an options object that holds a magic string `content` property and optionally provides
71+
* a `filename` for the source within the bundle, as well as an optional `ignoreList` hint
72+
* (which defaults to `false`). The `filename` is used when constructing the source map for the
73+
* bundle, to identify this `source` in the source map's `sources` field. The `ignoreList` hint
74+
* is used to populate the `x_google_ignoreList` extension field in the source map, which is a
75+
* mechanism for tools to signal to debuggers that certain sources should be ignored by default
76+
* (depending on user preferences).
77+
*/
78+
addSource(source: MagicString | { filename?: string, content: MagicString, ignoreList?: boolean }): Bundle;
6979
append(str: string, options?: BundleOptions): Bundle;
7080
clone(): Bundle;
7181
generateMap(options?: SourceMapOptions): SourceMap;
@@ -117,7 +127,7 @@ export default class MagicString {
117127
append(content: string): MagicString;
118128
/**
119129
* Appends the specified content at the index in the original string.
120-
* If a range *ending* with index is subsequently moved, the insert will be moved with it.
130+
* If a range *ending* with index is subsequently moved, the insert will be moved with it.
121131
* See also `s.prependLeft(...)`.
122132
*/
123133
appendLeft(index: number, content: string): MagicString;
@@ -162,13 +172,13 @@ export default class MagicString {
162172
*/
163173
move(start: number, end: number, index: number): MagicString;
164174
/**
165-
* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
175+
* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
166176
* that range. The same restrictions as `s.remove()` apply.
167177
*
168178
* The fourth argument is optional. It can have a storeName property — if true, the original name will be stored
169179
* for later inclusion in a sourcemap's names array — and a contentOnly property which determines whether only
170180
* the content is overwritten, or anything that was appended/prepended to the range as well.
171-
*
181+
*
172182
* It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
173183
*/
174184
overwrite(start: number, end: number, content: string, options?: boolean | OverwriteOptions): MagicString;
@@ -181,7 +191,7 @@ export default class MagicString {
181191
*/
182192
update(start: number, end: number, content: string, options?: boolean | UpdateOptions): MagicString;
183193
/**
184-
* Prepends the string with the specified content.
194+
* Prepends the string with the specified content.
185195
*/
186196
prepend(content: string): MagicString;
187197
/**

‎src/Bundle.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default class Bundle {
3131
);
3232
}
3333

34-
['filename', 'indentExclusionRanges', 'separator'].forEach((option) => {
34+
['filename', 'ignoreList', 'indentExclusionRanges', 'separator'].forEach((option) => {
3535
if (!hasOwnProp.call(source, option)) source[option] = source.content[option];
3636
});
3737

@@ -84,6 +84,7 @@ export default class Bundle {
8484

8585
generateDecodedMap(options = {}) {
8686
const names = [];
87+
let x_google_ignoreList = undefined;
8788
this.sources.forEach((source) => {
8889
Object.keys(source.content.storedNames).forEach((name) => {
8990
if (!~names.indexOf(name)) names.push(name);
@@ -141,6 +142,13 @@ export default class Bundle {
141142
if (magicString.outro) {
142143
mappings.advance(magicString.outro);
143144
}
145+
146+
if (source.ignoreList && sourceIndex !== -1) {
147+
if (x_google_ignoreList === undefined) {
148+
x_google_ignoreList = [];
149+
}
150+
x_google_ignoreList.push(sourceIndex);
151+
}
144152
});
145153

146154
return {
@@ -153,6 +161,7 @@ export default class Bundle {
153161
}),
154162
names,
155163
mappings: mappings.raw,
164+
x_google_ignoreList,
156165
};
157166
}
158167

‎src/MagicString.js

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default class MagicString {
3434
sourcemapLocations: { writable: true, value: new BitSet() },
3535
storedNames: { writable: true, value: {} },
3636
indentStr: { writable: true, value: undefined },
37+
ignoreList: { writable: true, value: options.ignoreList },
3738
});
3839

3940
if (DEBUG) {
@@ -168,6 +169,7 @@ export default class MagicString {
168169
sourcesContent: options.includeContent ? [this.original] : undefined,
169170
names,
170171
mappings: mappings.raw,
172+
x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined
171173
};
172174
}
173175

‎test/MagicString.Bundle.js

+38
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,32 @@ describe('MagicString.Bundle', () => {
2727
assert.strictEqual(b.sources[0].indentExclusionRanges, array);
2828
});
2929

30+
it('should accept ignore-list hint', () => {
31+
const b = new MagicString.Bundle();
32+
const foo = new MagicString('foo', {filename: 'foo.js'});
33+
const bar = new MagicString('bar', {filename: 'bar.js'});
34+
35+
b.addSource({content: foo, ignoreList: true});
36+
b.addSource({content: bar, ignoreList: false});
37+
assert.strictEqual(b.sources[0].content, foo);
38+
assert.strictEqual(b.sources[0].ignoreList, true);
39+
assert.strictEqual(b.sources[1].content, bar);
40+
assert.strictEqual(b.sources[1].ignoreList, false);
41+
});
42+
3043
it('respects MagicString init options with { content: source }', () => {
3144
const b = new MagicString.Bundle();
3245
const array = [];
3346
const source = new MagicString('abcdefghijkl', {
3447
filename: 'foo.js',
48+
ignoreList: false,
3549
indentExclusionRanges: array
3650
});
3751

3852
b.addSource({ content: source });
3953
assert.strictEqual(b.sources[0].content, source);
4054
assert.strictEqual(b.sources[0].filename, 'foo.js');
55+
assert.strictEqual(b.sources[0].ignoreList, false);
4156
assert.strictEqual(b.sources[0].indentExclusionRanges, array);
4257
});
4358
});
@@ -345,6 +360,29 @@ describe('MagicString.Bundle', () => {
345360
assert.equal(loc.source, 'three.js');
346361
});
347362

363+
it('should generate x_google_ignoreList correctly', () => {
364+
const b = new MagicString.Bundle();
365+
366+
const one = new MagicString('function one () {}', { filename: 'one.js' });
367+
const two = new MagicString('function two () {}', { filename: 'two.js' });
368+
const three = new MagicString('function three () {}', { filename: 'three.js' });
369+
const four = new MagicString('function four () {}', { filename: 'four.js' });
370+
371+
b.addSource({ content: one, ignoreList: false });
372+
b.addSource({ content: two, ignoreList: true });
373+
b.addSource({ content: three, ignoreList: true });
374+
b.addSource({ content: four });
375+
376+
const map = b.generateMap({
377+
file: 'output.js'
378+
});
379+
380+
assert.deepEqual(map.x_google_ignoreList, [
381+
map.sources.indexOf('two.js'),
382+
map.sources.indexOf('three.js')
383+
]);
384+
});
385+
348386
it('handles prepended content', () => {
349387
const b = new MagicString.Bundle();
350388

‎test/MagicString.js

+16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ describe('MagicString', () => {
1313

1414
assert.equal(s.filename, 'foo.js');
1515
});
16+
17+
it('stores ignore-list hint', () => {
18+
const s = new MagicString('abc', { ignoreList: true });
19+
20+
assert.equal(s.ignoreList, true);
21+
});
1622
});
1723

1824
describe('append', () => {
@@ -418,6 +424,16 @@ describe('MagicString', () => {
418424
const map = s.generateMap();
419425
assert.equal(map.mappings, 'IAAA');
420426
});
427+
428+
it('generates x_google_ignoreList', () => {
429+
const s = new MagicString('function foo(){}', {
430+
ignoreList: true
431+
});
432+
433+
const map = s.generateMap({ source: 'foo.js' });
434+
assert.deepEqual(map.sources, ['foo.js']);
435+
assert.deepEqual(map.x_google_ignoreList, [0]);
436+
});
421437
});
422438

423439
describe('getIndentString', () => {

0 commit comments

Comments
 (0)
Please sign in to comment.