Skip to content

Commit

Permalink
Use ES2015 features in generated code snippets (#4215)
Browse files Browse the repository at this point in the history
* Add generatedCode option stub

* Prepare improved SystemJS exports

* Introduce snippets to finalizers

* Add indent to snippets

* Use arrow functions in IIFE finalizer

* Ensure tests have a description

* Improve test cleanup

* Separate indent again as it became unpredictable and possibly wrong

* Replace functions in remaining wrappers

* Wrap SystemJS and AMD factories for better performance

* Do not use compact where it is not needed

* Always destructure render options

* Add object shorthand option

* Use object shorthand for namespaces

* Add option to not quote reserved names used as props

* Refactor SystemJS reexports for simpler setters

* Use arrow functions for import expressions

* Update getExportBlock

* Use snippets for interop helpers

* Further convert interop helpers

* Replace property access in export block

* Add more arrow functions

* Merge helper strings

* Preserve context for amd/cjs dynamic non-arrow requires

Resolves #3092

* Add presets

* Use common helper for invalid option errors

* Use property access for namespace generation

* Update dependencies

* Improve coverage

* Update documentation

* Use symbolic links to keep tests in sync

* Start introducing new blockBindings option

* Always use arrow functions for large IIFEs

* Use block bindings for SystemJS output

* Use block bindings in remaining places

* Replace varOrConst

* Get rid of remainint varOrConst usages

* Account for Node 16 error messages

* Deprecated preferConst

* Properly merge external namespaces

* Refine namespace merge

* Rename blockBindings -> constBindings

* Update docs

* Do not quote props for ES5

* Use more efficient loops for const bindings

* Refine loop formatting

* Merge directReturnFunction left and right

* Refine code formatting

* Update dependencies
  • Loading branch information
lukastaegert committed Sep 22, 2021
1 parent 5700728 commit ca86df2
Show file tree
Hide file tree
Showing 2,938 changed files with 18,451 additions and 12,497 deletions.
2 changes: 1 addition & 1 deletion cli/cli.ts
Expand Up @@ -16,7 +16,7 @@ if (command.help || (process.argv.length <= 2 && process.stdin.isTTY)) {
} else {
try {
require('source-map-support').install();
} catch (err) {
} catch {
// do nothing
}

Expand Down
6 changes: 3 additions & 3 deletions cli/run/commandPlugins.ts
Expand Up @@ -59,7 +59,7 @@ function loadAndRegisterPlugin(inputOptions: InputOptions, pluginText: string):
try {
plugin = require(prefix + pluginText);
break;
} catch (ex) {
} catch {
// if this does not work, we try requiring the actual name below
}
}
Expand All @@ -68,8 +68,8 @@ function loadAndRegisterPlugin(inputOptions: InputOptions, pluginText: string):
try {
if (pluginText[0] == '.') pluginText = path.resolve(pluginText);
plugin = require(pluginText);
} catch (ex) {
throw new Error(`Cannot load plugin "${pluginText}": ${ex.message}.`);
} catch (err: any) {
throw new Error(`Cannot load plugin "${pluginText}": ${err.message}.`);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions cli/run/getConfigPath.ts
Expand Up @@ -14,10 +14,10 @@ export function getConfigPath(commandConfig: string | true): string {
const pkgName = commandConfig.slice(5);
try {
return relative.resolve(`rollup-config-${pkgName}`, cwd);
} catch (err) {
} catch {
try {
return relative.resolve(pkgName, cwd);
} catch (err) {
} catch (err: any) {
if (err.code === 'MODULE_NOT_FOUND') {
handleError({
code: 'MISSING_EXTERNAL_CONFIG',
Expand Down
4 changes: 2 additions & 2 deletions cli/run/index.ts
Expand Up @@ -74,11 +74,11 @@ export default async function runRollup(command: Record<string, any>): Promise<v
message: 'Warnings occurred and --failAfterWarnings flag present'
});
}
} catch (err) {
} catch (err: any) {
warnings.flush();
handleError(err);
}
} catch (err) {
} catch (err: any) {
handleError(err);
}
}
Expand Down
2 changes: 1 addition & 1 deletion cli/run/loadConfigFile.ts
Expand Up @@ -117,7 +117,7 @@ async function loadConfigFromBundledFile(fileName: string, bundledCode: string)
const config = getDefaultFromCjs(require(fileName));
require.extensions[extension] = defaultLoader;
return config;
} catch (err) {
} catch (err: any) {
if (err.code === 'ERR_REQUIRE_ESM') {
return error({
code: 'TRANSPILED_ESM_CONFIG',
Expand Down
4 changes: 2 additions & 2 deletions cli/run/watch-cli.ts
Expand Up @@ -66,7 +66,7 @@ export async function watch(command: Record<string, any>): Promise<void> {
}
start(configs);
}
} catch (err) {
} catch (err: any) {
configs = [];
reloadingConfig = false;
handleError(err, true);
Expand All @@ -86,7 +86,7 @@ export async function watch(command: Record<string, any>): Promise<void> {
function start(configs: MergedRollupOptions[]) {
try {
watcher = rollup.watch(configs as any);
} catch (err) {
} catch (err: any) {
return handleError(err);
}

Expand Down
133 changes: 127 additions & 6 deletions docs/999-big-list-of-options.md
Expand Up @@ -458,6 +458,125 @@ Type: `boolean`<br> CLI: `--extend`/`--no-extend`<br> Default: `false`

Whether to extend the global variable defined by the `name` option in `umd` or `iife` formats. When `true`, the global variable will be defined as `(global.name = global.name || {})`. When false, the global defined by `name` will be overwritten like `(global.name = {})`.

#### output.generatedCode

Type: `"es5" | "es2015" | { arrowFunctions?: boolean, constBindings?: boolean, objectShorthand?: boolean, preset?: "es5" | "es2015", reservedNamesAsProps?: boolean }`<br> CLI: `--generatedCode <preset>`<br> Default: `"es5"`

Which language features Rollup can safely use in generated code. This will not transpile any user code but only change the code Rollup uses in wrappers and helpers. You may choose one of several presets:

- `"es5"`: Do not use ES2015+ features like arrow functions, but do not quote reserved names used as props.
- `"es2015"`: Use any JavaScript features up to ES2015.

**output.generatedCode.arrowFunctions**<br> Type: `boolean`<br> CLI: `--generatedCode.arrowFunctions`/`--no-generatedCode.arrowFunctions`<br> Default: `false`

Whether to use arrow functions for auto-generated code snippets. Note that in certain places like module wrappers, Rollup will keep using regular functions wrapped in parentheses as in some JavaScript engines, these will provide [noticeably better performance](https://v8.dev/blog/preparser#pife).

**output.generatedCode.constBindings**<br> Type: `boolean`<br> CLI: `--generatedCode.constBindings`/`--no-generatedCode.constBindings`<br> Default: `false`

This will use `const` instead of `var` in certain places and helper functions. This will allow Rollup to generate more efficient helpers due to block scoping.

```js
// input
export * from 'external';

// cjs output with constBindings: false
var external = require('external');

Object.keys(external).forEach(function (k) {
if (k !== 'default' && !exports.hasOwnProperty(k))
Object.defineProperty(exports, k, {
enumerable: true,
get: function () {
return external[k];
}
});
});

// cjs output with constBindings: true
const external = require('external');

for (const k in external) {
if (k !== 'default' && !exports.hasOwnProperty(k))
Object.defineProperty(exports, k, {
enumerable: true,
get: () => external[k]
});
}
```

**output.generatedCode.objectShorthand**<br> Type: `boolean`<br> CLI: `--generatedCode.objectShorthand`/`--no-generatedCode.objectShorthand`<br> Default: `false`

Allows the use of shorthand notation in objects when the property name matches the value.

```javascript
// input
const foo = 1;
export { foo, foo as bar };

// system output with objectShorthand: false
System.register('bundle', [], function (exports) {
'use strict';
return {
execute: function () {
const foo = 1;
exports({ foo: foo, bar: foo });
}
};
});

// system output with objectShorthand: true
System.register('bundle', [], function (exports) {
'use strict';
return {
execute: function () {
const foo = 1;
exports({ foo, bar: foo });
}
};
});
```

**output.generatedCode.preset**<br> Type: `"es5" | "es2015"`<br> CLI: `--generatedCode <value>`

Allows choosing one of the presets listed above while overriding some options.

```js
export default {
// ...
output: {
generatedCode: {
preset: 'es2015',
arrowFunctions: false
}
// ...
}
};
```

**output.generatedCode.reservedNamesAsProps**<br> Type: `boolean`<br> CLI: `--generatedCode.reservedNamesAsProps`/`--no-generatedCode.reservedNamesAsProps`<br> Default: `false`

Determine whether reserved words like "default" can be used as prop names without using quotes. This will make the syntax of the generated code ES3 compliant. Note however that for full ES3 compliance, you may also need to polyfill some builtin functions like `Object.keys` or `Array.prototype.forEach`.

```javascript
// input
const foo = null;
export { foo as void };

// cjs output with reservedNamesAsProps: false
Object.defineProperty(exports, '__esModule', { value: true });

const foo = null;

exports['void'] = foo;

// cjs output with reservedNamesAsProps: true
Object.defineProperty(exports, '__esModule', { value: true });

const foo = null;

exports.void = foo;
```

#### output.hoistTransitiveImports

Type: `boolean`<br> CLI: `--hoistTransitiveImports`/`--no-hoistTransitiveImports`<br> Default: `true`
Expand Down Expand Up @@ -1256,8 +1375,6 @@ Example:
export { x } from 'external';

// CJS output with externalLiveBindings: true
('use strict');

Object.defineProperty(exports, '__esModule', { value: true });

var external = require('external');
Expand All @@ -1270,8 +1387,6 @@ Object.defineProperty(exports, 'x', {
});

// CJS output with externalLiveBindings: false
('use strict');

Object.defineProperty(exports, '__esModule', { value: true });

var external = require('external');
Expand Down Expand Up @@ -1525,7 +1640,7 @@ Note that despite the name, this option does not "add" side effects to modules t

**treeshake.preset**<br> Type: `"smallest" | "safest" | "recommended"`<br> CLI: `--treeshake <value>`<br>

Allows choosing one of the presets listed above while overriding some of the options.
Allows choosing one of the presets listed above while overriding some options.

```js
export default {
Expand Down Expand Up @@ -1631,7 +1746,7 @@ Whether to collect performance timings. When used from the command line or a con

`getTimings()` returns an object of the following form:

```json
```
{
"# BUILD": [ 698.020877, 33979632, 45328080 ],
"## parse modules": [ 537.509342, 16295024, 27660296 ],
Expand Down Expand Up @@ -1743,6 +1858,12 @@ _Use the [`renderDynamicImport`](guide/en/#renderdynamicimport) plugin hook inst

This will rename the dynamic import function to the chosen name when outputting ES bundles. This is useful for generating code that uses a dynamic import polyfill such as [this one](https://github.com/uupaa/dynamic-import-polyfill).

#### output.preferConst

_Use the [`output.generatedCode.constBindings`](guide/en/#outputgeneratedcode) option instead._<br> Type: `boolean`<br> CLI: `--preferConst`/`--no-preferConst`<br> Default: `false`

Generate `const` declarations for exports rather than `var` declarations.

#### treeshake.pureExternalModules

_Use [`treeshake.moduleSideEffects: 'no-external'`](guide/en/#treeshake) instead._<br> Type: `boolean | string[] | (id: string) => boolean | null`<br> CLI: `--treeshake.pureExternalModules`/`--no-treeshake.pureExternalModules`<br> Default: `false`
Expand Down

0 comments on commit ca86df2

Please sign in to comment.