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

lib: move queueMicrotask to stable #25594

Merged
merged 1 commit into from
Mar 8, 2019

Conversation

devsnek
Copy link
Member

@devsnek devsnek commented Jan 20, 2019

IIRC the critera for stable was better support from other platforms, which has since been fulfilled by safari and chrome.

Closes #25592

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • documentation is changed or added
  • commit message follows commit guidelines

@devsnek devsnek added the experimental Issues and PRs related to experimental features. label Jan 20, 2019
@devsnek devsnek requested a review from a team January 20, 2019 16:29
@devsnek devsnek force-pushed the queuemicrotask-stable branch 2 times, most recently from 49f907d to 156cd59 Compare January 20, 2019 16:54
@mcollina
Copy link
Member

Is this compatible with the other implementation? If so, have we got tests in wpt?

@devsnek
Copy link
Member Author

devsnek commented Jan 20, 2019

Looks like this exists: https://github.com/web-platform-tests/wpt/tree/master/html/webappapis/microtask-queuing

@joyeecheung how should i go about integrating the tests here?

@joyeecheung
Copy link
Member

joyeecheung commented Jan 21, 2019

@devsnek The only test in the WPT that can be run in Node without modification is https://github.com/web-platform-tests/wpt/blob/master/html/webappapis/microtask-queuing/queue-microtask.any.js (the other two either needs document.createElement or window.addEventListener)so I would not mind if you just port it by hand, but you can also follow the instructions in https://github.com/nodejs/node/tree/master/test/wpt#how-to-add-tests-for-a-new-module (though I am not sure if the current tooling work on tests under html/webappapis as they do not support non-top-level directories yet, I could work on that though)

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

LGTM

@Trott
Copy link
Member

Trott commented Jan 21, 2019

Is test/known_issues/test-vm-timeout-escape-queuemicrotask.js a queuemicrotask bug, a vm timeout bug, or a V8 bug? I'm guessing that it's not a queuemicrotask bug, and therefore not worth holding this up over, but leaving this comment in case I'm wrong.

@addaleax
Copy link
Member

@Trott It’s a vm “bug” that requires currently not existing V8 APIs to be fixed. Tbh, I don’t think it will ever be worth the effort to properly fix it and we should just leave it alone, and Workers might fill the gap well enough.

In any case, yes, it’s definitely not a queueMicrotask bug.

@sam-github
Copy link
Contributor

I'm not sure if this is the right place, but I would like to suggest that the documentation be enhanced to describe why Node.js has this API, and/or under what conditions we think it should be used.

https://nodejs.org/api/globals.html#globals_queuemicrotask_callback is ATM a purely factual description of what it does, but given the difficulty in knowing when to use setImmediate() vs nextTick(), adding a third option seems to just add to the confusion.

I'm personally confused, because while the docs don't say anything on expected usage, there is some example code, that is virtually identical in purpose to the examples in process.nextTick, but with the additional mention of something about interaction with promises. The example just makes me wonder if all usages of nextTick somehow don't interact with promises, or perhaps the example is not specific enough.

See https://nodejs.org/api/process.html#process_process_nexttick_callback_args to compare the examples, and description.

For me, this kind of vagueness is fine for experimental APIs, but once they have had some use, it should be clarified.

Its possible the docs should be something like:

This API allows access to the same callback queue used by promises. Most Node.js code should be using nextTick, but implementors of promise utility libraries may need to schedule callbacks with precise ordering relationships with respect to promises. It may also be useful for running non-Node.js specific javascript code, since the API also exists in browsers (ref to browser docs....).

If the above guess at the purpose is somewhat correct, the example should not be so similar to the nextTick example, but instead be a Promise.waitAll() implementation, or something of the like.

@devsnek
Copy link
Member Author

devsnek commented Jan 21, 2019

It originally said something along the lines of "This API schedules a callback interleaved in the microtask queue, interleaved with promsies. Most Node.js code should use this API for scheduling. If you want to guarantee your callback runs before promises, use process.nextTick" but iirc @bnoordhuis removed it?

@sam-github
Copy link
Contributor

Most Node.js code should use this API for scheduling.

If this is true, then the process.nextTick docs need to be modified to reflect that. As it is, we seem to have two different APIs that "should" be used for the same purpose, quite confusing.

@mcollina
Copy link
Member

Most Node.js code should use this API for scheduling.

I disagree. Using this API triggers a costly JS <-> C++ transition, while nextTick  happens only in JS-land. I expect a significant performance different between the two. IMHO nextTick  should be the preferred way, wit queueMicrotask  being used for compat reason.

@devsnek
Copy link
Member Author

devsnek commented Jan 21, 2019

@mcollina if performance is a concern we can definitely work on that, but nextTick jumps out of line and the zalgo of that isn't usually needed.

@sam-github
Copy link
Contributor

@devsnek There are two lines. It would be equally true to say promises jump out of line. Since the nextTick line is used extensively inside node.js (not to mention the wider set of node.js user code), encouraging people to use a different queue seems more likely to create problems than to create consistency. Note for those not familiar: zalgo.

The core of the problem is that promises created a new queue, and now there are two. I assume having the utask queue be integrated with the nexttick queue wasn't technically possible? I had the impression that v8 went through some effort to give embedders control over utask scheduling.

And how does setImmediate fit into this? Didn't it come from the browser? Did the promises queue unleash zalgo in pure browser javascript, or did browsers retarget setImmediate at the utask queue?

@jasnell
Copy link
Member

jasnell commented Jan 21, 2019

I'm -1 on any language that suggests that this be favored over nextTick for a number of reasons that have already been discussed here. We should say only what the differences between them are without placing any relative value or preference.

@joyeecheung
Copy link
Member

I opened #25616 to run the WPT in core - to my surprise no additional modification to the current tooling is necessary to add this into core

@sam-github
Copy link
Contributor

I'm a little uncomfortable with not specifying a preference, I think our API users deserve to be informed not only about how the APIs work, but how we expect them to be used. But I can see it is contentious.

Perhaps we can at least acknowlege the tradeoffs between nextTick and and queueMicrotask, either in the API docs here, or we could link to the guide, and enhance it with information about the new queue.
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

And despite the title of that guide, I notice it isn't linked to from the nextTick docs. I'll add it.

@Trott Trott added the semver-minor PRs that contain new features and should be released in the next minor version. label Jan 27, 2019
@@ -761,30 +761,12 @@ function setupGlobalEncoding() {
}

function setupQueueMicrotask() {
const { queueMicrotask } =
NativeModule.require('internal/queue_microtask');
Object.defineProperty(global, 'queueMicrotask', {
Copy link
Member

@lpinca lpinca Feb 9, 2019

Choose a reason for hiding this comment

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

We can do

global.queueMicrotask = queueMicrotask;

now no?

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 can, but it's best to be explicit.

Copy link
Member

Choose a reason for hiding this comment

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

We do it for setTimeout, setImmediate, etc. I'm fine with it as is though.

Copy link
Member

Choose a reason for hiding this comment

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

Making it global means semver-major.

Copy link
Member Author

Choose a reason for hiding this comment

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

it's already a global

Copy link
Member

Choose a reason for hiding this comment

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

Ah! Right lol... Had forgotten that :)

Copy link
Member

Choose a reason for hiding this comment

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

I personally prefer

global.queueMicrotask = queueMicrotask;

It is significantly shorter and the implications should be clear.

@@ -761,30 +761,12 @@ function setupGlobalEncoding() {
}

function setupQueueMicrotask() {
const { queueMicrotask } =
NativeModule.require('internal/queue_microtask');
Object.defineProperty(global, 'queueMicrotask', {
Copy link
Member

Choose a reason for hiding this comment

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

I personally prefer

global.queueMicrotask = queueMicrotask;

It is significantly shorter and the implications should be clear.

@BridgeAR
Copy link
Member

BridgeAR commented Mar 6, 2019

@sam-github I agree that the docs could and probably should be improved further but to me it seems that can be done in a separate PR as this should mainly just move the queueMicrtask to stable without changing the documentation.

@devsnek this needs a rebase.

@sam-github
Copy link
Contributor

I think its odd to move something from experimental when we don't have consensus on what purpose it has, but its stable in the sense of "not going to change", so sure, +0.

@devsnek
Copy link
Member Author

devsnek commented Mar 6, 2019

the two points were parity with browsers and providing an api that lets people enter the proper async queue.

i feel like this api should be explained as "if you don't know why you need nextTick, use queueMicrotask."

"why do i need nextTick" is probably legacy reasons or performance (we can get rid of the perf issue entirely by using %EnqueueMicrotask instead of calling c++)

@sam-github
Copy link
Contributor

Unfortunately, there is also a sizable "if you don't know why you need queueMicrotask, use nextTick" camp. And also a ... use setImmediate and ... use setTimeout(0) camp (though that last camp is hopefully being abandoned by its last inhabitants).

@devsnek
Copy link
Member Author

devsnek commented Mar 6, 2019

there is also a sizable "if you don't know why you need queueMicrotask, use nextTick" camp

no one has yet given a reason why new code should use nextTick over queueMicrotask besides performance. I understand there are legacy timing reasons to use nextTick, but that seems to fall squarely in the category of "I know why I need nextTick"

some reasons to use queueMicrotask:

  • the async primitive of js is a promise, so it makes sense to engage with that queue, not platform specific ones.
  • supported in multiple platforms

@BridgeAR
Copy link
Member

BridgeAR commented Mar 6, 2019

refack pushed a commit to joyeecheung/node that referenced this pull request Mar 8, 2019
PR-URL: nodejs#26520
Fixes: nodejs#26528
Refs: nodejs#25594
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
BridgeAR pushed a commit to BridgeAR/node that referenced this pull request Mar 13, 2019
PR-URL: nodejs#26520
Fixes: nodejs#26528
Refs: nodejs#25594
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
BridgeAR pushed a commit that referenced this pull request Mar 14, 2019
PR-URL: #26520
Fixes: #26528
Refs: #25594
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
@mcollina
Copy link
Member

This breaks readable-stream test suite. Please don't include it in a release as it would need to be addressed or reverted.

@devsnek
Copy link
Member Author

devsnek commented Mar 14, 2019

@mcollina can you provide some more info on that?

@mcollina
Copy link
Member

The tests of readable-stream all comes out red. It might be something in the harness.

@targos
Copy link
Member

targos commented Mar 14, 2019

What I saw in citgm is that the presence of the new global makes the tests throw an error

@devsnek
Copy link
Member Author

devsnek commented Mar 14, 2019

is there some common test framework or something that is failing? if something needs to be updated we should make sure it is updated. I added queueMicrotask to the globals lib a while ago (sindresorhus/globals#142)

@devsnek
Copy link
Member Author

devsnek commented Mar 14, 2019

seems like it just needs to be modified to collect globals at startup instead of using a known list cc @mcollina

@joyeecheung
Copy link
Member

joyeecheung commented Mar 15, 2019

That file looks like a port of our test/common/index.js, maybe it just needs an update?

@mcollina
Copy link
Member

Yes. However the switch of the enumerable flag makes this change semver-major in nature as it’s going to broke some module CI systems. I think it would be safer if this is backported to 11 with the enumerable flag disabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. experimental Issues and PRs related to experimental features. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.