-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
module: handle Top-Level Await non-fulfills better #34640
Closed
Closed
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import '../common/index.mjs'; | ||
import assert from 'assert'; | ||
import child_process from 'child_process'; | ||
import fixtures from '../common/fixtures.js'; | ||
|
||
{ | ||
// Unresolved TLA promise, --eval | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
['--input-type=module', '--eval', 'await new Promise(() => {})'], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout, stderr], [13, '', '']); | ||
} | ||
|
||
{ | ||
// Rejected TLA promise, --eval | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
['--input-type=module', '-e', 'await Promise.reject(new Error("Xyz"))'], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout], [1, '']); | ||
assert.match(stderr, /Error: Xyz/); | ||
} | ||
|
||
{ | ||
// Unresolved TLA promise with explicit exit code, --eval | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
['--input-type=module', '--eval', | ||
'process.exitCode = 42;await new Promise(() => {})'], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout, stderr], [42, '', '']); | ||
} | ||
|
||
{ | ||
// Rejected TLA promise with explicit exit code, --eval | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
['--input-type=module', '-e', | ||
'process.exitCode = 42;await Promise.reject(new Error("Xyz"))'], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout], [1, '']); | ||
assert.match(stderr, /Error: Xyz/); | ||
} | ||
|
||
{ | ||
// Unresolved TLA promise, module file | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
[fixtures.path('es-modules/tla/unresolved.mjs')], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout, stderr], [13, '', '']); | ||
} | ||
|
||
{ | ||
// Rejected TLA promise, module file | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
[fixtures.path('es-modules/tla/rejected.mjs')], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout], [1, '']); | ||
assert.match(stderr, /Error: Xyz/); | ||
} | ||
|
||
{ | ||
// Unresolved TLA promise, module file | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
[fixtures.path('es-modules/tla/unresolved-withexitcode.mjs')], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout, stderr], [42, '', '']); | ||
} | ||
|
||
{ | ||
// Rejected TLA promise, module file | ||
const { status, stdout, stderr } = child_process.spawnSync( | ||
process.execPath, | ||
[fixtures.path('es-modules/tla/rejected-withexitcode.mjs')], | ||
{ encoding: 'utf8' }); | ||
assert.deepStrictEqual([status, stdout], [1, '']); | ||
assert.match(stderr, /Error: Xyz/); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
process.exitCode = 42; | ||
await Promise.reject(new Error('Xyz')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
await Promise.reject(new Error('Xyz')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
process.exitCode = 42; | ||
await new Promise(() => {}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
await new Promise(() => {}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will be used if any part of the
import()
process stalls, for example a loader returning a promise that never resolves.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you suggesting to explicitly list that special case? I would prefer not to, if you’re working on an ESM loader then you can probably imagine that
import()
stalling would look like unfinished TLA. The far more common case is going to be actual TLA usage, I assumeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I'm just saying, with the current implementation, 13 doesn't actually imply the lack of promise resolution came from a source text module with TLA. I think the best we could do is moving the exitCode check to where module.evaluate() is called, although that still isn't inherently a source text module using TLA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I consider any kind of failure to finish the main module’s evaluation, whether through TLA or not, something that should not be considered a successful operation. This is intentional, and I would be against restricting the check here to only
module.evaluate()
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we shouldn't consider those success cases. I'm saying, the message says "Unfinished Top-Level Await" but it can be caused by other things, which is potentially confusing. It might be better to rename it to "ESM Import Stalled" or something and mention that while many things can cause it, it would probably be caused by
await (promise that never resolves)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think most people would know what “ESM Import Stalled” means.
Again, I think this is mostly relevant when you’re actually developing a loader or similar, and in that case you most likely don’t even need any explanation at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO,
Stalled Top-Level Await
will be the best mix of both 🙄