'How to use BigInt exponentiation with Babel?

Consider this:

const a = BigInt(2);
const b = BigInt(2);
const c = a ** b;

Babel will convert this to:

var a = BigInt(2);
var b = BigInt(2);
var c = Math.pow(a, b);

However, Math.pow doesn't work with BigInt. As far as I know, it's impossible to get Babel to ignore a certain line. I found babel-plugin-transform-bigint, but I don't want to load a polyfill for this. If BigInt isn't supported, then I'll just set an upper limit for the input.

My options are to override Math.pow or manually implement exponentiation. Is it impossible to use the native ** operator with BigInt and Babel at the moment?

Also, just confirming, ** would be a syntax error if it isn't supported right?

Edit: babel.config.js:

module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'usage',
      corejs: '2',
      exclude: [
        'babel-plugin-transform-async-to-generator',
        'babel-plugin-transform-regenerator',
      ],
    }],
  ],
  plugins: [
    '@babel/plugin-syntax-dynamic-import',
    ['@babel/plugin-transform-react-jsx', { pragma: 'h' }],
    '@babel/plugin-proposal-do-expressions',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-optional-chaining',
    /*
    Async/await increases file size by a lot.
    ['module:fast-async', {
      'compiler': { 'promises': true, 'generators': false, 'useRuntimeModule': true },
    }],
    ['@babel/plugin-transform-modules-commonjs', {
      'strictMode': false,
    }],
    */
  ],
  env: {
    production: {
      plugins: ['transform-react-remove-prop-types'],
    },
  },
  sourceType: 'unambiguous',
};


Solution 1:[1]

For those of you getting this problem in Create React App. See the following thread and solutions:

https://github.com/0xs34n/starknet.js/issues/37#issuecomment-955797303 and https://github.com/babel/babel/issues/13109#issuecomment-826287089

Basically you can change the browserlist of your package.json in order to prevent babel from running its transform-exponentiation-operator plugin like so:

"browserslist": {
    "production": [
      "chrome >= 67",
      "edge >= 79",
      "firefox >= 68",
      "opera >= 54",
      "safari >= 14"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }

For non-browser react environments such as react-native-macos, react-native-windows, electron, see the gist here for a way to create your own babel.config.js to choose which plugins/transforms to run:

https://gist.github.com/karanjthakkar/3241808022a75d8068f35a33b57e90c5

There's a twitter thread explaining the problem: https://twitter.com/geekykaran/status/1082218546799755266

An example of babel.config.js without the babel-plugin-transform-exponentiation-operator applied:

const lazyImports = require('metro-react-native-babel-preset/src/configs/lazy-imports');

module.exports = (api) => {
  api.cache(true);
  return {
    comments: false,
    compact: true,
    plugins: [
      '@babel/plugin-transform-flow-strip-types',
      '@babel/plugin-proposal-optional-catch-binding',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-block-scoping',
      ['@babel/plugin-proposal-class-properties', {
        loose: true,
      }],
      '@babel/plugin-syntax-dynamic-import',
      '@babel/plugin-syntax-export-default-from',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-computed-properties',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-destructuring',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-function-name',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-literals',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-parameters',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-shorthand-properties',
      '@babel/plugin-transform-react-jsx',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-regenerator',
      '@babel/plugin-transform-sticky-regex',
      '@babel/plugin-transform-unicode-regex',
      '@babel/plugin-proposal-export-default-from',
      [
        '@babel/plugin-transform-modules-commonjs',
        {
          strict: false,
          strictMode: false, // prevent "use strict" injections
          lazy: importSpecifier => lazyImports.has(importSpecifier),
          allowTopLevelThis: true, // dont rewrite global `this` -> `undefined`
        },
      ],
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-classes',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-arrow-functions'
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-spread',
      '@babel/plugin-proposal-object-rest-spread',
      // SUPPORTED BY DEFAULT: [
      // SUPPORTED BY DEFAULT:   '@babel/plugin-transform-template-literals',
      // SUPPORTED BY DEFAULT:   {loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
      // SUPPORTED BY DEFAULT: ],
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-exponentiation-operator',
      // SUPPORTED BY DEFAULT: '@babel/plugin-transform-object-assign',
      // SUPPORTED BY DEFAULT: ['@babel/plugin-transform-for-of', {loose: true}],
      // 'metro-react-native-babel-preset/src/transforms/transform-symbol-member',
      '@babel/plugin-transform-react-display-name',
      '@babel/plugin-proposal-optional-chaining',
      '@babel/plugin-proposal-nullish-coalescing-operator',
      ['@babel/plugin-transform-runtime', {
        helpers: true,
        regenerator: true,
      }],
    ],
  };
};

Remember to reset the cache when restarting the bundler with npm/yarn

npm start -- --reset-cache

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ragamufin