Skip to content

Conversation

@nicolo-ribaudo
Copy link
Contributor

Fixes#60757 (comment)

I also added a bunch more tests for when using defer as a binding identifier in ES import declarations. Note that import defer from from "foo" is invalid, but I added a test to verify that it reports the same error as for import defer foo from "foo".

cc @jakebailey

CopilotAI review requested due to automatic review settings June 9, 2025 12:50
@github-project-automationgithub-project-automationbot moved this to Not started in PR BacklogJun 9, 2025
@typescript-bottypescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Jun 9, 2025
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

1 similar comment
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR restores the parsing of the "defer" identifier in import equals declarations and enhances the test coverage for various scenarios involving "defer" in import statements.

  • Adds new test cases for valid and invalid "defer" usage in various module systems.
  • Updates baseline outputs to reflect the corrections.
  • Refines the parser logic in src/compiler/parser.ts to correctly distinguish "defer" as a phase modifier.

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

FileDescription
tests/cases/conformance/importDefer/*.tsAdded tests for "defer" usage in import equals and import declarations.
tests/baselines/reference/*Updated baselines reflecting the new parsing behavior.
src/compiler/parser.tsModified the condition for recognizing "defer" to improve parsing accuracy.
Comments suppressed due to low confidence (2)

src/compiler/parser.ts:8396

  • [nitpick] The compound condition for detecting a deferred import is complex; adding an inline comment or refactoring using intermediate variables could improve code clarity.
identifier?.escapedText === "defer" && (token() === SyntaxKind.FromKeyword ? !lookAhead(nextTokenIsStringLiteral) : token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.EqualsToken) 

src/compiler/parser.ts:8396

  • [nitpick] Consider caching the result of token() in a local variable before the condition to ensure consistency and potentially reduce function calls.
identifier?.escapedText === "defer" && (token() === SyntaxKind.FromKeyword ? !lookAhead(nextTokenIsStringLiteral) : token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.EqualsToken) 

@jakebailey
Copy link
Member

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 9, 2025

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
test top400✅ Started✅ Results
user test this✅ Started✅ Results
run dt✅ Started✅ Results
perf test this faster✅ Started👀 Results

@typescript-bot
Copy link
Collaborator

Hey @jakebailey, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

@jakebailey Here are the results of running the user tests with tsc comparing main and refs/pull/61837/merge:

Everything looks good!

@typescript-bot
Copy link
Collaborator

@jakebailey
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-Unions - node (v18.15.0, x64)
Errors3434~~~p=1.000 n=6
Symbols62,39062,390~~~p=1.000 n=6
Types50,39550,395~~~p=1.000 n=6
Memory used195,424k (± 0.91%)194,741k (± 1.01%)~192,918k196,579kp=0.173 n=6
Parse Time1.30s (± 0.79%)1.30s (± 0.75%)~1.29s1.31sp=0.784 n=6
Bind Time0.73s0.73s~~~p=1.000 n=6
Check Time9.71s (± 0.20%)9.72s (± 0.20%)~9.70s9.75sp=0.514 n=6
Emit Time2.74s (± 0.69%)2.74s (± 0.68%)~2.72s2.77sp=0.744 n=6
Total Time14.49s (± 0.10%)14.49s (± 0.26%)~14.46s14.55sp=0.935 n=6
angular-1 - node (v18.15.0, x64)
Errors5656~~~p=1.000 n=6
Symbols949,249949,249~~~p=1.000 n=6
Types411,061411,061~~~p=1.000 n=6
Memory used1,225,146k (± 0.01%)1,225,136k (± 0.00%)~1,225,106k1,225,233kp=0.688 n=6
Parse Time6.58s (± 0.89%)6.61s (± 0.29%)~6.58s6.63sp=0.295 n=6
Bind Time1.88s (± 0.73%)1.88s (± 0.78%)~1.86s1.90sp=0.934 n=6
Check Time31.96s (± 0.22%)31.99s (± 0.32%)~31.85s32.13sp=0.810 n=6
Emit Time14.87s (± 0.09%)14.87s (± 0.36%)~14.79s14.95sp=1.000 n=6
Total Time55.29s (± 0.16%)55.35s (± 0.17%)~55.24s55.49sp=0.630 n=6
mui-docs - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,583,0142,583,014~~~p=1.000 n=6
Types892,129892,129~~~p=1.000 n=6
Memory used2,862,982k (± 0.00%)2,862,941k (± 0.00%)~2,862,903k2,862,994kp=0.092 n=6
Parse Time9.17s (± 0.37%)9.14s (± 0.33%)~9.10s9.18sp=0.225 n=6
Bind Time2.29s (± 0.48%)2.29s (± 0.36%)~2.28s2.30sp=0.383 n=6
Check Time87.34s (± 0.49%)87.37s (± 0.27%)~87.02s87.74sp=0.810 n=6
Emit Time0.30s (± 1.74%)0.30s (± 1.74%)~0.29s0.30sp=1.000 n=6
Total Time99.10s (± 0.43%)99.11s (± 0.24%)~98.76s99.50sp=0.689 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,9011,228,901~~~p=1.000 n=6
Types267,535267,535~~~p=1.000 n=6
Memory used2,362,748k (± 0.01%)2,606,544k (±14.49%)~2,361,973k3,095,135kp=1.000 n=6
Parse Time5.18s (± 0.83%)5.24s (± 1.44%)~5.16s5.34sp=0.066 n=6
Bind Time1.80s (± 0.47%)1.79s (± 1.08%)~1.76s1.82sp=0.612 n=6
Check Time35.48s (± 0.43%)35.63s (± 0.42%)~35.37s35.75sp=0.128 n=6
Emit Time2.95s (± 0.55%)3.01s (± 0.99%)+0.05s (+ 1.86%)2.97s3.05sp=0.008 n=6
Total Time45.43s (± 0.36%)45.67s (± 0.40%)~45.39s45.85sp=0.065 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,9011,228,901~~~p=1.000 n=6
Types267,535267,535~~~p=1.000 n=6
Memory used3,067,152k (± 7.59%)3,041,022k (± 9.80%)~2,432,339k3,163,333kp=0.378 n=6
Parse Time6.87s (± 1.12%)6.90s (± 1.31%)~6.75s7.02sp=0.575 n=6
Bind Time2.18s (± 1.89%)2.18s (± 1.46%)~2.15s2.24sp=1.000 n=6
Check Time42.89s (± 0.77%)43.08s (± 0.28%)~42.96s43.29sp=0.298 n=6
Emit Time3.40s (± 2.91%)3.52s (± 2.75%)~3.41s3.69sp=0.066 n=6
Total Time55.35s (± 0.67%)55.68s (± 0.19%)+0.33s (+ 0.59%)55.50s55.79sp=0.031 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols263,517263,517~~~p=1.000 n=6
Types107,246107,246~~~p=1.000 n=6
Memory used442,127k (± 0.01%)442,144k (± 0.02%)~442,046k442,277kp=0.689 n=6
Parse Time3.51s (± 0.69%)3.54s (± 0.56%)~3.51s3.56sp=0.106 n=6
Bind Time1.31s (± 1.64%)1.32s (± 1.17%)~1.30s1.34sp=0.684 n=6
Check Time18.90s (± 0.36%)18.93s (± 0.34%)~18.80s18.98sp=0.170 n=6
Emit Time1.52s (± 1.21%)1.53s (± 1.07%)~1.51s1.55sp=0.359 n=6
Total Time25.25s (± 0.40%)25.31s (± 0.29%)~25.19s25.41sp=0.228 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors7171~~~p=1.000 n=6
Symbols225,981225,981~~~p=1.000 n=6
Types94,35694,356~~~p=1.000 n=6
Memory used371,280k (± 0.01%)371,362k (± 0.05%)~371,145k371,617kp=0.575 n=6
Parse Time2.88s (± 0.95%)2.89s (± 1.80%)~2.83s2.96sp=0.748 n=6
Bind Time1.59s (± 1.38%)1.59s (± 1.72%)~1.57s1.64sp=1.000 n=6
Check Time16.50s (± 0.35%)16.57s (± 0.37%)~16.49s16.65sp=0.126 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time20.97s (± 0.38%)21.05s (± 0.17%)~21.02s21.10sp=0.065 n=6
vscode - node (v18.15.0, x64)
Errors3838~~~p=1.000 n=6
Symbols3,495,7693,495,769~~~p=1.000 n=6
Types1,180,2361,180,236~~~p=1.000 n=6
Memory used3,537,356k (± 0.01%)3,537,327k (± 0.01%)~3,536,912k3,537,532kp=0.689 n=6
Parse Time14.98s (± 0.53%)14.94s (± 0.35%)~14.87s15.01sp=0.624 n=6
Bind Time4.86s (± 0.40%)4.87s (± 1.00%)~4.81s4.94sp=0.746 n=6
Check Time96.06s (± 3.79%)96.83s (± 3.53%)~94.26s101.57sp=0.748 n=6
Emit Time29.89s (± 4.18%)30.98s (± 6.65%)~29.32s34.97sp=0.173 n=6
Total Time145.79s (± 3.34%)147.61s (± 2.55%)~143.27s152.00sp=0.298 n=6
webpack - node (v18.15.0, x64)
Errors22~~~p=1.000 n=6
Symbols320,092320,092~~~p=1.000 n=6
Types140,399140,399~~~p=1.000 n=6
Memory used474,405k (± 0.02%)474,331k (± 0.02%)~474,249k474,441kp=0.128 n=6
Parse Time4.34s (± 0.81%)4.34s (± 0.56%)~4.32s4.39sp=0.809 n=6
Bind Time1.76s (± 1.74%)1.76s (± 0.86%)~1.74s1.78sp=1.000 n=6
Check Time20.82s (± 0.62%)20.83s (± 0.39%)~20.72s20.93sp=0.936 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time26.93s (± 0.41%)26.95s (± 0.29%)~26.83s27.02sp=0.689 n=6
xstate-main - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols662,826662,826~~~p=1.000 n=6
Types197,993197,993~~~p=1.000 n=6
Memory used568,656k (± 0.01%)568,738k (± 0.01%)~568,669k568,896kp=0.066 n=6
Parse Time4.43s (± 0.79%)4.43s (± 0.60%)~4.40s4.48sp=0.872 n=6
Bind Time1.32s (± 1.12%)1.32s (± 0.96%)~1.31s1.34sp=0.869 n=6
Check Time20.55s (± 0.32%)20.42s (± 1.55%)~19.80s20.66sp=0.573 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time26.30s (± 0.30%)26.18s (± 1.09%)~25.62s26.40sp=0.574 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Compiler-Unions - node (v18.15.0, x64)
  • angular-1 - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • ts-pre-modules - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate-main - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

identifier = isIdentifier() ? parseIdentifier() : undefined;
}
else if (identifier?.escapedText === "defer" && token() !== SyntaxKind.FromKeyword){
else if (
Copy link
Member

@jakebaileyjakebaileyJun 9, 2025

Choose a reason for hiding this comment

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

Why isn't this just the same as what's done for type above? You can't mix type and defer, so I would have expected both to parse in the same fashion.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

The difference is that the type parsing considers type as a modifier in import type foo =, while the defer parsing doesn't in import defer foo =.

Do you prefer if I unify the path, but then add a "nice" error for import defer foo = rather than just complaining about the unexpected foo/=?

Copy link
Member

Choose a reason for hiding this comment

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

Daniel pointed out there's a difference between them in other ways like import type foo,{bar } from "..." is not legal as it's ambiguous whether or not bar is type or not. So, all good.

Copy link
ContributorAuthor

@nicolo-ribaudonicolo-ribaudoJun 9, 2025

Choose a reason for hiding this comment

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

Well technically we could still unify parsing for them and report that type case as an "early error" while still building the proper AST.

(I'm happy to both keep the code as-is or to update it)

Choose a reason for hiding this comment

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

After thinking more, technically neither allow named bindings or defaults. I think this is okay as-is. I'll make a second PR to add more tests.

@typescript-bot
Copy link
Collaborator

@jakebailey Here are the results of running the top 400 repos with tsc comparing main and refs/pull/61837/merge:

Everything looks good!

@github-project-automationgithub-project-automationbot moved this from Not started to Needs merge in PR BacklogJun 9, 2025
@DanielRosenwasserDanielRosenwasser merged commit 0dfd0c2 into microsoft:mainJun 9, 2025
32 checks passed
@github-project-automationgithub-project-automationbot moved this from Needs merge to Done in PR BacklogJun 9, 2025
@nicolo-ribaudonicolo-ribaudo deleted the restore-import-defer-equals branch June 9, 2025 22:19
@microsoftmicrosoft locked as resolved and limited conversation to collaborators Dec 9, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@nicolo-ribaudo@typescript-bot@jakebailey@DanielRosenwasser