Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the ability to ignore-list sources #243

Merged
merged 2 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ You can pass an options argument:

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

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

// Sources can be marked as ignore-listed, which provides a hint to debuggers
// to not step into this code and also don't show the source files depending
// on user preferences.
bundle.addSource({
filename: 'some-3rdparty-library.js',
content: new MagicString('function myLib(){}'),
ignoreList: false // <--
})

// Advanced: a source can include an `indentExclusionRanges` property
// alongside `filename` and `content`. This will be passed to `s.indent()`
// - see documentation above
Expand Down
20 changes: 15 additions & 5 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,17 @@ export class SourceMap {

export class Bundle {
constructor(options?: BundleOptions);
addSource(source: MagicString | { filename?: string, content: MagicString }): Bundle;
/**
* Adds the specified source to the bundle, which can either be a `MagicString` object directly,
* or an options object that holds a magic string `content` property and optionally provides
* a `filename` for the source within the bundle, as well as an optional `ignoreList` hint
* (which defaults to `false`). The `filename` is used when constructing the source map for the
* bundle, to identify this `source` in the source map's `sources` field. The `ignoreList` hint
* is used to populate the `x_google_ignoreList` extension field in the source map, which is a
* mechanism for tools to signal to debuggers that certain sources should be ignored by default
* (depending on user preferences).
*/
addSource(source: MagicString | { filename?: string, content: MagicString, ignoreList?: boolean }): Bundle;
bmeurer marked this conversation as resolved.
Show resolved Hide resolved
append(str: string, options?: BundleOptions): Bundle;
clone(): Bundle;
generateMap(options?: SourceMapOptions): SourceMap;
Expand Down Expand Up @@ -117,7 +127,7 @@ export default class MagicString {
append(content: string): MagicString;
/**
* Appends the specified content at the index in the original string.
* If a range *ending* with index is subsequently moved, the insert will be moved with it.
* If a range *ending* with index is subsequently moved, the insert will be moved with it.
* See also `s.prependLeft(...)`.
*/
appendLeft(index: number, content: string): MagicString;
Expand Down Expand Up @@ -162,13 +172,13 @@ export default class MagicString {
*/
move(start: number, end: number, index: number): MagicString;
/**
* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
* that range. The same restrictions as `s.remove()` apply.
*
* The fourth argument is optional. It can have a storeName property — if true, the original name will be stored
* for later inclusion in a sourcemap's names array — and a contentOnly property which determines whether only
* the content is overwritten, or anything that was appended/prepended to the range as well.
*
*
* It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
*/
overwrite(start: number, end: number, content: string, options?: boolean | OverwriteOptions): MagicString;
Expand All @@ -181,7 +191,7 @@ export default class MagicString {
*/
update(start: number, end: number, content: string, options?: boolean | UpdateOptions): MagicString;
/**
* Prepends the string with the specified content.
* Prepends the string with the specified content.
*/
prepend(content: string): MagicString;
/**
Expand Down
11 changes: 10 additions & 1 deletion src/Bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class Bundle {
);
}

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

Expand Down Expand Up @@ -84,6 +84,7 @@ export default class Bundle {

generateDecodedMap(options = {}) {
const names = [];
let x_google_ignoreList = undefined;
this.sources.forEach((source) => {
Object.keys(source.content.storedNames).forEach((name) => {
if (!~names.indexOf(name)) names.push(name);
Expand Down Expand Up @@ -141,6 +142,13 @@ export default class Bundle {
if (magicString.outro) {
mappings.advance(magicString.outro);
}

if (source.ignoreList && sourceIndex !== -1) {
if (x_google_ignoreList === undefined) {
x_google_ignoreList = [];
}
x_google_ignoreList.push(sourceIndex);
}
});

return {
Expand All @@ -153,6 +161,7 @@ export default class Bundle {
}),
names,
mappings: mappings.raw,
x_google_ignoreList,
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/MagicString.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default class MagicString {
sourcemapLocations: { writable: true, value: new BitSet() },
storedNames: { writable: true, value: {} },
indentStr: { writable: true, value: undefined },
ignoreList: { writable: true, value: options.ignoreList },
});

if (DEBUG) {
Expand Down Expand Up @@ -168,6 +169,7 @@ export default class MagicString {
sourcesContent: options.includeContent ? [this.original] : undefined,
names,
mappings: mappings.raw,
x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined
};
}

Expand Down
38 changes: 38 additions & 0 deletions test/MagicString.Bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,32 @@ describe('MagicString.Bundle', () => {
assert.strictEqual(b.sources[0].indentExclusionRanges, array);
});

it('should accept ignore-list hint', () => {
const b = new MagicString.Bundle();
const foo = new MagicString('foo', {filename: 'foo.js'});
const bar = new MagicString('bar', {filename: 'bar.js'});

b.addSource({content: foo, ignoreList: true});
b.addSource({content: bar, ignoreList: false});
assert.strictEqual(b.sources[0].content, foo);
assert.strictEqual(b.sources[0].ignoreList, true);
assert.strictEqual(b.sources[1].content, bar);
assert.strictEqual(b.sources[1].ignoreList, false);
});

it('respects MagicString init options with { content: source }', () => {
const b = new MagicString.Bundle();
const array = [];
const source = new MagicString('abcdefghijkl', {
filename: 'foo.js',
ignoreList: false,
indentExclusionRanges: array
});

b.addSource({ content: source });
assert.strictEqual(b.sources[0].content, source);
assert.strictEqual(b.sources[0].filename, 'foo.js');
assert.strictEqual(b.sources[0].ignoreList, false);
assert.strictEqual(b.sources[0].indentExclusionRanges, array);
});
});
Expand Down Expand Up @@ -345,6 +360,29 @@ describe('MagicString.Bundle', () => {
assert.equal(loc.source, 'three.js');
});

it('should generate x_google_ignoreList correctly', () => {
const b = new MagicString.Bundle();

const one = new MagicString('function one () {}', { filename: 'one.js' });
const two = new MagicString('function two () {}', { filename: 'two.js' });
const three = new MagicString('function three () {}', { filename: 'three.js' });
const four = new MagicString('function four () {}', { filename: 'four.js' });

b.addSource({ content: one, ignoreList: false });
b.addSource({ content: two, ignoreList: true });
b.addSource({ content: three, ignoreList: true });
b.addSource({ content: four });

const map = b.generateMap({
file: 'output.js'
});

assert.deepEqual(map.x_google_ignoreList, [
map.sources.indexOf('two.js'),
map.sources.indexOf('three.js')
]);
});

it('handles prepended content', () => {
const b = new MagicString.Bundle();

Expand Down
16 changes: 16 additions & 0 deletions test/MagicString.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ describe('MagicString', () => {

assert.equal(s.filename, 'foo.js');
});

it('stores ignore-list hint', () => {
const s = new MagicString('abc', { ignoreList: true });

assert.equal(s.ignoreList, true);
});
});

describe('append', () => {
Expand Down Expand Up @@ -418,6 +424,16 @@ describe('MagicString', () => {
const map = s.generateMap();
assert.equal(map.mappings, 'IAAA');
});

it('generates x_google_ignoreList', () => {
const s = new MagicString('function foo(){}', {
ignoreList: true
});

const map = s.generateMap({ source: 'foo.js' });
assert.deepEqual(map.sources, ['foo.js']);
assert.deepEqual(map.x_google_ignoreList, [0]);
});
});

describe('getIndentString', () => {
Expand Down