Skip to content

Commit 73987ab

Browse files
committed
[java] Make JsonInput.hasNext() idempotent between elements
hasNext() consumed the comma between elements but did not clear the 'container has element' flag, so a second hasNext() before reading the next value threw as if the comma were missing. Iterator-style callers that probe multiple times per element saw spurious failures on valid input like [1,2].
1 parent d9c9e39 commit 73987ab

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

java/src/org/openqa/selenium/json/JsonInput.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ public boolean hasNext() {
364364
throw new JsonException("Unexpected ',' before first element of container. " + input);
365365
}
366366
input.read();
367+
// We've moved past the separator, so we're once again expecting an element rather than
368+
// another comma. Clear the flag so a repeat hasNext() before reading is a no-op.
369+
clearSeenElement();
367370
skipWhitespace(input);
368371
JsonType afterComma = peek();
369372
// Trailing comma leniency: '[1,]' and '{"a":1,}' are accepted.
@@ -608,6 +611,13 @@ private void markElementRead() {
608611
}
609612
}
610613

614+
private void clearSeenElement() {
615+
if (!containerHasElement.isEmpty()) {
616+
containerHasElement.removeFirst();
617+
containerHasElement.addFirst(false);
618+
}
619+
}
620+
611621
/**
612622
* Read the next element from the JSON input stream, converting with the supplied mapper if it's
613623
* the expected string.

java/test/org/openqa/selenium/json/JsonInputTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,39 @@ void shouldRejectLeadingCommaInArray() {
429429
}
430430
}
431431

432+
@Test
433+
void hasNextIsIdempotentBetweenElementsInArray() {
434+
// Iterator-style probing (peek/hasNext repeatedly before reading) must not falsely fail
435+
// once hasNext() has already consumed the comma before the next element.
436+
try (JsonInput input = newInput("[1,2]")) {
437+
input.beginArray();
438+
assertThat(input.hasNext()).isTrue();
439+
assertThat(input.nextNumber()).isEqualTo(1L);
440+
assertThat(input.hasNext()).isTrue();
441+
assertThat(input.hasNext()).isTrue();
442+
assertThat(input.nextNumber()).isEqualTo(2L);
443+
assertThat(input.hasNext()).isFalse();
444+
assertThat(input.hasNext()).isFalse();
445+
input.endArray();
446+
}
447+
}
448+
449+
@Test
450+
void hasNextIsIdempotentBetweenEntriesInObject() {
451+
try (JsonInput input = newInput("{\"a\":1,\"b\":2}")) {
452+
input.beginObject();
453+
assertThat(input.hasNext()).isTrue();
454+
assertThat(input.nextName()).isEqualTo("a");
455+
assertThat(input.nextNumber()).isEqualTo(1L);
456+
assertThat(input.hasNext()).isTrue();
457+
assertThat(input.hasNext()).isTrue();
458+
assertThat(input.nextName()).isEqualTo("b");
459+
assertThat(input.nextNumber()).isEqualTo(2L);
460+
assertThat(input.hasNext()).isFalse();
461+
input.endObject();
462+
}
463+
}
464+
432465
@Test
433466
void nullInputsShouldCoerceAsNullValues() throws IOException {
434467
try (InputStream is = new ByteArrayInputStream(new byte[0]);

0 commit comments

Comments
 (0)