[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[java] Keys: enforce CharSequence contract in charAt() - #17166

Merged
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds
Mar 4, 2026
Merged

[java] Keys: enforce CharSequence contract in charAt()#17166
asolntsev merged 5 commits into
SeleniumHQ:trunkfrom
seethinajayadileep:fix-scriptkey-charat-bounds

Conversation

@seethinajayadileep

Copy link
Copy Markdown
Contributor

💥 What does this PR do?

Updates Keys.charAt(int index) to validate the index and throw
IndexOutOfBoundsException when the index is not 0.

Previously, the method returned the null character ('\u0000') for any
index other than 0, which silently violated the CharSequence contract.

This change ensures:

  • length() returns 1
  • charAt(0) returns the key code
  • charAt(index != 0) throws IndexOutOfBoundsException

This aligns the implementation with expected CharSequence behavior.


🔧 Implementation Notes

Keys represents a single Unicode PUA character. Since its length is
always 1, only index 0 is valid.

Instead of returning '\u0000' for invalid indexes (which can mask bugs
and produce incorrect comparisons), the method now explicitly throws
IndexOutOfBoundsException.

Alternative considered:

  • Keeping the previous behavior (returning '\u0000') — rejected because
    it silently hides incorrect usage and breaks contract expectations.

💡 Additional Considerations

  • No behavioral change for valid usage (charAt(0)).
  • Improves correctness when used in string comparisons or iteration.
  • No impact on toString(), subSequence(), or chord() behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Enforce CharSequence contract in Keys.charAt() bounds checking

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enforce bounds checking in Keys.charAt() method
• Throw IndexOutOfBoundsException for invalid indexes
• Comply with CharSequence contract requirements
• Prevent silent violations and incorrect comparisons

Grey Divider

File Changes

1. java/src/org/openqa/selenium/Keys.java 🐞 Bug fix +3/-3

Add bounds validation to Keys.charAt() method

• Changed charAt(int index) to validate index parameter
• Now throws IndexOutOfBoundsException when index != 0
• Removed silent return of null character ('\u0000')
• Ensures compliance with CharSequence interface contract

java/src/org/openqa/selenium/Keys.java


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-reviewBot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📎 Requirement gaps (0)

Grey Divider


Action required

1. KeysTest expects charAt(10)📘 Rule violation⛯ Reliability
Description
Keys.charAt(int) now throws IndexOutOfBoundsException for any index other than 0, but the
existing unit test still asserts that charAt(10) returns 0. This functional change needs
corresponding test updates/additions to avoid incorrect expectations and failing CI.
Code

java/src/org/openqa/selenium/Keys.java[R143-146]

+ if (index != 0) {+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 1");
}
- return 0;+ return keyCode;
Evidence
PR Compliance ID 5 requires updating/adding tests for functional changes. The PR changes
Keys.charAt to throw on index != 0, while the existing unit test still expects a 0 return
value for a non-zero index, so tests must be updated to match the new contract.

AGENTS.md
java/src/org/openqa/selenium/Keys.java[141-147]
java/test/org/openqa/selenium/KeysTest.java[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`Keys.charAt(int)` now throws for `index != 0`, but `KeysTest.charAtOtherPositionReturnsZero()` still asserts a `0` return value, which no longer matches the new behavior.
## Issue Context
The production change enforces the `CharSequence` contract by throwing `IndexOutOfBoundsException` for invalid indices. The unit test suite should be updated to reflect this and prevent CI failures.
## Fix Focus Areas
- java/test/org/openqa/selenium/KeysTest.java[32-41]
- java/src/org/openqa/selenium/Keys.java[141-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@selenium-ciselenium-ci added the C-java Java Bindings label Mar 3, 2026
Comment threadjava/src/org/openqa/selenium/Keys.java
@seethinajayadileep
seethinajayadileepforce-pushed the fix-scriptkey-charat-bounds branch from 4f2a4d1 to 2754996CompareMarch 3, 2026 07:36
@cgoldberg

Copy link
Copy Markdown
Member

@seethinajayadileep I just approved the workflows to run for this PR, but we are having some issues so you will likely see some unrelated test failures in CI.

@asolntsevasolntsev added this to the 4.42.0 milestone Mar 4, 2026
@asolntsev
asolntsev merged commit 5b3c36c into SeleniumHQ:trunkMar 4, 2026
43 of 44 checks passed
AutomatedTester pushed a commit that referenced this pull request Mar 11, 2026
* Enforce bounds check in Keys.charAt() to comply with CharSequence contract
* update charAt test to validate bounds
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-javaJava Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@seethinajayadileep@cgoldberg@asolntsev@selenium-ci