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

Extending from native classes #17042

Closed
bastimeyer opened this issue Oct 4, 2018 · 19 comments
Closed

Extending from native classes #17042

bastimeyer opened this issue Oct 4, 2018 · 19 comments

Comments

@bastimeyer
Copy link

Follow up of
ember-decorators/ember-decorators#115 (comment)
and new issue here, as requested by @rwjblue

Extending a native class with .extend which itself is extending EmberObject is throwing a

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

The motivation of this is being able to use native classes and mixins, like this:

class Foo extends EmberObject {
  // ...
}

const Bar = Foo.extend({
  // ...
});

class Baz extends Bar {
  // ...
}

See this ember-twiddle:
https://canary.ember-twiddle.com/b365ecfbc29444455d082cf1b295156b?openFiles=tests.foo-test.js%2C

@boris-petrov
Copy link
Contributor

Is this the same as https://discuss.emberjs.com/t/ember-3-2-ember-decorators-subclassing-bug/15380? We also hit that issue.

@rwjblue
Copy link
Member

rwjblue commented Oct 16, 2018

Yes, it is the same issue.

@boris-petrov
Copy link
Contributor

@rwjblue - is there any timeframe on fixing this? Do you have any idea where the problem might be? Because we've been hitting this a lot when using native classes in TypeScript (and using the language with .extend sucks a lot) and I wonder whether to postpone migrating to TypeScript more of our code.

@krisselden
Copy link
Contributor

If you create a patched version extend in your app so that babel compiles it according to your App settings.

import EmberObject from "@ember/object";
EmberObject.extend = function (...args) {
  class Class extends this;
  Class.reopen(...args);
  return Class;
}
export default EmberObject;

then import from that in your app it should workaround the problem until we publish the es so that ember-cli compiles ember with the same babel settings.

@boris-petrov
Copy link
Contributor

boris-petrov commented Dec 6, 2018

@krisselden - thank you for the suggested workaround! For any future readers, the class Class extends this; line should actually say class Class extends this {} instead. :)

@rwjblue
Copy link
Member

rwjblue commented Dec 7, 2018

This is fixed in the current release, so I'm going to go ahead and close...

@rwjblue rwjblue closed this as completed Dec 7, 2018
@boris-petrov
Copy link
Contributor

@rwjblue - this is still not fixed for me on 3.6.1. Getting the same error as in the first post of this issue. I think this should be reopened. Or am I missing something?

@rwjblue
Copy link
Member

rwjblue commented Dec 21, 2018

Happy to reopen with a demo repo

@bastimeyer
Copy link
Author

Just in case anybody is wondering about the ember-twiddle tests which I had posted in the OP, those are wrong... I had incorrectly mixed the properties on the class prototype (.extend) and class instance (native class properties). 3.6.1 is working fine, though.

@boris-petrov
Copy link
Contributor

@rwjblue - here is a reproduction. It took me a while but it was quite simple in the end - it's because of the targets.js file.

@boris-petrov
Copy link
Contributor

@rwjblue - ping. :) Did you manage to take a look at the reproduction? Let's reopen the issue so we don't forget it. :)

@rwjblue
Copy link
Member

rwjblue commented Dec 27, 2018

Yes, I did but I’m not sure we can/should reopen. Sorry, I’m out with the family at the moment but will try to explain once I’m back at a keyboard...

@boris-petrov
Copy link
Contributor

@rwjblue - I don't want to be annoying, but could you please explain why you don't think this is a bug? :) Thanks!

@boris-petrov
Copy link
Contributor

@rwjblue - after updating @babel packages from 7.3.4 to 7.4.0 this started happening again. Nothing else has changed in my project. Should I try to create a reproduction or is this a known problem?

Also, if you could explain why adding edge to targets.js causes the same problem and why you consider this to not be a bug?

@boris-petrov
Copy link
Contributor

I've pushed a commit in my reproduction repo that showcases the latest problem. Both issues can be seen in it - edge in targets.js causing TypeError: Class constructor Model cannot be invoked without 'new' and updating @babel packages to 7.4.0 causing the same error. Should I open a new issue for this?

@Krzyrok
Copy link

Krzyrok commented Apr 17, 2019

I have the same issue after upgrade of dependencies in my repo. Upgrade of direct dependencies was OK but after removing yarn.lock and generating new one - minor upgrades took place in indirect dependencies (i.e. dependencies of dependencies). E.g.
@babel/preset-env was upgraded from 7.3.1 to 7.4.3 (I don't if this is a reason - this is my guess). I use also TS and ember-cli-typescript in the newest version

Error which I have:
Error while processing route: index Class constructor XXX cannot be invoked without 'new' TypeError: Class constructor XXX cannot be invoked without 'new'. It seems that problem is with generated code for CoreObject. See details below

Details with generated code AFTER upgrade

Part of the stack trace (from generated code):

    CoreObject.extend = function extend() {
      var Class =
      /*#__PURE__*/
      function (_this) {
        (0, _emberBabel.inheritsLoose)(Class, _this);

        function Class() {
          // !!!!!!!!!!!!!!!!!!!!!!
          return _this.apply(this, arguments) || this; // THIS LINE EXPLODED
          // !!!!!!!!!!!!!!!!!!!!!!
        }

        return Class;
      }(this);

      _reopen.apply(Class.PrototypeMixin, arguments);

      return Class;
    }

and generated Class definiton which extends XXX class (_base below). These definitions below are the same BEFORE and AFTER upgrade

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.ClassWhichExtendsXXX = void 0;

  class ClassWhichExtendsXXX extends _base.default.extend({
    // some computed properties
  }) {}

  _exports.ClassWhichExtendsXXX = ClassWhichExtendsXXX;

generated XXX class (_base above):

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = void 0;

  class XXX extends Ember.Service.extend({
    init() {
      this._super(...arguments);
    },
    // ...
  }) {}


  _exports.default = XXX;

In the code we crate new instance of ClassWhichExtendsXXX with new (new ClassWhichExtendsXXX()) keywords (I tried also .create() from ember object: ClassWhichExtendsXXX.create()`.

Details with generated code BEFORE upgrade Only difference is in vendor (CoreObject): ``` static extend() { let Class = class extends this {}; reopen.apply(Class.PrototypeMixin, arguments); return Class; } ```

@boris-petrov
Copy link
Contributor

@Krzyrok - I opened another issue for that. They fixed it, we're waiting for the new version to fix it. :)

@Krzyrok
Copy link

Krzyrok commented Apr 17, 2019

Great! Thanks for link :)

@Mifrill
Copy link

Mifrill commented Aug 2, 2021

For surfers who face this bug on Ember upgrade 3.1 -> 3.2, exactly as mentioned here:
#17042 (comment)
For me it was solved this way:

// ember-cli-build.js

let app = new EmberApp(defaults, {
	// ...

    babel: {
      include: [
        'transform-classes',
      ],
    },
	// ...	

source:
https://stackoverflow.com/questions/36577683/babel-error-class-constructor-foo-cannot-be-invoked-without-new

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

No branches or pull requests

7 participants