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

[BUGFIX release] Fix Ember.Error inheritance #15522

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 9 additions & 16 deletions packages/ember-debug/lib/error.js
@@ -1,15 +1,6 @@
/**
@module @ember/error
*/
function ExtendBuiltin(klass) {
function ExtendableBuiltin() {
klass.apply(this, arguments);
}

ExtendableBuiltin.prototype = Object.create(klass.prototype);
ExtendableBuiltin.prototype.constructor = ExtendableBuiltin;
return ExtendableBuiltin;
}

/**
A subclass of the JavaScript Error object for use in Ember.
Expand All @@ -19,15 +10,12 @@ function ExtendBuiltin(klass) {
@constructor
@public
*/
export default class EmberError extends ExtendBuiltin(Error) {
constructor(message) {
super();

if (!(this instanceof EmberError)) {
return new EmberError(message);
}
export default EmberError;
function EmberError(message, code) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dumb question, but why make this a function instead of using the fancy ES6 classes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EmberError unfortunately supports being invoked without using new. This ends up being a less hacky solution. We should deprecate that, so we can eventually switch over entirely though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Thank you for taking a moment to respond to my question.

if (this instanceof EmberError) {
let error = Error.call(this, message, code);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: In V8, using super() would give you the benefit of omitting all frames up to and including the EmberError constructor (which is what I believe Error.captureStackTrace was used for). ES6 Error subclasses are basically the better Error.captureStackTrace. Copying error properties below would also be unnecessary.

I'm not sure how other browsers behave though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't actually using real super (getting transpiled) also we still support an unfortunate scenario calling the constructor without new. Which ES6 classes don't support. We will need to deprecate that first, then remove in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll open another PR that deprecated the call constructor behavior so by the best LTS we can drop


let error = Error.call(this, message);
this.stack = error.stack;
this.description = error.description;
this.fileName = error.fileName;
Expand All @@ -36,5 +24,10 @@ export default class EmberError extends ExtendBuiltin(Error) {
this.name = error.name;
this.number = error.number;
this.code = error.code;
} else {
return new EmberError(message, code);
}
}

EmberError.prototype = Object.create(Error.prototype);
EmberError.constructor = EmberError;