diff --git a/packages/babel/README.md b/packages/babel/README.md
index 3b573fbec..5c004e70a 100644
--- a/packages/babel/README.md
+++ b/packages/babel/README.md
@@ -94,7 +94,7 @@ A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patt
### `filter`
-Type: (id: string) => boolean
+Type: (id: string, code: string) => boolean
Custom [filter function](https://github.com/rollup/plugins/tree/master/packages/pluginutils#createfilter) can be used to determine whether or not certain modules should be operated upon.
diff --git a/packages/babel/package.json b/packages/babel/package.json
index 45bdda3b7..aeda64e99 100644
--- a/packages/babel/package.json
+++ b/packages/babel/package.json
@@ -55,7 +55,7 @@
"peerDependencies": {
"@babel/core": "^7.0.0",
"@types/babel__core": "^7.1.9",
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ "rollup": "^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
diff --git a/packages/babel/src/index.js b/packages/babel/src/index.js
index 125e6305a..322f8ada0 100644
--- a/packages/babel/src/index.js
+++ b/packages/babel/src/index.js
@@ -5,7 +5,7 @@ import { BUNDLED, HELPERS } from './constants.js';
import bundledHelpersPlugin from './bundledHelpersPlugin.js';
import preflightCheck from './preflightCheck.js';
import transformCode from './transformCode.js';
-import { addBabelPlugin, escapeRegExpCharacters, warnOnce, stripQuery } from './utils.js';
+import { addBabelPlugin, escapeRegExpCharacters, warnOnce } from './utils.js';
const unpackOptions = ({
extensions = babel.DEFAULT_EXTENSIONS,
@@ -37,7 +37,7 @@ const warnAboutDeprecatedHelpersOption = ({ deprecatedOption, suggestion }) => {
);
};
-const unpackInputPluginOptions = ({ skipPreflightCheck = false, ...rest }, rollupVersion) => {
+const unpackInputPluginOptions = ({ skipPreflightCheck = false, ...rest }) => {
if ('runtimeHelpers' in rest) {
warnAboutDeprecatedHelpersOption({
deprecatedOption: 'runtimeHelpers',
@@ -63,8 +63,7 @@ const unpackInputPluginOptions = ({ skipPreflightCheck = false, ...rest }, rollu
supportsStaticESM: true,
supportsDynamicImport: true,
supportsTopLevelAwait: true,
- // todo: remove version checks for 1.20 - 1.25 when we bump peer deps
- supportsExportNamespaceFrom: !rollupVersion.match(/^1\.2[0-5]\./),
+ supportsExportNamespaceFrom: true,
...rest.caller
}
});
@@ -110,77 +109,76 @@ function createBabelInputPluginFactory(customCallback = returnObject) {
overrides
);
- let babelHelpers;
- let babelOptions;
- let filter;
- let skipPreflightCheck;
- return {
- name: 'babel',
-
- options() {
- // todo: remove options hook and hoist declarations when version checks are removed
- let exclude;
- let include;
- let extensions;
- let customFilter;
-
- ({
- exclude,
- extensions,
- babelHelpers,
- include,
- filter: customFilter,
- skipPreflightCheck,
- ...babelOptions
- } = unpackInputPluginOptions(pluginOptionsWithOverrides, this.meta.rollupVersion));
+ const {
+ exclude,
+ extensions,
+ babelHelpers,
+ include,
+ filter: customFilter,
+ skipPreflightCheck,
+ ...babelOptions
+ } = unpackInputPluginOptions(pluginOptionsWithOverrides);
+
+ const extensionRegExp = new RegExp(
+ `(${extensions.map(escapeRegExpCharacters).join('|')})(\\?.*)?(#.*)?$`
+ );
+ if (customFilter && (include || exclude)) {
+ throw new Error('Could not handle include or exclude with custom filter together');
+ }
+ const userDefinedFilter =
+ typeof customFilter === 'function' ? customFilter : createFilter(include, exclude);
+ const filter = (id, code) => extensionRegExp.test(id) && userDefinedFilter(id, code);
- const extensionRegExp = new RegExp(
- `(${extensions.map(escapeRegExpCharacters).join('|')})$`
- );
- if (customFilter && (include || exclude)) {
- throw new Error('Could not handle include or exclude with custom filter together');
- }
- const userDefinedFilter =
- typeof customFilter === 'function' ? customFilter : createFilter(include, exclude);
- filter = (id) => extensionRegExp.test(stripQuery(id).bareId) && userDefinedFilter(id);
+ const helpersFilter = { id: new RegExp(`^${escapeRegExpCharacters(HELPERS)}$`) };
- return null;
- },
+ return {
+ name: 'babel',
- resolveId(id) {
- if (id !== HELPERS) {
- return null;
+ resolveId: {
+ filter: helpersFilter,
+ handler(id) {
+ if (id !== HELPERS) {
+ return null;
+ }
+ return id;
}
- return id;
},
- load(id) {
- if (id !== HELPERS) {
- return null;
+ load: {
+ filter: helpersFilter,
+ handler(id) {
+ if (id !== HELPERS) {
+ return null;
+ }
+ return babel.buildExternalHelpers(null, 'module');
}
- return babel.buildExternalHelpers(null, 'module');
},
- transform(code, filename) {
- if (!filter(filename)) return null;
- if (filename === HELPERS) return null;
-
- return transformCode(
- code,
- { ...babelOptions, filename },
- overrides,
- customOptions,
- this,
- async (transformOptions) => {
- if (!skipPreflightCheck) {
- await preflightCheck(this, babelHelpers, transformOptions);
+ transform: {
+ filter: {
+ id: extensionRegExp
+ },
+ async handler(code, filename) {
+ if (!(await filter(filename, code))) return null;
+ if (filename === HELPERS) return null;
+
+ return transformCode(
+ code,
+ { ...babelOptions, filename },
+ overrides,
+ customOptions,
+ this,
+ async (transformOptions) => {
+ if (!skipPreflightCheck) {
+ await preflightCheck(this, babelHelpers, transformOptions);
+ }
+
+ return babelHelpers === BUNDLED
+ ? addBabelPlugin(transformOptions, bundledHelpersPlugin)
+ : transformOptions;
}
-
- return babelHelpers === BUNDLED
- ? addBabelPlugin(transformOptions, bundledHelpersPlugin)
- : transformOptions;
- }
- );
+ );
+ }
}
};
};
diff --git a/packages/babel/test/as-input-plugin.mjs b/packages/babel/test/as-input-plugin.mjs
index c7d145558..4b8d9495f 100644
--- a/packages/babel/test/as-input-plugin.mjs
+++ b/packages/babel/test/as-input-plugin.mjs
@@ -122,6 +122,23 @@ console.log("the answer is ".concat(foo()));
);
});
+test('does not babelify excluded code with code-based filter', async (t) => {
+ const filter = (id, code) => code.includes('the answer is');
+ const code = await generate('exclusions/main.js', { filter });
+ // eslint-disable-next-line no-template-curly-in-string
+ t.false(code.includes('${foo()}'));
+ t.true(code.includes('=> 42'));
+ t.is(
+ code,
+ `'use strict';
+
+const foo = () => 42;
+
+console.log("the answer is ".concat(foo()));
+`
+ );
+});
+
test('does babelify included code with custom filter', async (t) => {
const filter = createFilter('**/foo.js', [], {
resolve: DIRNAME
@@ -143,6 +160,25 @@ console.log(\`the answer is \${foo()}\`);
);
});
+test('does babelify excluded code with code-based filter', async (t) => {
+ const filter = (id, code) => !code.includes('the answer is');
+ const code = await generate('exclusions/main.js', { filter });
+ // eslint-disable-next-line no-template-curly-in-string
+ t.true(code.includes('${foo()}'));
+ t.false(code.includes('=> 42'));
+ t.is(
+ code,
+ `'use strict';
+
+var foo = function foo() {
+ return 42;
+};
+
+console.log(\`the answer is \${foo()}\`);
+`
+ );
+});
+
test('can not pass include or exclude when custom filter specified', async (t) => {
const filter = createFilter('**/foo.js', [], {
resolve: DIRNAME
diff --git a/packages/babel/types/index.d.ts b/packages/babel/types/index.d.ts
index 20288d8a0..76cf6af8a 100644
--- a/packages/babel/types/index.d.ts
+++ b/packages/babel/types/index.d.ts
@@ -1,5 +1,5 @@
import type { Plugin, PluginContext, TransformPluginContext } from 'rollup';
-import type { FilterPattern, CreateFilter } from '@rollup/pluginutils';
+import type { FilterPattern } from '@rollup/pluginutils';
import type * as babelCore from '@babel/core';
export interface RollupBabelInputPluginOptions
@@ -23,7 +23,7 @@ export interface RollupBabelInputPluginOptions
* const filter = createFilter(include, exclude, {});
* @default undefined;
*/
- filter?: ReturnType;
+ filter?: (id: string, code: string) => Promise;
/**
* An array of file extensions that Babel should transpile. If you want to transpile TypeScript files with this plugin it's essential to include .ts and .tsx in this option.
* @default ['.js', '.jsx', '.es6', '.es', '.mjs']