Skip to content

Commit

Permalink
fix(babel): strip hash and query param in extension filter (#533)
Browse files Browse the repository at this point in the history
* fix(babel): strip query param in extension filter

* fix(babel): fix test

* test(babel): make test more robust
  • Loading branch information
csr632 committed Oct 28, 2020
1 parent 4387386 commit 83bcdcf
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 10 deletions.
1 change: 1 addition & 0 deletions packages/babel/package.json
Expand Up @@ -62,6 +62,7 @@
"@babel/plugin-transform-runtime": "^7.10.5",
"@babel/preset-env": "^7.10.4",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"@types/babel__core": "^7.1.9",
"rollup": "^2.23.0",
"source-map": "^0.7.3"
Expand Down
21 changes: 14 additions & 7 deletions packages/babel/src/index.js
Expand Up @@ -5,7 +5,7 @@ import { BUNDLED, HELPERS } from './constants';
import bundledHelpersPlugin from './bundledHelpersPlugin';
import preflightCheck from './preflightCheck';
import transformCode from './transformCode';
import { addBabelPlugin, escapeRegExpCharacters, warnOnce } from './utils';
import { addBabelPlugin, escapeRegExpCharacters, warnOnce, stripQuery } from './utils';

const unpackOptions = ({
extensions = babel.DEFAULT_EXTENSIONS,
Expand Down Expand Up @@ -35,7 +35,7 @@ const warnAboutDeprecatedHelpersOption = ({ deprecatedOption, suggestion }) => {
`\`${deprecatedOption}\` has been removed in favor a \`babelHelpers\` option. Try changing your configuration to \`${suggestion}\`. ` +
`Refer to the documentation to learn more: https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers`
);
}
};

const unpackInputPluginOptions = ({ skipPreflightCheck = false, ...rest }, rollupVersion) => {
if ('runtimeHelpers' in rest) {
Expand Down Expand Up @@ -110,13 +110,18 @@ function createBabelInputPluginFactory(customCallback = returnObject) {
overrides
);

let babelHelpers, babelOptions, filter, skipPreflightCheck;
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, include, extensions;
// todo: remove options hook and hoist declarations when version checks are removed
let exclude;
let include;
let extensions;

({
exclude,
Expand All @@ -127,9 +132,11 @@ function createBabelInputPluginFactory(customCallback = returnObject) {
...babelOptions
} = unpackInputPluginOptions(pluginOptionsWithOverrides, this.meta.rollupVersion));

const extensionRegExp = new RegExp(`(${extensions.map(escapeRegExpCharacters).join('|')})$`);
const extensionRegExp = new RegExp(
`(${extensions.map(escapeRegExpCharacters).join('|')})$`
);
const includeExcludeFilter = createFilter(include, exclude);
filter = (id) => extensionRegExp.test(id) && includeExcludeFilter(id);
filter = (id) => extensionRegExp.test(stripQuery(id).bareId) && includeExcludeFilter(id);

return null;
},
Expand Down
11 changes: 11 additions & 0 deletions packages/babel/src/utils.js
Expand Up @@ -14,3 +14,14 @@ export function warnOnce(ctx, msg) {

const regExpCharactersRegExp = /[\\^$.*+?()[\]{}|]/g;
export const escapeRegExpCharacters = (str) => str.replace(regExpCharactersRegExp, '\\$&');

export function stripQuery(id) {
// strip query params from import
const [bareId, query] = id.split('?');
const suffix = `${query ? `?${query}` : ''}`;
return {
bareId,
query,
suffix
};
}
39 changes: 36 additions & 3 deletions packages/babel/test/as-input-plugin.js
@@ -1,9 +1,11 @@
import * as nodePath from 'path';
import * as fs from 'fs';

import test from 'ava';
import { rollup } from 'rollup';
import { SourceMapConsumer } from 'source-map';
import jsonPlugin from '@rollup/plugin-json';
import nodeResolvePlugin from '@rollup/plugin-node-resolve';

import { getCode } from '../../../util/test';

Expand Down Expand Up @@ -157,12 +159,14 @@ test('allows transform-runtime to be used instead of bundled helpers', async (t)
code,
`'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
var _classCallCheck = _interopDefault(require('@babel/runtime/helpers/classCallCheck'));
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
var Foo = function Foo() {
_classCallCheck(this, Foo);
_classCallCheck__default['default'](this, Foo);
};
module.exports = Foo;
Expand Down Expand Up @@ -287,6 +291,35 @@ test('transpiles only files with whitelisted extensions', async (t) => {
t.false(code.includes('class Other '), 'should transpile .other');
});

test('transpiles files when path contains query and hash', async (t) => {
const code = await generate(
'fixtures/with-query-and-hash/main.js',
{},
{},
{
plugins: [
babelPlugin({ babelHelpers: 'bundled' }),
// node-resolve plugin know how to resolve relative request with query
nodeResolvePlugin(),
{
load(id) {
// rollup don't know how to load module with query
// we could teach rollup to discard query while loading module
const [bareId] = id.split(`?`);
return fs.readFileSync(bareId, 'utf-8');
}
}
]
}
);
t.true(code.includes('function WithQuery()'), 'should transpile when path contains query');
t.true(code.includes('function WithHash()'), 'should transpile when path contains hash');
t.true(
code.includes('function WithQueryAndHash()'),
'should transpile when path contains query and hash'
);
});

test('throws when trying to add babel helper unavailable in used @babel/core version', async (t) => {
await t.throwsAsync(
() =>
Expand Down
10 changes: 10 additions & 0 deletions packages/babel/test/fixtures/with-query-and-hash/main.js
@@ -0,0 +1,10 @@
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */

// ? should be treated as special symbol for query params
export { default as WithQuery } from './moduleQuery?q=asd';
// # should be treated as normal filename character
export { default as WithHash } from './module#Hash';

// So, this is an import with path "./moduleQueryAnd#Hash" and query "?q=asd#hash"
export { default as WithQueryAndHash } from './moduleQueryAnd#Hash?q=asd#hash';
@@ -0,0 +1 @@
export default class WithHash {}
@@ -0,0 +1 @@
export default class WithQuery {}
@@ -0,0 +1 @@
export default class WithQueryAndHash {}
22 changes: 22 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 83bcdcf

Please sign in to comment.