Skip to content

Commit

Permalink
fix(bug): fixes issue where babel helpers would force ESM variants ev…
Browse files Browse the repository at this point in the history
…en though they were marked as external. Fixes #15
  • Loading branch information
wessberg committed Apr 11, 2019
1 parent 7b4c4fa commit f981b17
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 42 deletions.
37 changes: 27 additions & 10 deletions src/constant/constant.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {InputOptions} from "rollup";

export const SOURCE_MAP_EXTENSION = ".map";
export const TS_EXTENSION = ".ts";
export const TSX_EXTENSION = ".tsx";
Expand All @@ -14,14 +16,10 @@ export const SOURCE_MAP_COMMENT_REGEXP = /\n\/\/# sourceMappingURL=.*/g;
export const TSLIB_NAME = `tslib${DECLARATION_EXTENSION}`;
export const BABEL_RUNTIME_PREFIX_1 = "@babel/runtime/";
export const BABEL_RUNTIME_PREFIX_2 = "babel-runtime/";

export const REGENERATOR_RUNTIME_NAME_1 = `${BABEL_RUNTIME_PREFIX_1}regenerator/index.js`;
export const REGENERATOR_RUNTIME_NAME_2 = `${BABEL_RUNTIME_PREFIX_2}regenerator/index.js`;
export const TYPEOF_BABEL_HELPER_NAME_1 = `${BABEL_RUNTIME_PREFIX_1}helpers/esm/typeof.js`;
export const TYPEOF_BABEL_HELPER_NAME_2 = `${BABEL_RUNTIME_PREFIX_2}helpers/typeof.js`;
export const TYPEOF_BABEL_HELPER_NAME_3 = `${BABEL_RUNTIME_PREFIX_1}helpers/esm/typeof.js`;
export const TYPEOF_BABEL_HELPER_NAME_4 = `${BABEL_RUNTIME_PREFIX_2}helpers/typeof.js`;
export const TYPEOF_BABEL_HELPER_NAME_5 = `${BABEL_RUNTIME_PREFIX_1}helpers/esm/instanceof.js`;
export const TYPEOF_BABEL_HELPER_NAME_6 = `${BABEL_RUNTIME_PREFIX_2}helpers/instanceof.js`;
export const BABEL_EXAMPLE_HELPERS = [`${BABEL_RUNTIME_PREFIX_1}helpers/esm/typeof.js`, `${BABEL_RUNTIME_PREFIX_2}helpers/esm/typeof.js`];

export const BABEL_MINIFICATION_BLACKLIST_PRESET_NAMES = [];

Expand Down Expand Up @@ -66,10 +64,29 @@ export const FORCED_BABEL_YEARLY_PRESET_OPTIONS = {
...FORCED_BABEL_PRESET_ENV_OPTIONS
};

export const FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS = {
helpers: true,
useESModules: true,
regenerator: true
export const FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS = (rollupInputOptions: InputOptions) => {
let forceESModules: boolean = true;

// Only apply the forceESModules option if @babel helpers aren't treated as external.
if (
BABEL_EXAMPLE_HELPERS.some(helper => {
if (typeof rollupInputOptions.external === "function") {
return rollupInputOptions.external(helper, "", true) === true;
} else if (Array.isArray(rollupInputOptions.external)) {
return rollupInputOptions.external.includes(helper);
} else {
return false;
}
})
) {
forceESModules = false;
}

return {
helpers: true,
regenerator: true,
...(forceESModules ? {forceESModules: true} : {})
};
};

export const MAIN_FIELDS = ["module", "es2015", "esm2015", "jsnext:main", "main"];
Expand Down
7 changes: 4 additions & 3 deletions src/plugin/typescript-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {EmitCache} from "../service/cache/emit-cache/emit-cache";
import {emitDeclarations} from "../util/emit-declarations/emit-declarations";
import {emitDiagnosticsThroughRollup} from "../util/diagnostic/emit-diagnostics-through-rollup";
import {getSupportedExtensions} from "../util/get-supported-extensions/get-supported-extensions";
import {ensureRelative, getExtension, isNonTransformableBabelHelper, isRollupPluginMultiEntry} from "../util/path/path-util";
import {ensureRelative, getExtension, isBabelHelper, isRollupPluginMultiEntry} from "../util/path/path-util";
import {join} from "path";
import {ModuleResolutionHost} from "../service/module-resolution-host/module-resolution-host";
import {takeBundledFilesNames} from "../util/take-bundled-filenames/take-bundled-filenames";
Expand Down Expand Up @@ -172,7 +172,8 @@ export default function typescriptRollupPlugin(pluginInputOptions: Partial<Types
babelConfig: pluginOptions.babelConfig,
forcedOptions: getForcedBabelOptions({cwd, pluginOptions, rollupInputOptions, browserslist: computedBrowserslist}),
defaultOptions: getDefaultBabelOptions({pluginOptions, rollupInputOptions, browserslist: computedBrowserslist}),
browserslist: computedBrowserslist
browserslist: computedBrowserslist,
rollupInputOptions
});
babelConfig = babelConfigResult.config;
babelMinifyConfig = babelConfigResult.minifyConfig;
Expand Down Expand Up @@ -261,7 +262,7 @@ export default function typescriptRollupPlugin(pluginInputOptions: Partial<Types
}

// Skip the file if it doesn't match the filter or if the helper cannot be transformed
if (!filter(file) || isNonTransformableBabelHelper(file)) {
if (!filter(file) || isBabelHelper(file)) {
return undefined;
}

Expand Down
70 changes: 70 additions & 0 deletions src/util/flat/flat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// tslint:disable:array-type

export declare type Flat<A> = A extends Array<infer B>
? B extends Array<infer C>
? C extends Array<infer D>
? D extends Array<infer E>
? E extends Array<infer F>
? F extends Array<infer G>
? G extends Array<infer H>
? H extends Array<infer I>
? I extends Array<infer J>
? J extends Array<infer K>
? K extends Array<infer L>
? L extends Array<infer M>
? M extends Array<infer N>
? M
: L
: K
: J
: I
: H
: G
: F
: E
: D
: C
: B
: A
: A;

// tslint:disable:no-any

/**
* Flattens the array with the given recursive depth
* @param {T[]} arr
* @returns {T[]}
*/
export function flat<T>(arr: T): Flat<T> {
const target: any[] = [];
if (!Array.isArray(arr)) return <Flat<T>>arr;

flattenIntoArray(target, arr, Infinity);
return <Flat<T>>(<any>target);
}

/**
* Flattens the given source array into a new array
* @param {T[]} target
* @param {T[]} source
* @param {number} [depth=1]
* @param {number} [start=0]
* @returns {number}
*/
function flattenIntoArray<T>(target: T[], source: T[], depth: number = 1, start: number = 0): number {
let targetIndex = start;
let sourceIndex = 0;
const sourceLength = source.length;
while (sourceIndex < sourceLength) {
const element = source[sourceIndex];

if (depth > 0 && Array.isArray(element)) {
targetIndex = flattenIntoArray(target, element, depth - 1, targetIndex);
} else {
target[targetIndex] = element;
targetIndex++;
}
sourceIndex++;
}
return targetIndex;
}
4 changes: 2 additions & 2 deletions src/util/get-babel-config/get-babel-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function configItemIsAllowedDuringNoMinification({file: {resolved}}: IBabelConfi
* @param {IGetBabelConfigOptions} options
* @returns {IGetBabelConfigResult}
*/
export function getBabelConfig({babelConfig, cwd, forcedOptions = {}, defaultOptions = {}, browserslist}: IGetBabelConfigOptions): IGetBabelConfigResult {
export function getBabelConfig({babelConfig, cwd, forcedOptions = {}, defaultOptions = {}, browserslist, rollupInputOptions}: IGetBabelConfigOptions): IGetBabelConfigResult {
// Load a partial Babel config based on the input options
const partialConfig = loadPartialConfig(
isBabelInputOptions(babelConfig)
Expand Down Expand Up @@ -156,7 +156,7 @@ export function getBabelConfig({babelConfig, cwd, forcedOptions = {}, defaultOpt
plugin.file.request,
{
...(plugin.options == null ? {} : plugin.options),
...FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS
...FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS(rollupInputOptions)
}
],
{type: "plugin", dirname: cwd}
Expand Down
2 changes: 2 additions & 0 deletions src/util/get-babel-config/i-get-babel-config-options.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {ITypescriptPluginBabelOptions} from "../../plugin/i-typescript-plugin-options";
import {IGetForcedBabelOptionsResult} from "../get-forced-babel-options/i-get-forced-babel-options-result";
import {IGetDefaultBabelOptionsResult} from "../get-default-babel-options/i-get-default-babel-options-result";
import {InputOptions} from "rollup";

export interface IGetBabelConfigOptions {
cwd: string;
browserslist: string[] | undefined;
rollupInputOptions: InputOptions;
babelConfig?: ITypescriptPluginBabelOptions["babelConfig"];
forcedOptions?: IGetForcedBabelOptionsResult;
defaultOptions?: IGetDefaultBabelOptionsResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS, FORCED_BABEL_PRESET_ENV_O
* @param {IGetDefaultBabelOptionsOptions} _options
* @returns {IGetDefaultBabelOptionsResult}
*/
export function getDefaultBabelOptions({browserslist}: IGetDefaultBabelOptionsOptions): IGetDefaultBabelOptionsResult {
export function getDefaultBabelOptions({browserslist, rollupInputOptions}: IGetDefaultBabelOptionsOptions): IGetDefaultBabelOptionsResult {
const includePresetEnv = browserslist != null;

return {
Expand Down Expand Up @@ -49,7 +49,7 @@ export function getDefaultBabelOptions({browserslist}: IGetDefaultBabelOptionsOp
[
"@babel/plugin-transform-runtime",
{
...FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS,
...FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS(rollupInputOptions),
corejs: false
}
]
Expand Down
46 changes: 21 additions & 25 deletions src/util/path/path-util.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import {isAbsolute, join, parse, relative, extname} from "path";
import {extname, isAbsolute, join, parse, relative} from "path";
import {
BABEL_RUNTIME_PREFIX_1,
BABEL_RUNTIME_PREFIX_2,
DECLARATION_EXTENSION,
DECLARATION_MAP_EXTENSION,
DEFAULT_LIB_NAMES,
JS_EXTENSION,
JSX_EXTENSION,
MJS_EXTENSION,
TSX_EXTENSION,
ROLLUP_PLUGIN_MULTI_ENTRY,
TS_EXTENSION,
DEFAULT_LIB_NAMES,
TSLIB_NAME,
TYPEOF_BABEL_HELPER_NAME_1,
TYPEOF_BABEL_HELPER_NAME_2,
TYPEOF_BABEL_HELPER_NAME_3,
TYPEOF_BABEL_HELPER_NAME_4,
BABEL_RUNTIME_PREFIX_1,
BABEL_RUNTIME_PREFIX_2,
TYPEOF_BABEL_HELPER_NAME_6,
TYPEOF_BABEL_HELPER_NAME_5,
ROLLUP_PLUGIN_MULTI_ENTRY
TSX_EXTENSION
} from "../../constant/constant";

/**
Expand Down Expand Up @@ -59,28 +53,30 @@ export function isTslib(path: string): boolean {
}

/**
* Returns true if the given path represents a Babel helper that shouldn't be transformed
* Returns true if the given path represents a Babel helper
* @param {string} path
* @returns {boolean}
*/
export function isBabelHelper(path: string): boolean {
return isBabelEsmHelper(path) || isBabelCjsHelper(path);
}

/**
* Returns true if the given path represents a Babel ESM helper
* @param {string} path
* @returns {boolean}
*/
export function isNonTransformableBabelHelper(path: string): boolean {
return (
path.endsWith(TYPEOF_BABEL_HELPER_NAME_1) ||
path.endsWith(TYPEOF_BABEL_HELPER_NAME_2) ||
path.endsWith(TYPEOF_BABEL_HELPER_NAME_3) ||
path.endsWith(TYPEOF_BABEL_HELPER_NAME_4) ||
path.endsWith(TYPEOF_BABEL_HELPER_NAME_5) ||
path.endsWith(TYPEOF_BABEL_HELPER_NAME_6)
);
export function isBabelEsmHelper(path: string): boolean {
return path.startsWith(`${BABEL_RUNTIME_PREFIX_1}helpers/esm`) || path.startsWith(`${BABEL_RUNTIME_PREFIX_2}helpers/esm`);
}

/**
* Returns true if the given path represents a Babel helper
* Returns true if the given path represents a Babel CJS helper
* @param {string} path
* @returns {boolean}
*/
export function isBabelHelper(path: string): boolean {
return path.startsWith(BABEL_RUNTIME_PREFIX_1) || path.startsWith(BABEL_RUNTIME_PREFIX_2);
export function isBabelCjsHelper(path: string): boolean {
return !isBabelEsmHelper(path) && (path.startsWith(`${BABEL_RUNTIME_PREFIX_1}helpers`) || path.startsWith(`${BABEL_RUNTIME_PREFIX_2}helpers`));
}

/**
Expand Down

0 comments on commit f981b17

Please sign in to comment.