Skip to content

Commit

Permalink
Add option to control unknown global side effects
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Aug 28, 2019
1 parent 4ed5632 commit c505f11
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 4 deletions.
25 changes: 24 additions & 1 deletion docs/999-big-list-of-options.md
Expand Up @@ -802,7 +802,7 @@ Default: `false`
If this option is provided, bundling will not fail if bindings are imported from a file that does not define these bindings. Instead, new variables will be created for these bindings with the value `undefined`.

#### treeshake
Type: `boolean | { annotations?: boolean, moduleSideEffects?: ModuleSideEffectsOption, propertyReadSideEffects?: boolean }`<br>
Type: `boolean | { annotations?: boolean, moduleSideEffects?: ModuleSideEffectsOption, propertyReadSideEffects?: boolean, tryCatchDeoptimization?: boolean, unknownGlobalSideEffects?: boolean }`<br>
CLI: `--treeshake`/`--no-treeshake`<br>
Default: `true`

Expand Down Expand Up @@ -938,6 +938,29 @@ test(otherFn);

```

**treeshake.unknownGlobalSideEffects**
Type: `boolean`<br>
CLI: `--treeshake.unknownGlobalSideEffects`/`--no-treeshake.unknownGlobalSideEffects`<br>
Default: `true`

Since accessing a non-existing global variable will throw an error, Rollup does by default retain any accesses to non-builtin global variables. Set this option to `false` to avoid this check.

```js
// input
const jQuery = $;
const requestTimeout = setTimeout;
const element = angular.element;

// output with unknownGlobalSideEffects == true
const jQuery = $;
const element = angular.element;

// output with unknownGlobalSideEffects == false
const element = angular.element;
```

In the example, the last line is always retained as accessing the `element` property could also throw an error if angular is e.g. `null`. To avoid this check, set `treeshake.propertyReadSideEffects` to `false` as well.

### Experimental options

These options reflect new features that have not yet been fully finalized. Availability, behaviour and usage may therefore be subject to change between minor versions.
Expand Down
7 changes: 5 additions & 2 deletions src/Graph.ts
Expand Up @@ -116,13 +116,16 @@ export default class Graph {
(options.treeshake as TreeshakingOptions).propertyReadSideEffects !== false,
pureExternalModules: (options.treeshake as TreeshakingOptions).pureExternalModules,
tryCatchDeoptimization:
(options.treeshake as TreeshakingOptions).tryCatchDeoptimization !== false
(options.treeshake as TreeshakingOptions).tryCatchDeoptimization !== false,
unknownGlobalSideEffects:
(options.treeshake as TreeshakingOptions).unknownGlobalSideEffects !== false
}
: {
annotations: true,
moduleSideEffects: true,
propertyReadSideEffects: true,
tryCatchDeoptimization: true
tryCatchDeoptimization: true,
unknownGlobalSideEffects: true
};
if (typeof this.treeshakingOptions.pureExternalModules !== 'undefined') {
this.warnDeprecation(
Expand Down
3 changes: 3 additions & 0 deletions src/Module.ts
Expand Up @@ -110,6 +110,7 @@ export interface AstContext {
traceVariable: (name: string) => Variable | null;
treeshake: boolean;
tryCatchDeoptimization: boolean;
unknownGlobalSideEffects: boolean;
usesTopLevelAwait: boolean;
warn: (warning: RollupWarning, pos: number) => void;
warnDeprecation: (deprecation: string | RollupWarning, activeDeprecation: boolean) => void;
Expand Down Expand Up @@ -605,6 +606,8 @@ export default class Module {
treeshake: !!this.graph.treeshakingOptions,
tryCatchDeoptimization: (!this.graph.treeshakingOptions ||
this.graph.treeshakingOptions.tryCatchDeoptimization) as boolean,
unknownGlobalSideEffects: (!this.graph.treeshakingOptions ||
this.graph.treeshakingOptions.unknownGlobalSideEffects) as boolean,
usesTopLevelAwait: false,
warn: this.warn.bind(this),
warnDeprecation: this.graph.warnDeprecation.bind(this.graph)
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/Identifier.ts
Expand Up @@ -102,8 +102,8 @@ export default class Identifier extends NodeBase implements PatternNode {
}

hasEffects(): boolean {
// TODO Lukas observe the option here
return (
this.context.unknownGlobalSideEffects &&
this.variable instanceof GlobalVariable &&
this.variable.hasEffectsWhenAccessedAtPath(EMPTY_PATH)
);
Expand Down
1 change: 1 addition & 0 deletions src/rollup/types.d.ts
Expand Up @@ -385,6 +385,7 @@ export interface TreeshakingOptions {
/** @deprecated Use `moduleSideEffects` instead */
pureExternalModules?: PureModulesOption;
tryCatchDeoptimization?: boolean;
unknownGlobalSideEffects?: boolean;
}

export type GetManualChunk = (id: string) => string | null | undefined;
Expand Down
10 changes: 10 additions & 0 deletions test/form/samples/ignore-unknown-global-side-effects/_config.js
@@ -0,0 +1,10 @@
module.exports = {
description:
'ignore side-effects when accessing unknown globals if treeshake.unknownGlobalSideEffects is false',
expectedWarnings: ['EMPTY_BUNDLE'],
options: {
treeshake: {
unknownGlobalSideEffects: false
}
}
};
@@ -0,0 +1 @@

2 changes: 2 additions & 0 deletions test/form/samples/ignore-unknown-global-side-effects/main.js
@@ -0,0 +1,2 @@
foo;
class bar extends baz {}

0 comments on commit c505f11

Please sign in to comment.