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

fix(strip): support specifying both functions and labels #471

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 43 additions & 14 deletions packages/strip/README.md
Expand Up @@ -36,59 +36,88 @@ export default {
dir: 'output',
format: 'cjs'
},
plugins: [
strip({
labels: ['unittest']
})
]
plugins: [strip({})]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

};
```

Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).

### Default Options
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this section. the defaults are spelled out in the options below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because I wished it had been here when I started trying to use this plugin, but ok.


By default the **strip** plugin applies the following options, you can override by specifing options manually.

> consider files matching **'\*\*/\*.js'**
> remove functions matching '**console.\***' and '**assert.\***'
> remove any **debugger** statements

### Custom Options Example
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this section. you've added examples in the options below and that's sufficient

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


```js
plugins: [
strip({
include: '**/*.(mjs|js)',
exclude: 'tests/**/*',
debugger: true,
functions: ['console.log', 'assert.*'],
labels: ['unittest'],
sourceMap: true
})
];
```

## Options

### `include`

Type: `String | RegExp | Array[...String|RegExp]`<br>
Default: `['**/*.js']`
Default: `['**/*.js']`<br>
Example: `include: '**/*.(mjs|js)',`<br>

A pattern, or array of patterns, which specify the files in the build the plugin should operate on.

### `exclude`

Type: `String | RegExp | Array[...String|RegExp]`<br>
Default: `[]`
Default: `[]`<br>
Example: `exlude: 'tests/**/*',`<br>

A pattern, or array of patterns, which specify the files in the build the plugin should _ignore_.

### `debugger`

Type: `Boolean`<br>
Default: `true`
Default: `true`<br>
Example: `debugger: false,`<br>

If `true`, instructs the plugin to remove debugger statements.
If `true` or unspecified, instructs the plugin to remove debugger statements.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or unspecified is not not necessary and doesn't add any value here, please revert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


### `functions`

Type: `Array[...String]`<br>
Default: `[ 'console.*', 'assert.*' ]`
Default: `[ 'console.*', 'assert.*' ]`<br>
Example: `functions: [ 'console.log', 'MyClass.Test' ],`<br>

Specifies the functions that the plugin will target and remove.

_Note: specifying functions that are used at the begining of a chain, such as 'a().b().c()', will result in '(void 0).b().c()' which will generate an error at runtime._

### `labels`

Type: `Array[...String]`<br>
Default: `[]`
Default: `[]`<br>
Example: `labels: ['unittest'],`<br>

Specifies the [labeled blocks or statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) that the plugin will target and remove.

Specifies the [labeled blocks](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) that the plugin will target and remove.
_Note: the '**:**' is implied and should not be specified in the config._

### `sourceMap`

Type: `Boolean`<br>
Default: `true`
Default: `true`<br>
Example: `sourceMap: false,`<br>

If `true`, instructs the plugin to update source maps accordingly after removing configured targets from the bundle.
If `true` or unspecified, instructs the plugin to update source maps accordingly after removing configured targets from the bundle.

## Meta

Expand Down
39 changes: 28 additions & 11 deletions packages/strip/src/index.js
Expand Up @@ -38,21 +38,34 @@ export default function strip(options = {}) {
const sourceMap = options.sourceMap !== false;

const removeDebuggerStatements = options.debugger !== false;
const functions = (options.functions || ['console.*', 'assert.*']).map((keypath) =>
shellscape marked this conversation as resolved.
Show resolved Hide resolved
keypath.replace(/\./g, '\\.').replace(/\*/g, '\\w+')
);

shellscape marked this conversation as resolved.
Show resolved Hide resolved
const functions = options.functions || ['console.*', 'assert.*'];
const labels = options.labels || [];

const firstpass = new RegExp(`\\b(?:${functions.join('|')}|debugger)\\b`);
const pattern = new RegExp(`^(?:${functions.join('|')})$`);
const functionsPatterns = functions.map((f) =>
f.replace(/\*/g, '\\w+').replace(/\./g, '\\.\\s*')
);
const labelsPatterns = labels.map((l) => `${l}\\s*:`);

const firstPassPatterns = removeDebuggerStatements
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this ternary and the following array assignment within is unnecessary.

const firstPass = [...functionsPatterns, ...labelsPatterns];
if (removeDebuggerStatements) {
  firstPass.push('debugger\\b');
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops, that would be my C++ background where const is deep. I'd forgotten in JS const is shallow and still allows the object to be mutated. Done.

? [...functionsPatterns, ...labelsPatterns, 'debugger\\b']
: [...functionsPatterns, ...labelsPatterns];

const functionsRE = new RegExp(`^(?:${functionsPatterns.join('|')})$`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while we're in here, please use the naming pattern reFunctions and reFirstpass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const firstpassRE = new RegExp(`\\b(?:${firstPassPatterns.join('|')})`);

const firstPassFilter =
firstPassPatterns.length > 0 ? (code) => firstpassRE.test(code) : () => false;

const UNCHANGED = null;

return {
name: 'strip',

transform(code, id) {
if (!filter(id)) return null;
if (functions.length > 0 && !firstpass.test(code)) return null;
if (!filter(id) || !firstPassFilter(code)) {
return UNCHANGED;
}

let ast;

Expand Down Expand Up @@ -81,7 +94,7 @@ export default function strip(options = {}) {
if (parent.type === 'ExpressionStatement') {
removeStatement(parent);
} else {
magicString.overwrite(node.start, node.end, 'void 0');
magicString.overwrite(node.start, node.end, '(void 0)');
}

edited = true;
Expand All @@ -93,7 +106,7 @@ export default function strip(options = {}) {
if (isBlock(parent)) {
remove(node.start, node.end);
} else {
magicString.overwrite(node.start, node.end, 'void 0;');
magicString.overwrite(node.start, node.end, '(void 0);');
}

edited = true;
Expand All @@ -114,21 +127,25 @@ export default function strip(options = {}) {

if (removeDebuggerStatements && node.type === 'DebuggerStatement') {
removeStatement(node);
this.skip();
} else if (node.type === 'LabeledStatement') {
if (node.label && labels.includes(node.label.name)) {
removeStatement(node);
this.skip();
}
} else if (node.type === 'CallExpression') {
const keypath = flatten(node.callee);
if (keypath && pattern.test(keypath)) {
if (keypath && functionsRE.test(keypath)) {
removeExpression(node);
this.skip();
}
}
}
});

if (!edited) return null;
if (!edited) {
return UNCHANGED;
}

code = magicString.toString();
const map = sourceMap ? magicString.generateMap() : null;
Expand Down
6 changes: 0 additions & 6 deletions packages/strip/test/fixtures/assert/input.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/strip/test/fixtures/console-custom/input.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/strip/test/fixtures/console/input.js

This file was deleted.

6 changes: 0 additions & 6 deletions packages/strip/test/fixtures/custom/input.js

This file was deleted.

5 changes: 0 additions & 5 deletions packages/strip/test/fixtures/debugger-false/input.js

This file was deleted.

5 changes: 0 additions & 5 deletions packages/strip/test/fixtures/debugger/input.js

This file was deleted.

3 changes: 0 additions & 3 deletions packages/strip/test/fixtures/if-block/input.js

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion packages/strip/test/fixtures/inline-if/input.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/strip/test/fixtures/inline-while/input.js

This file was deleted.

This file was deleted.

9 changes: 0 additions & 9 deletions packages/strip/test/fixtures/label-block-multiple/input.js

This file was deleted.

7 changes: 0 additions & 7 deletions packages/strip/test/fixtures/label-block/input.js

This file was deleted.

This file was deleted.

8 changes: 0 additions & 8 deletions packages/strip/test/fixtures/super-method/input.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/strip/test/fixtures/switch-case/input.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/strip/test/fixtures/this-method/input.js

This file was deleted.