From c252d3dae6bef764b8c0a956f29880cd9fe937ba Mon Sep 17 00:00:00 2001 From: Richard Macklin Date: Sun, 19 Jun 2016 02:32:24 -0700 Subject: [PATCH] Add exactGlobals option to transform-es2015-modules-umd plugin to enable more flexibility specifying global names --- .../README.md | 98 +++++++++++++++++++ .../src/index.js | 30 +++++- .../actual.js | 3 + .../expected.js | 21 ++++ .../options.json | 12 +++ .../umd/imports-exact-globals-false/actual.js | 3 + .../imports-exact-globals-false/expected.js | 21 ++++ .../actual.js | 3 + .../expected.js | 21 ++++ .../options.json | 13 +++ .../umd/imports-exact-globals-true/actual.js | 3 + .../imports-exact-globals-true/expected.js | 21 ++++ .../imports-exact-globals-true/options.json | 8 ++ 13 files changed, 252 insertions(+), 5 deletions(-) create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/actual.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/expected.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/options.json create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/actual.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/expected.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/actual.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/expected.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/options.json create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/actual.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/expected.js create mode 100644 packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/options.json diff --git a/packages/babel-plugin-transform-es2015-modules-umd/README.md b/packages/babel-plugin-transform-es2015-modules-umd/README.md index 6a3e8f1b7e..823cd428fb 100644 --- a/packages/babel-plugin-transform-es2015-modules-umd/README.md +++ b/packages/babel-plugin-transform-es2015-modules-umd/README.md @@ -34,6 +34,104 @@ as `global.Promise` rather than `global.es6Promise`. This can be accommodated by } ``` +#### Default semantics + +There are a couple things to note about the default semantics. + +_First_, this transform uses the +[basename](https://en.wikipedia.org/wiki/Basename) of each import to generate +the global names in the UMD output. This means that if you're importing +multiple modules with the same basename, like: + +```js +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +``` + +it will transpile into two references to the same browser global: + +```js +factory(global.fooBar, global.fooBar); +``` + +If you set the plugin options to: + +```json +{ + "globals": { + "foo-bar": "fooBAR", + "./mylib/foo-bar": "mylib.fooBar" + } +} +``` + +it will still transpile both to one browser global: + +```js +factory(global.fooBAR, global.fooBAR); +``` + +because again the transform is only using the basename of the import. + +_Second_, the specified override will still be passed to the `toIdentifier` +function in [babel-types/src/converters](../babel-types/src/converters.js). +This means that if you specify an override as a member expression like: + +```json +{ + "globals": { + "fizzbuzz": "fizz.buzz" + } +} +``` + +this will _not_ transpile to `factory(global.fizz.buzz)`. Instead, it will +transpile to `factory(global.fizzBuzz)` based on the logic in `toIdentifier`. + +#### More flexible semantics with `exactGlobals: true` + +Both of these behaviors can limit the flexibility of the `globals` map. To +remove these limitations, you can set the `exactGlobals` option to `true`. +Doing this instructs the plugin to: + +1. always use the full import string instead of the basename when generating +the global names +2. skip passing `globals` overrides to the `toIdentifier` function. Instead, +they are used exactly as written, so you will get errors if you do not use +valid identifiers or valid uncomputed (dot) member expressions. + +Thus, if you set `exactGlobals` to `true` and do not pass any overrides, the +first example of: + +```js +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +``` + +will transpile to: + +```js +factory(global.fooBar, global.mylibFooBar); +``` + +And if you set the plugin options to: + +```json +{ + "globals": { + "foo-bar": "fooBAR", + "./mylib/foo-bar": "mylib.fooBar" + }, + "exactGlobals": true +} +``` + +then it'll transpile to: + +```js +factory(global.fooBAR, global.mylib.fooBar) +``` + ### Via CLI ```sh diff --git a/packages/babel-plugin-transform-es2015-modules-umd/src/index.js b/packages/babel-plugin-transform-es2015-modules-umd/src/index.js index 26b59f19d0..cbe8cae0ee 100644 --- a/packages/babel-plugin-transform-es2015-modules-umd/src/index.js +++ b/packages/babel-plugin-transform-es2015-modules-umd/src/index.js @@ -65,12 +65,32 @@ export default function ({ types: t }) { } else if (arg.value === "exports") { return t.memberExpression(t.identifier("mod"), t.identifier("exports")); } else { - let requireName = basename(arg.value, extname(arg.value)); - let globalName = browserGlobals[requireName] || requireName; + let memberExpression; - return t.memberExpression(t.identifier("global"), t.identifier( - t.toIdentifier(globalName) - )); + if (state.opts.exactGlobals) { + let globalRef = browserGlobals[arg.value]; + if (globalRef) { + if (globalRef.indexOf(".") > -1) { + memberExpression = globalRef.split(".").reduce( + (accum, curr) => t.memberExpression(accum, t.identifier(curr)), t.identifier("global") + ); + } else { + memberExpression = t.memberExpression(t.identifier("global"), t.identifier(globalRef)); + } + } else { + memberExpression = t.memberExpression( + t.identifier("global"), t.identifier(t.toIdentifier(arg.value)) + ); + } + } else { + let requireName = basename(arg.value, extname(arg.value)); + let globalName = browserGlobals[requireName] || requireName; + memberExpression = t.memberExpression( + t.identifier("global"), t.identifier(t.toIdentifier(globalName)) + ); + } + + return memberExpression; } }); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/actual.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/actual.js new file mode 100644 index 0000000000..0e67018dc4 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/actual.js @@ -0,0 +1,3 @@ +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +import fizzBuzz from "fizzbuzz"; diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/expected.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/expected.js new file mode 100644 index 0000000000..5bb49994e0 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/expected.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["foo-bar", "./mylib/foo-bar", "fizzbuzz"], factory); + } else if (typeof exports !== "undefined") { + factory(require("foo-bar"), require("./mylib/foo-bar"), require("fizzbuzz")); + } else { + var mod = { + exports: {} + }; + factory(global.fooBAR, global.fooBAR, global.fizzBuzz); + global.actual = mod.exports; + } +})(this, function (_fooBar, _fooBar3, _fizzbuzz) { + "use strict"; + + var _fooBar2 = babelHelpers.interopRequireDefault(_fooBar); + + var _fooBar4 = babelHelpers.interopRequireDefault(_fooBar3); + + var _fizzbuzz2 = babelHelpers.interopRequireDefault(_fizzbuzz); +}); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/options.json b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/options.json new file mode 100644 index 0000000000..e15ffb81e0 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false-with-overrides/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + "external-helpers", + ["transform-es2015-modules-umd", { + "globals": { + "foo-bar": "fooBAR", + "./mylib/foo-bar": "mylib.fooBar", + "fizzbuzz": "fizz.buzz" + } + }] + ] +} diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/actual.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/actual.js new file mode 100644 index 0000000000..0e67018dc4 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/actual.js @@ -0,0 +1,3 @@ +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +import fizzBuzz from "fizzbuzz"; diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/expected.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/expected.js new file mode 100644 index 0000000000..527e2f698b --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-false/expected.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["foo-bar", "./mylib/foo-bar", "fizzbuzz"], factory); + } else if (typeof exports !== "undefined") { + factory(require("foo-bar"), require("./mylib/foo-bar"), require("fizzbuzz")); + } else { + var mod = { + exports: {} + }; + factory(global.fooBar, global.fooBar, global.fizzbuzz); + global.actual = mod.exports; + } +})(this, function (_fooBar, _fooBar3, _fizzbuzz) { + "use strict"; + + var _fooBar2 = babelHelpers.interopRequireDefault(_fooBar); + + var _fooBar4 = babelHelpers.interopRequireDefault(_fooBar3); + + var _fizzbuzz2 = babelHelpers.interopRequireDefault(_fizzbuzz); +}); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/actual.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/actual.js new file mode 100644 index 0000000000..0e67018dc4 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/actual.js @@ -0,0 +1,3 @@ +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +import fizzBuzz from "fizzbuzz"; diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/expected.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/expected.js new file mode 100644 index 0000000000..702163cd78 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/expected.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["foo-bar", "./mylib/foo-bar", "fizzbuzz"], factory); + } else if (typeof exports !== "undefined") { + factory(require("foo-bar"), require("./mylib/foo-bar"), require("fizzbuzz")); + } else { + var mod = { + exports: {} + }; + factory(global.fooBAR, global.mylib.fooBar, global.fizz.buzz); + global.actual = mod.exports; + } +})(this, function (_fooBar, _fooBar3, _fizzbuzz) { + "use strict"; + + var _fooBar2 = babelHelpers.interopRequireDefault(_fooBar); + + var _fooBar4 = babelHelpers.interopRequireDefault(_fooBar3); + + var _fizzbuzz2 = babelHelpers.interopRequireDefault(_fizzbuzz); +}); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/options.json b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/options.json new file mode 100644 index 0000000000..01e37b5b27 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true-with-overrides/options.json @@ -0,0 +1,13 @@ +{ + "plugins": [ + "external-helpers", + ["transform-es2015-modules-umd", { + "globals": { + "foo-bar": "fooBAR", + "./mylib/foo-bar": "mylib.fooBar", + "fizzbuzz": "fizz.buzz" + }, + "exactGlobals": true + }] + ] +} diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/actual.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/actual.js new file mode 100644 index 0000000000..0e67018dc4 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/actual.js @@ -0,0 +1,3 @@ +import fooBar1 from "foo-bar"; +import fooBar2 from "./mylib/foo-bar"; +import fizzBuzz from "fizzbuzz"; diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/expected.js b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/expected.js new file mode 100644 index 0000000000..990ac8401f --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/expected.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["foo-bar", "./mylib/foo-bar", "fizzbuzz"], factory); + } else if (typeof exports !== "undefined") { + factory(require("foo-bar"), require("./mylib/foo-bar"), require("fizzbuzz")); + } else { + var mod = { + exports: {} + }; + factory(global.fooBar, global.mylibFooBar, global.fizzbuzz); + global.actual = mod.exports; + } +})(this, function (_fooBar, _fooBar3, _fizzbuzz) { + "use strict"; + + var _fooBar2 = babelHelpers.interopRequireDefault(_fooBar); + + var _fooBar4 = babelHelpers.interopRequireDefault(_fooBar3); + + var _fizzbuzz2 = babelHelpers.interopRequireDefault(_fizzbuzz); +}); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/options.json b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/options.json new file mode 100644 index 0000000000..3ac7220822 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-umd/test/fixtures/umd/imports-exact-globals-true/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + "external-helpers", + ["transform-es2015-modules-umd", { + "exactGlobals": true + }] + ] +}