Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After upgrading babel preset-env, core, runtime and typescript to 7.7.7, async functions are not working in some cases #10928

Open
kelly-tock opened this issue Dec 26, 2019 · 14 comments
Labels

Comments

@kelly-tock
Copy link

@kelly-tock kelly-tock commented Dec 26, 2019

Bug Report

After updating preset-env ,core, runtime, and typescript to 7.7.7 from 7.7.5, in some scenarios async functions are not behaving the same way.

image

  • I would like to work on a fix!

Current Behavior
When a click handler is called in this case, the error in the screenshot above is generated for the async function.

Input Code

  • REPL or Repo link if applicable:
const Modal = () => {
const onClose = async () => {
    if (isFormDirty) {
      try {
        await confirm.show('You have unsaved changes. Are you sure you want to close?'); // returns a promise
      } catch (err) {
        return;
      }
    }
  };

return <Header onClose={onClose} />
}



class Header {
 
handleClose = (event) => {
 this.props.onClose();
}

render() {
 <Thingy onClose={this.handleClose} />
}
}

const Thingy = ({ onClose }) => {
<button onClick={onClose}>
}

Expected behavior/code
A clear and concise description of what you expected to happen (or code).

I expect the code to be ok executing the async function.

Babel Configuration (babel.config.js, .babelrc, package.json#babel, cli command, .eslintrc)

  • Filename: babel.config.js
module.exports = function buildPreset(context, options) {
  const env = process.env.BABEL_ENV || process.env.NODE_ENV || 'development';

  const plugins = [
    'babel-plugin-lodash',
    '@babel/plugin-proposal-nullish-coalescing-operator',
    '@babel/plugin-proposal-optional-chaining',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-function-sent',
    '@babel/plugin-proposal-json-strings',
    '@babel/plugin-proposal-numeric-separator',
    '@babel/plugin-proposal-throw-expressions',
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-syntax-import-meta',
    '@babel/plugin-transform-runtime',
  ];

  const presetEnvOptions = {
    loose: true,
    modules: false,
    useBuiltIns: 'usage',
    spec: true,
    corejs: 2,
    ...options,
  };

  const presets = [
    [require('@babel/preset-env'), presetEnvOptions],
    '@babel/preset-react',
    '@babel/preset-typescript',
  ];

  if (env === 'production') {
    plugins.push(
      '@babel/plugin-transform-react-constant-elements',
      '@babel/plugin-transform-react-inline-elements'
    );
  }

  return {
    presets: presets,
    plugins: plugins,
  };
};

Environment

  System:
    OS: macOS 10.15.2
  Binaries:
    Node: 11.12.0 - ~/.nvm/versions/node/v11.12.0/bin/node
    Yarn: 1.21.1 - /usr/local/bin/yarn
    npm: 6.7.0 - ~/.nvm/versions/node/v11.12.0/bin/npm
  npmPackages:
    @babel/core: ^7.7.7 => 7.7.7
    @babel/runtime: ^7.7.7 => 7.7.7
    babel-jest: ^24.0.0 => 24.9.0
    babel-loader: ^8.0.2 => 8.0.6
    babel-plugin-ts-optchain: ../babel-plugin-ts-optchain/ => 1.0.2
    eslint: ^6.8.0 => 6.8.0
    jest: ^24.0.0 => 24.9.0
    webpack: ^4.41.4 => 4.41.4
  • Babel version(s): [e.g. v6.0.0, v7.0.0-beta.34]
  • Node/npm version: [e.g. Node 8/npm 5]
  • OS: [e.g. OSX 10.13.4, Windows 10]
  • Monorepo: [e.g. yes/no/Lerna]
  • How you are using Babel: [e.g. cli, register, loader]

Possible Solution

Additional context/Screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.

@babel-bot

This comment has been minimized.

Copy link
Collaborator

@babel-bot babel-bot commented Dec 26, 2019

Hey @kelly-tock! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite."

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Dec 26, 2019

this seemed relevant from the release notes:

#10839
#9481

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Dec 26, 2019

As a workaround you can disable the spec: true preset-env option. Btw, why do you enable both spec and loose, which do opposite things?

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Dec 27, 2019

Will try this and great question. This was set up this way when I first saw it already.

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 2, 2020

disabling spec: true worked for me. is this an incorrect usage somehow or a bug?

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jan 2, 2020

Using both spec: true and loose: true is an incorrect usage. However, I think that this is a bug anyway: are you able to reproduce it using spec: true with loose disabled?

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 2, 2020

I just tried spec true and loose false, and it still had the same issue. its working with both set to false.

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jan 2, 2020

I have some problems reproducing this. Could you post the full stack trace, and the transpiled version of the handleClose and onClose functions?

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 2, 2020

stack:

backend.js:6 2020-01-02T21:40:43.179Z [WARN] Unhandled rejection (promise:  Promise {<rejected>: TypeError: Cannot instantiate an arrow function
    at _newArrowCheck (webpack-internal:///./node_m…} , reason:  TypeError: Cannot instantiate an arrow function
    at _newArrowCheck (newArrowCheck.js?10a5:3)
    at _callee$ (EditProfileModal.tsx?48ea:88)
    at tryCatch (runtime.js?96cf:45)
    at Generator.invoke [as _invoke] (runtime.js?96cf:271)
    at Generator.prototype.<computed> [as next] (runtime.js?96cf:97)
    at asyncGeneratorStep (asyncToGenerator.js?c973:3)
    at _next (asyncToGenerator.js?c973:25)
    at eval (asyncToGenerator.js?c973:32)
    at new Promise (<anonymous>)
    at eval (asyncToGenerator.js?c973:21) ).
r @ backend.js:6
_loggerFunction @ logger.ts?157d:81
warn @ logger.ts?157d:59
eval @ AjaxActions.ts?3338:87
newArrowCheck.js?10a5:3 Uncaught (in promise) TypeError: Cannot instantiate an arrow function
    at _newArrowCheck (newArrowCheck.js?10a5:3)
    at _callee$ (EditProfileModal.tsx?48ea:88)
    at tryCatch (runtime.js?96cf:45)
    at Generator.invoke [as _invoke] (runtime.js?96cf:271)
    at Generator.prototype.<computed> [as next] (runtime.js?96cf:97)
    at asyncGeneratorStep (asyncToGenerator.js?c973:3)
    at _next (asyncToGenerator.js?c973:25)
    at eval (asyncToGenerator.js?c973:32)
    at new Promise (<anonymous>)
    at eval (asyncToGenerator.js?c973:21)
_newArrowCheck @ newArrowCheck.js?10a5:3
_callee$ @ EditProfileModal.tsx?48ea:88
tryCatch @ runtime.js?96cf:45
invoke @ runtime.js?96cf:271
prototype.<computed> @ runtime.js?96cf:97
asyncGeneratorStep @ asyncToGenerator.js?c973:3
_next @ asyncToGenerator.js?c973:25
eval @ asyncToGenerator.js?c973:32
eval @ asyncToGenerator.js?c973:21
onClose @ EditProfileModal.tsx?48ea:88
handleClose @ Modal.tsx?cb1f:173
eval @ touchUtils.ts?cde9:37
handleClick @ Button.tsx?f345:68
callCallback @ react-dom.development.js?61bb:336
invokeGuardedCallbackDev @ react-dom.development.js?61bb:385
invokeGuardedCallback @ react-dom.development.js?61bb:440
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js?61bb:454
executeDispatch @ react-dom.development.js?61bb:584
executeDispatchesInOrder @ react-dom.development.js?61bb:606
executeDispatchesAndRelease @ react-dom.development.js?61bb:713
executeDispatchesAndReleaseTopLevel @ react-dom.development.js?61bb:722
forEachAccumulated @ react-dom.development.js?61bb:694
runEventsInBatch @ react-dom.development.js?61bb:739
runExtractedPluginEventsInBatch @ react-dom.development.js?61bb:880
handleTopLevel @ react-dom.development.js?61bb:5803
batchedEventUpdates$1 @ react-dom.development.js?61bb:24401
batchedEventUpdates @ react-dom.development.js?61bb:1415
dispatchEventForPluginEventSystem @ react-dom.development.js?61bb:5894
attemptToDispatchEvent @ react-dom.development.js?61bb:6010
dispatchEvent @ react-dom.development.js?61bb:5914
unstable_runWithPriority @ scheduler.development.js?3069:697
runWithPriority$2 @ react-dom.development.js?61bb:12149
discreteUpdates$1 @ react-dom.development.js?61bb:24417
discreteUpdates @ react-dom.development.js?61bb:1438
dispatchDiscreteEvent @ react-dom.development.js?61bb:5881
Show 5 more frames
@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 2, 2020

compiled onClose:

  var onClose =
  /*#__PURE__*/
  function () {
    var _onClose = _asyncToGenerator(
    /*#__PURE__*/
    _regeneratorRuntime.mark(function _callee() {
      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _newArrowCheck(this, _this3);

              if (!isFormDirty) {
                _context.next = 10;
                break;
              }

              _context.prev = 2;
              _context.next = 5;
              return confirm.show('You have unsaved changes. Are you sure you want to close?');

            case 5:
              _context.next = 10;
              break;

            case 7:
              _context.prev = 7;
              _context.t0 = _context["catch"](2);
              return _context.abrupt("return");

            case 10:
              patronActions.closeEditPatronProfileModal();

            case 11:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this, [[2, 7]]);
    }));

    function onClose() {
      return _onClose.apply(this, arguments);
    }

    return onClose;
  }().bind(this);
@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 2, 2020

original code:

const onClose = async () => {
    if (isFormDirty) {
      try {
        await confirm.show('You have unsaved changes. Are you sure you want to close?');
      } catch (err) {
        return;
      }
    }
  };
@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jan 2, 2020

Ok, I'm really confused but interested 🙃
I understand if you don't have time to help me debug this bug since you have worked it around, but...

  1. There is a var _this3 = declaration somewhere. Could you check if it seems to use the same this as the one in the last line (.bind(this)) of the code you posted?
  2. Could you add a debugger; right before the _newArrowCheck in the compiled output, check the values of this and _this3, and check which one is unexpected? They should be the this available in the arrow function, so the one in the context which encloses the arrow itself.
@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 3, 2020

happy to help.

var EditProfileModal = function EditProfileModal(_ref) {
  var _this3 = this,
      _ref2,
      _ref3,
      _ref4,
      _ref5,
      _ref6,
      _ref7;

  _newArrowCheck(this, _this2);

  var onClose =
  /*#__PURE__*/
  function () {
    var _onClose = _asyncToGenerator(
    /*#__PURE__*/
    _regeneratorRuntime.mark(function _callee() {
      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _newArrowCheck(this, _this3);

              if (!isFormDirty) {
                _context.next = 10;
                break;
              }

              _context.prev = 2;
              _context.next = 5;
              return confirm.show('You have unsaved changes. Are you sure you want to close?');

            case 5:
              _context.next = 10;
              break;

            case 7:
              _context.prev = 7;
              _context.t0 = _context["catch"](2);
              return _context.abrupt("return");

            case 10:
              patronActions.closeEditPatronProfileModal();

            case 11:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this, [[2, 7]]);
    }));

    function onClose() {
      return _onClose.apply(this, arguments);
    }

    return onClose;
  }().bind(this);

so it appears to be the this of the function component.

debugger to see the values, where the this is the window and not the this of the function:

image

@kelly-tock

This comment has been minimized.

Copy link
Author

@kelly-tock kelly-tock commented Jan 3, 2020

and this was working previously to the latest round of 7.7.7 updates to the various babel packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.