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

Uncaught TypeError: Class constructor [extended class] cannot be invoked without 'new' #839

Closed
rokyed opened this issue Feb 17, 2018 · 25 comments
Labels

Comments

@rokyed
Copy link

rokyed commented Feb 17, 2018

Choose one: is this a 🐛 bug report or 🙋 feature request?

🎛 Configuration (.babelrc, package.json, cli command)

// .babelrc
{
  "presets" : ["es2015-ie"]
}

//.postcssrc
{
	"modules": true,
	"plugins": {
		"autoprefixer": {
			"grid": true
		}
	}
}
//package.json
{
 "name": "",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "start": "./node_modules/.bin/parcel --no-cache ./src/index.html --out-dir ./dist",
  "build": "./node_modules/.bin/parcel build --no-minify ./src/index.html --out-dir ./dist"
 },
 "author": "",
 "license": "",
 "dependencies": {
  "acorn": "^5.4.1",
  "babel-preset-es2015-ie": "^6.7.0",
  "mobile-detect": "^1.4.1",
  "node-sass": "^4.7.2",
  "parcel-bundler": "^1.6.1",
  "postcss-modules": "^1.1.0",
  "webpack": "^3.1.0",
  "wrench-set": "^1.0.6"
 }
}

🤔 Expected Behavior

It should just create the class and do the magic of Element. (wrench-set was created by me, and tested in another project, which works perfectly, using parcel 1.5.1)

😯 Current Behavior

it shoots error with class constructor cannot be invoked without new for the super()

Uncaught TypeError: Class constructor Element cannot be invoked without 'new'
at new Viewport (viewport.js:5)
at Object.require.4../index.scss (index.js:4)
at newRequire (3127ebea6fd59e02267b4119b100f294.js:42)
at require.14 (3127ebea6fd59e02267b4119b100f294.js:69)

💁 Possible Solution

the hacky way 😄
revert to 1.5.1 in order to be able to successfully compile the code

🔦 Context

💻 Code Sample

// main.js
import style from './index.scss'
import Viewport from './viewport.js'

const VIEWPORT = new Viewport({
	renderTo: document.body
})

// viewport.js
import {Element} from 'wrench-set'
import style from './viewport.scss'

export default class Viewport extends Element {
	constructor (config) {
		super({
			renderTo: config.renderTo,
			innerHTML: 'hi',
			className: `${style.viewport}`
		})
	}
}

🌍 Your Environment

Software Version(s)
Parcel 1.6.1
Node 8.9.3
npm/Yarn 5.5.1
Operating System Linux Mint 18
@mthadley
Copy link

mthadley commented Mar 2, 2018

I had a similar issue. I was extending a class exported from a node module. Upon inspecting the compiled code, I noticed that my class was transpiled into an ES5 class, but the code coming from the node modules was not being transpiled (it was still defined with the class keyword, etc).

So it was essentially an ES5 class extending an ES6 class, and that seems to cause this error. I haven't managed to fix it yet, but it seems like one reason might be that Parcel isn't compiling the module.

Here's the module in question.. Maybe it has something in common with wrench-set?

@rokyed
Copy link
Author

rokyed commented Mar 3, 2018

@mthadley about wrench-set, yes, it's not minified. It's a module that I've built, it's super simple, it's based on ES6, but I don't think that should be the problem, when you are packaging something, you shouldn't expect that modules are already packaged, that's my understanding of a package. I think that it should be compiled/baked into your code, from the code that was provided.

@rokyed
Copy link
Author

rokyed commented Mar 15, 2018

After further investigation, it seems that babel won't compile node_modules, in webpack there are ways to mitigate this trough webpack.

attente added a commit to horizon-games/eth-state-channels-research that referenced this issue Apr 4, 2018
@FishOrBear
Copy link

I have encountered the same problem using webpack+typescript.

I use @ContextMenuTarget

@danmarshall
Copy link
Contributor

danmarshall commented Jun 9, 2018

@mthadley describes this bug succinctly:

an ES5 class extending an ES6 class, and that seems to cause this error.

Parcel has compiled some of my classes to functions. 🤔
@FishOrBear do you have a workaround?

I'm getting this error in version 1.8.1

@danmarshall
Copy link
Contributor

danmarshall commented Jun 9, 2018

I have a simple repro:

test.html:

<html>
<head>
    <script>
        //some other library
        class Animal {
            move(distance) {
                console.log(`Animal moved ${distance}`);
            }
        }
    </script>
</head>
<body>
    <script src="test.js"></script>
</body>
</html>

test.js:

class Horse extends Animal {
    move(distance) {
        console.log(`Horse galloped ${distance}`);
    }
}

new Animal().move(7);
new Horse().move(7);

Output before Parcel:

Animal moved 7
Horse galloped 7

Output after Parcel:

Animal moved 7
test.84371532.js:2 Uncaught TypeError: Class constructor Animal cannot be invoked without 'new'
    at new i (test.84371532.js:2)
    at Object.parcelRequire.4 (test.84371532.js:2)
    at i (test.84371532.js:1)
    at parcelRequire.4 (test.84371532.js:1)
    at test.84371532.js:1
i @ test.84371532.js:2
parcelRequire.4 @ test.84371532.js:2
i @ test.84371532.js:1
parcelRequire.4 @ test.84371532.js:1
(anonymous) @ test.84371532.js:1

@danmarshall
Copy link
Contributor

danmarshall commented Jun 9, 2018

Here is the compiled Horse which is now a function instead of a class:

var Horse = function (_Animal) {
    _inherits(Horse, _Animal);

    function Horse() {
        _classCallCheck(this, Horse);

        return _possibleConstructorReturn(this, (Horse.__proto__ || Object.getPrototypeOf(Horse)).apply(this, arguments));
    }

    _createClass(Horse, [{
        key: "move",
        value: function move(distance) {
            console.log("Horse galloped " + distance);
        }
    }]);

    return Horse;
}(Animal);

@alber70g
Copy link

alber70g commented Jul 23, 2018

Any news on a fix? I'm using LitElement and creating mixins for classes but I'm not able to compile with Parcel. I'm also using Typescript.

[edit] Example here https://codesandbox.io/s/0pl314l77l

@arnm
Copy link

arnm commented Aug 22, 2018

bump...

@Nviano
Copy link

Nviano commented Sep 15, 2018

bump

@jamesgpearce
Copy link

If you manage the dependent module's package.json, you might be able to avoid this by using "source": true

@alber70g
Copy link

alber70g commented Sep 17, 2018

Any news on a fix? I'm using LitElement and creating mixins for classes but I'm not able to compile with Parcel. I'm also using Typescript.

I got a fix to get it work with Parcel. This makes it to not remove the class syntax. But it'll hurt older browsers:

Add this to your package.json and Parcel will pick it up as babel config.

"browserslist": [
    "last 1 chrome versions"
  ]

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Sep 17, 2018

Adding babel-polyfill would probably fix this.

It's probably due to parcel compiling using babel to correspond to specified browserlist as @alber70g pointed out already

@prasannavl
Copy link

prasannavl commented Nov 12, 2018

I think this real issue is due to the fact that parcel uses pkg.module in package.json incorrectly. A lot of the modern libraries today providing both cjs and es6, set main to cjs versions, while module will be set to es6 versions.

The correct behavior should be, when an es6 module is encountered, and the compile target is es5 and not es6, parcel should compile these into es5, despite them being node_modules.

But that rises new questions: who should do this? Can parcel set these babel configs automatically, if so how does parcel know if your compile target is es6, or es5? Should that be identified from babel config (can they even be reliably)? This also walks you down the rabbit hole of should modules be compiled with the same config as your project? Now, that could have unforeseen side-effects. (Relevant: #13)

If you're not bound by legacy browsers, I'd just set babel to ignore es6 class transformations and call it a day.

The other issue is extending ES6 native classes like HTMLElement, HTMLDivElement, etc with ES5. The only right way to do this is to use Object/Reflect.setPrototypeOf, etc, or simply use the above solution where you just stick to ES6 classes.

Long story short - ES6.

@jantimon
Copy link

jantimon commented Nov 12, 2018

@prasannavl the best practice is to transpile es6 as there are so many different es6 stages:

So even module should be es5:
https://github.com/rollup/rollup/wiki/pkg.module#wait-it-just-means-import-and-export--not-other-future-javascript-features

@prasannavl
Copy link

prasannavl commented Nov 12, 2018

@jantimon - Err, almost all modern platforms support a most of the commonly used features today, but not import and export. So, most modern libraries, take the polymer's lit-html, for instance, just completely bids good-bye to es5.

And since we're specifically talking about es6 classes here, it's supported everywhere today unless you're concerned with legacy. The point being, there are and probably will be libraries that forgo es5, and just apply module to use es6. The only way to do it correctly moving forward would be to handle this case.

PS: The rollup link simply tells you that you need other features to be transpiled -- one might choose to just transpile their code to the lowest es6 stages with classes. That's still completely valid as far module field is concerned.

@timdeng2324
Copy link

@prasannavl what should the babelrc target be for ES6? @alber70g's latest 1 chrome version worked for me, but i want to make sure i have maximum browser compatibility. right now i'm just using @babel/preset-env.

@prasannavl
Copy link

@timdeng2324 - perhaps, try adding @babel/plugin-transform-classes to exclude, and see if that does the trick? (haven't really tested it myself)

@Mouvedia
Copy link

Mouvedia commented May 1, 2019

Is there a fix that doesn't involve using browserslist?

@leoseccia
Copy link

I had this problem too and after spending a day messing around with babel, I fixed it by changing the way I imported these (and don't use babel at all):

import Inline from 'quill/blots/Inline';
import ReactQuill from 'react-quill';

to:

import ReactQuill, {Quill} from 'react-quill';
let Inline = Quill.import('blots/inline');

@stale
Copy link

stale bot commented Jan 17, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 30 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Stale Inactive issues label Jan 17, 2020
@parcel-bundler parcel-bundler deleted a comment from Mouvedia Jan 17, 2020
@DeMoorJasper
Copy link
Member

This will get fixed in Parcel 2

@Mouvedia
Copy link

@DeMoorJasper last alpha release was in November of last year.

Do you have an idea of when Parcel will be stable?
Is it already fixed in the alpha?

@DeMoorJasper
Copy link
Member

@Mouvedia we currently do not have a timeline on when a stable Parcel 2 version will be out, we are however working on a list of features/bugfixes that are required to get it to stable so we can focus on getting it out asap without focusing too much on improvements and features we can add-on afterwards.

I think it should be fixed in the current alpha, not entirely sure.

@marlonicus
Copy link

marlonicus commented May 21, 2020

To anyone arriving here having this problem with TypeScript and Parcel, you might need to add the following to a tsconfig.json in your project root to fix the issue:

{
  "compilerOptions": {
    "target": "esnext"
  }
}

And be sure to run parcel again with --no-cache for it to kick in 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

16 participants