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

Derived constructors should not be allowed to return primitives #13571

Closed
wants to merge 2 commits into from

Conversation

dhrubesh
Copy link
Contributor

@dhrubesh dhrubesh commented Jul 19, 2021

Q                       A
Fixed Issues? Fixes #13566
Patch: Bug Fix?
Major: Breaking Change? No
Minor: New Feature? 👍
Tests Added + Pass? 👍
Documentation PR Link
Any Dependency Changes?
License MIT

Derived constructor won't be allowed to return primitive values

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jul 19, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 6f975ee:

Sandbox Source
babel-repl-custom-plugin Configuration
babel-plugin-multi-config Configuration

@babel-bot
Copy link
Collaborator

babel-bot commented Jul 19, 2021

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/47406/

Copy link
Member

@fedeci fedeci left a comment

Choose a reason for hiding this comment

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

Looks fine to me.

@fedeci fedeci added PR: Bug Fix 🐛 A type of pull request used for our changelog categories Spec: Classes labels Jul 19, 2021
@dhrubesh
Copy link
Contributor Author

Hi @fedeci thanks for your comments, I've resolved them, please consider re-reviewing it. I'm not sure why my prettier on my local isn't running, I'll have to check that out.

@dhrubesh dhrubesh requested a review from fedeci July 19, 2021 13:18
@fedeci
Copy link
Member

fedeci commented Jul 19, 2021

It is not running because those are strings and not "real lines of code". If I am not wrong we started moving the helpers to individual files so that eslint and prettier could work.

if (typeof call === "object" || typeof call === "function") {
return call;
} else {
throw new TypeError("Invalid attempt to return primitive value");
Copy link
Member

Choose a reason for hiding this comment

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

Thoughts on matching v8's error?

Suggested change
throw new TypeError("Invalid attempt to return primitive value");
throw new TypeError("Derived constructors may only return object or undefined");

if (call) {
if (typeof call === "object" || typeof call === "function") {
return call;
} else {
Copy link
Member

Choose a reason for hiding this comment

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

This logic doesn't work if the constructor returns, for example, 0 or null (can you add a test for a falsy value?).

It should be something like

if (call && (typeof call === "object" || typeof call === "function")) {
  return call;
} else if (call !== void 0) {
  throw new TypeError("...");
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Or

if (call !== void 0) {
  if (typeof call === "object" || typeof call === "function") {
    return call;
  } else {
    // throw errors
  }
}

Copy link
Member

Choose a reason for hiding this comment

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

My version is 3 bytes shorter when using terser 😛

function f(o){if(o&&("object"==typeof o||"function"==typeof o))return o;if(void 0!==o)throw new TypeError("...")}
function g(o){if(void 0!==o){if("object"==typeof o||"function"==typeof o)return o;throw new TypeError("...")}}

Also, I think yours incorrectly allows returning null.

This comment was marked as off-topic.

Copy link

Choose a reason for hiding this comment

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

but use of 'typeof' is a bad idea and kill perf.

Copy link
Member

Choose a reason for hiding this comment

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

What do you suggest to use instead?

Copy link

@KFlash KFlash Jul 22, 2021

Choose a reason for hiding this comment

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

Well. 'typeof obj === 'object';' is almost ~50% slower than other 'typeof'. And 'typeof number' return NaN even if it's not an number - in some cases.

There exist 2 popular utility libraries that has an optimized check for this.

Personally I would have used some kind of meta data and bitwise masks

Copy link
Member

Choose a reason for hiding this comment

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

There exist 2 popular utility libraries that has an optimized check for this.

I only found is-object (which still uses typeof === "object") and lodash.isObject (which also uses typeof and checks if it's "object"). Why would typeof === "object" be slower than the other types?

Personally I would have used some kind of meta data and bitwise masks

o can be any possible JS value present in the JS code of our users, we cannot use bitwise mask

Copy link

Choose a reason for hiding this comment

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

I forgot the history behind this, but AngularJS had some good checks in their earlier versions. 1x of their library. I think they checked against the constructor. Also Google had a library a few years back - forgot the name - with fast checks.

@nicolo-ribaudo nicolo-ribaudo changed the title Fix Derived constructors should not be allowed to return primitive va… Derived constructors should not be allowed to return primitives Jul 19, 2021
@nicolo-ribaudo nicolo-ribaudo added PR: Spec Compliance 👓 A type of pull request used for our changelog categories and removed PR: Bug Fix 🐛 A type of pull request used for our changelog categories labels Jul 19, 2021
if (call) {
if (typeof call === "object" || typeof call === "function") {
return call;
} else {
Copy link

Choose a reason for hiding this comment

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

This 'else' is not needed. You already return in the line above.

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Aug 9, 2021

@dhrubesh Thanks! I merged this manually as 23d4f8c. I couldn't merge it using the GitHub UI because you made your changes on your fork's main branch rather than creating a new branch, so GitHub didn't let me update this PR to handle the review comments.

@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 9, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue PR: Spec Compliance 👓 A type of pull request used for our changelog categories Spec: Classes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Derived constructors should not be allowed to return primitive values
8 participants