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

JS nullish coalescing and optional chaining operators break syntax highlighting on GitHub #5118

Open
FeBe95 opened this issue Jan 8, 2025 · 0 comments
Labels
bug Something isn't working

Comments

@FeBe95
Copy link

FeBe95 commented Jan 8, 2025

Vue - Official extension or vue-tsc version

N/A

VSCode version

N/A

Vue version

N/A

TypeScript version

N/A

System Info

No response

package.json dependencies

No response

Steps to reproduce

I've noticed that using ?? and/or ?. inside of a <script> tag breaks syntax highlighting on GitHub.

Note

GitHub is using this repository for its syntax highlighting since end of last year:

Examples

  • Closing tag of script element is highlighted incorrectly when using nullish coalescing operator ??:
    <script>
    let foo = bar ?? baz;
    </script>
  • Closing tag of script element is highlighted incorrectly when using optional chaining operator ?.:
    <script>
    let foo = bar?.baz;
    </script>
  • Closing tag of script element is highlighted correctly when using logical OR ||:
    <script>
    let foo = bar || baz;
    </script>

What is expected?

Code is highlighted correctly.

What is actually happening?

Code is not highlighted correctly, or not even highlighted at all.

Link to minimal reproduction

No response

Any additional comments?

This bug is the potentially causing another issue on GitHub, where syntax highlighting is completely absent for larger files that contain these operators. I've tracked it down to be caused from a certain amount of statements containing any of the two operators in combination with surrounding parentheses.

I guess there might be some syntax analysis depth limit being hit, because the operators are not parsed correctly (causing some kind of nesting where there should be none).

The following table demonstrates this (secondary) issue:

# Highlighting mostly working,
closing tag highlighted incorrectly,
(using 84x ??)
No highlighting at all
(using 85x ??)
Correct highlighting
(using 85x ||)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<script>
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
// foo = (bar ?? 'bar');
</script>
<script>
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
foo = (bar ?? 'bar');
</script>
<script>
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
foo = (bar || 'bar');
</script>

Note:

You can observe a similar "syntax analysis depth limit" when nesting if statements. In this case 253 nested if statements are highlighted correctly, while 254 nested if statements are not highlighted at all (I made sure to break the statements into multiple lines, so that the single-line length limit of 1024 is not being hit).

<script>
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) {
  // foo
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}
</script>
<script>
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) { if (true) {
if (true) { if (true) {
  // foo
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
}}
</script>
@KazariEX KazariEX added bug Something isn't working and removed pending triage labels Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants