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

Native classes cannot be extended by transpiled classes #9367

Closed
vzaidman opened this issue Jan 19, 2019 · 10 comments
Closed

Native classes cannot be extended by transpiled classes #9367

vzaidman opened this issue Jan 19, 2019 · 10 comments
Labels
i: bug i: needs triage outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@vzaidman
Copy link

vzaidman commented Jan 19, 2019

Bug Report

Current Behavior
I'm building the library @welldone-software/why-did-you-render where I transpile the code:

class WDYRPatchedClassComponent extends ClassComponent{
  ...
}

Where ClassComponent is provided by the user.

For the code transpiling I use @babel/preset-env with default target which means plugins are used including babel-plugin-transform-classes.

If a user provides a native class in case his app is transpiled for latest browsers without babel-plugin-transform-classes, the applicaiton fails with the error:

TypeError: Class constructor model cannot be invoked without 'new'

Because transpiled classes are failing to extend native classes.

Expected behavior/code
Transpiled classes supports native classes extension.

Babel Config File (Simplified)

module.exports = function(api){
  const presets = [
    ['@babel/preset-env', {
      modules: false
    }],
    '@babel/preset-react'
  ]
  const plugins = [
    'babel-plugin-lodash',
  ]
  return {presets, plugins}
}

Environment

    "@babel/cli": "7.2.3",
    "@babel/core": "7.2.2",
    "@babel/preset-env": "7.2.3",
    "@babel/preset-react": "7.0.0"
  • Node/npm version: v10.15.0, v6.4.1
  • OS: Windows 10
  • Monorepo: no
  • How you are using Babel: 'rollup'

Possible Solution
Make the plugin check if the passed class to extend is a native one and if it is, use the native extends code or an equivalent one.

Workarounds
For now, to help users who encounter this problem, I added 3 endpoints where classes are not transpiled:

  "main-no-classes-transpile": "dist/no-classes-transpile/cjs/whyDidYouRender.min.js",
  "module-no-classes-transpile": "dist/no-classes-transpile/esm/whyDidYouRender.min.js",
  "browser-no-classes-transpile": "dist/no-classes-transpile/umd/whyDidYouRender.min.js"

by excluding the babel-plugin-transform-classes plugin:

    ['@babel/preset-env', {
      modules: false,
      exclude: ['babel-plugin-transform-classes']
    }],

Other Relevant Suggestions
If we had an improved error message when calling a class as a function, this error would of been much easier to debug. The error Class constructor model cannot be invoked without 'new' is very unclear: #8948

Related Issues
#4269
#6299
#7022
#7221
#8894
#9280

@babel-bot
Copy link
Collaborator

Hey @vzaidman! 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.

@vzaidman
Copy link
Author

vzaidman commented Jan 19, 2019

I'll be glad to fix it with a PR of my own. Can I have a suggestion on how to do it, please?

@nicolo-ribaudo
Copy link
Member

Actually there already is #8656!

@vzaidman
Copy link
Author

oh wow thanks

@mschipperheyn
Copy link

@nicolo-ribaudo the PR is no longer compatible with master

@rijnhard
Copy link

Keep running into this bug as well

@scaret
Copy link

scaret commented Jun 10, 2021

Thanks! My early version of preset-env:
"exclude": ["babel-plugin-transform-es2015-classes"],

@nicolo-ribaudo
Copy link
Member

Fixed by #8656

@jksmithing
Copy link

@nicolo-ribaudo it looks like this is still an issue when loose mode is enabled, is that expected?

Starting with the output from this repl, if I replace var Super = function Super() {} with class Super {} then I get the error:

Uncaught TypeError: Class constructor Super cannot be invoked without 'new'

@nicolo-ribaudo
Copy link
Member

It's because you are using loose mode. You can disable loose mode, and granularly enable the assumptions you need (but not superIsCallableConstructor).

@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Nov 10, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
i: bug i: needs triage outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

7 participants