-
Notifications
You must be signed in to change notification settings - Fork 78
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
Make async/await monkey-patchable #142
Comments
👍 from me. Jumping that native barrier all the time hurts. Hard. |
As a RASP vendor, this is probably one of the best solution right now! |
How would a vendor monkey-patch async-await to add tracing? My only fear is that if we ask for this it might come back and haunt us for years to come. |
@mcollina I guess it's very similar to how it currently works with promises. You change the
It already haunts us with
As said I guess we could make this change in V8 quickly, maybe couple of days. Getting this back-ported to V8 6.2 (for Node 8) might take another day or two. It also depends on whether this is something we can do in Chrome, or whether we have to flag it for Node initially. |
If it's something we would only offer to Node.js (even if initially), I would add the API to monkey-patch in C++ (i.e. |
@hashseed That's kind of exactly what PromiseHooks do, and how we ended up with this problem. |
I am 👍 . |
@bmeurer 👎 unless you have a good answer for this: how will we implement the
Can you elaborate on why PromiseHooks is the root cause of the problem? Isn't it that the JS-native barrier is expensive, or that the spec doesn't allow monkey-patching. I think it is important to understand what the problem is before we agree on a solution, even if the solution is temporary. I also think it is important to have a roadmap for a more long-term solution.
I don't think we should try to solve "the problem for the existing monitoring software", they need to go away from monkey-patching not add more. If /cc @nodejs/async_hooks |
@AndreasMadsen This issue is about keeping existing software working that uses monkey-patching with promises. It's not about replacing
There are multiple issues here. The JS-native barrier is definitely the most important one.
The whole idea of this proposal is to buy us time to think about a long-term solution, while still allowing monitoring software to work properly in a world where
I don't think |
So it is also not about replacing |
Definitely not. I'm more and more convinced that we should have promise hooks as part of the language specification, because there are similar use cases in the browser. My proposal here is to make sure we don't break existing enterprise software while we try to make promise hooks viable. |
Makes sense. 👍 /cc @JiaLiPassion |
I think you misunderstand. What I'm suggesting is that you would only expose the monkey-patchability in V8's C++ API, not in JavaScript. I.e to monkey patch, you would need to use the C++ API. You would still monkey-patch with a JavaScript function, not a C++ callback. |
@hashseed I'm not certain I understand, would that require a C++ addons in APM/RASP agents? |
What I'm suggesting is that V8 does not expose this monkey-patching feature in JavaScript, but offer a C++ API to do so. Node.js can then expose that C++ API to JS in, say, the |
Okay, thanks for the clarification! |
@hashseed The existing software already monkey-patches via global.Promise = MyPromise; or Promise.prototype.then = function() { ... } so all we need to do is to use that in |
That's not the issue. The issue with just "use that" is that this would be unspec'ed behavior. |
Sure, but that's the same with |
All I'm asking is not for V8 to expose this via JS directly as long as it's not part of the spec. Node would be free to expose it via internal modules. Unless you want to run into the situation where pure JS code that is seemingly spec conform only works on Node but not Chrome. Also there is no guarantee it will be accepted at TC39. It's fairly obvious that async hooks are not standard JS and there is no risk of people accidentally trying to make async hook work on Chrome. |
@hashseed Ok, so we should first figure out what's the state regarding the spec? |
How about introducing a |
Also sync up with our language team upfront :) |
I see what you're saying. Yeah that'd do the trick I guess. |
I've been asked to comment here on whether changing the spec is a good idea. Personally I don't think so. We have a long history of syntax being "trustworthy" and not monkey-patchable, e.g. object literal properties not invoking setters on Object.prototype, array/object literal syntax not invoking any monkey-patched Object/Array constructor, and so on. The intent of the async/await spec was to provide similar guarantees, that you'd be guaranteeing no interference between you and the native Promise constructor. I've favored for a long time making all async operations trackable (but not modifiable) via zones, instead of introducing a one-off at the language level for async/await. I think if Node.js/V8 wants to introduce some specific "promise hooks v2" that works similar to what @hashseed describes, that seems fine, as a way of saying that this particular environment has decided to trade the trustworthiness guarantees of the standard for other capabilities. But I'd rather not change the language spec to allow arbitrary monkeypatching. |
@bmeurer do you think Zones would be optimizable in the same way as what is proposed above? |
@bmeck I've been told that you only need to bridge the current gap for @domenic Thanks for your feedback. I share your sentiment that syntax should be trustworthy in general and I'm also not a big fan of monkey-patching usually. I do however also buy the argument about consistency here. |
Ok, so summarizing the discussion here and the discussions I've had with JavaScript folks about this via other channels (especially @ajklein and @domenic), the conclusion is that we cannot just violate the specification here, so essentially we'd need to do exactly what @hashseed suggested and enable the behavior via a special C++ API call. But that also means that existing monkey-patching approaches will still not work out of the box with Potential steps forward:
I hope that makes sense, and thanks to everyone who helped to enlighten me on this topic. |
Let's follow up on |
Chiming in late here, but the conclusion seems reasonable to me. It was a deliberate design decision of TC39 to not allow monkey patching here, and I wouldn't expect it to be reversed lightly. It may also be complex to make the monkey-patched Promise methods interact well with devtools (something transpiled async/await simply didn't try to do). |
A very good point. Let's make exception prediction not even more complicated :D |
I'd like to bring up an idea from @gsathya here, which could help to make progress short-/middle-term while we're resolving the performance problems with
async_hooks
, specifically with promise hooks. As mentioned in nodejs/benchmarking#181 (comment) just enablingasync_hooks
on a simple hapi v17 server already causes a 30% performance drop, which is way below what's acceptable.Given the discussions I've had with some many people from the Node community about this since NodeConfEU, I see several ways to make progress on this, but no easy path forward. We might need to make some difficult decisions in what hooks we want to support for promises and the trade-offs for performance we're willing to make. Unfortunately, as pointed out by @ofrobots and others, we're kind of in a hurry now, since
async
/await
is a thing already and monkey-patching doesn't work there because of the way the specification is written. So essentially vendors are forced to useasync_hooks
now for their monitoring tools, even though it's not ready, and might even undergo breaking changes while it's in EXPERIMENTAL.So in order to buy us some time, and maybe even enable things like
zone.js
in the browser, we could instead change the specification to essentially makeawait
monkey-patchable. That means we need to change the places in the specification that allocate the implicit promises forasync
andawait
,and also make
await
lookup"then"
on the promise instead of hardcoding the internal operation.Both of which sounds somewhat straight-forward, and V8 can still optimize the common case (no prototype mutation) as it does today, i.e. skip the
"then"
lookup on native promises if we know that no one touchedPromise.prototype.then
. I think this change could even be back-ported to Node 8. I also think that making such a change wouldn't break web compatibility, although it makesawait
monkey-patchable in some sense. It would probably still take a while to change the spec, but Node/V8 wouldn't need to wait for that to reach stage 4.What do you folks think?
cc @nodejs/collaborators @jasnell @ofrobots @littledan @gsathya @caitp @hashseed @AndreasMadsen @mathiasbynens
The text was updated successfully, but these errors were encountered: