-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
Don't use userobject.call/userobject.apply #12956
Comments
@mscdex this is not timers specific: this applies across many of node's libs (timers included). another example (from util.js): util = require("util");
a = function() {};
b = function() { return "b" }
a[util.inspect.custom] = b
b.call = "some value"
a Output:
and also in sameish area: util = require("util");
a = function() {};
a[util.inspect.custom] = function() { return "a" };
Object.defineProperty(a, "constructor", {get: function() {throw Error()}}) Output:
|
@daurnimator I believe that in both cases
Node implements JavaScript (more precisely ECMAscript), and like many other programing languages, it allows you to make mistakes, from never ending loops, to division by 0, and yes, even manipulating the internal mechanics to throw errors. I'm going to close this issue, since I didn't find a deviation from the standards. If you find such a deviation, feel free to reopen, and give us an example so we can do better... |
When the standard says "Invoke the Function" it doesn't mean to use
Try printing/inspecting
IMO internal mechanics throwing errors is an entirely different category to infinite loops and divide by zero.
Please see above: |
@daurnimator note that in all cases IMHO node did what you asked it to do, and most importantly did not crash. It provided you with a proper Error with a stack trace. We can argue the trade-offs in the implementation of the 'util' module (i.e. printing/inspecting) it is a |
I'm going to re-open this. I think @daurnimator has a point. In particular, the first sample code provided runs as expected in the browser (tested on Chrome) and I would think we'd want to emulate that robustness. |
Please note that this issue can be found all across the node code-base. I've mentioned
|
Also as you might know node welcomes all contributions. If you feel you can help us improve the |
@Trott IMHO it's not a matter of robustness, since there was not crash, nor any non-deterministic behaviour. I obviously welcome the re-open If you feel we're deviating from the standard. |
Just tried this: b = Object.create(Function)
setTimeout(b, 0) Chrome:Uncaught TypeError: Function.prototype.toString is not generic
at Function.toString (<anonymous>)
at <anonymous>:1:1
(anonymous) @ VM271:1 nodeTypeError: "callback" argument must be a function
at exports.setTimeout (timers.js:348:11)
at repl:1:1
at REPLServer.defaultEval (repl.js:339:29)
at bound (domain.js:280:14)
at REPLServer.onLine (repl.js:536:10)
at emitOne (events.js:101:20)
at REPLServer.emit (events.js:191:7)
at REPLServer.Interface._onLine (readline.js:241:10)
at REPLServer.Interface._line (readline.js:590:8)
at REPLServer.Interface._ttyWrite (readline.js:869:14) IMHO our Error is better. You win some, you lose some... |
@refack No that is standard behaviour. |
@daurnimator Ok so my reference to the WhatWG All I'm saying it's a matter of trade offs. I'll finish with an open question a['b'] = 1
1 === a.b On the other hand a instanceof Object === false Working with a duck-typed language is subtle... |
a = 5
a === 5
typeof a === 'number'
a instanceof Number === false Yes |
Addressing just the timers part, not util or anything else: #12960 |
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. Refs: nodejs#12956
@daurnimator I followed up or your idea in #12981, you're invited to review. |
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. PR-URL: nodejs#12960 Ref: nodejs#12956 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. PR-URL: nodejs#12960 Ref: nodejs#12956 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. PR-URL: #12960 Ref: #12956 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. PR-URL: #12960 Ref: #12956 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Instead of callback bound apply, instead use the standard Reflect.apply. This is both safer and appears to offer a slight performance benefit. PR-URL: #17456 Refs: #12956 Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Instead of callback bound apply, instead use the standard Reflect.apply. This is both safer and appears to offer a slight performance benefit. PR-URL: nodejs#17456 Refs: nodejs#12956 Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Instead of callback bound apply, instead use the standard Reflect.apply. This is both safer and appears to offer a slight performance benefit. Backport-PR-URL: #18487 PR-URL: #17456 Refs: #12956 Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
@daurnimator In your estimation, should this remain open? If so, I imagine we should catalog all the instances and make a tracking issue so that we know when it will be closable. Although I wonder how long that list would be... |
It appears we've fixed the most egregious cases (just see all the commits linked to this issue!). However I'm sure there's still a few we've missed. I think we should close this for now; but perhaps it's something that can be added to code-review guidelines? i.e. "watch out for new code introduced that uses |
@daurnimator progress is slowly being made, take a look at #17434, #18795 and #18773 |
Internally node shouldn't rely on user provided functions/objects having 'normal' values.
e.g.
Output:
For this example, node's timers.js should be using
Function.prototype.call
orReflect.apply
The text was updated successfully, but these errors were encountered: