Selenium This Week: JSON Parser and Manager Fixes

   |   5 minute read   |   Using 908 words

The recent activity in Selenium, the browser automation project, is mostly about making edge cases less strange. The headline change is Java JSON parser hardening, with smaller but useful fixes in Selenium Manager, Grid session queue wiring, and Python remote connection routing.

JSON parsing gets stricter where it should

The busiest files this week were JsonInput.java and JsonInputTest.java. Parser changes without tests are where sadness starts.

The maintainers first fixed a container parsing gap with a change that enforces comma separators while still accepting one trailing comma. Before this, inputs like [1 2 3] or [,1] could get through, while [1,2,3,] failed. The new logic tracks whether the active array or object has already seen an element, then uses that state in hasNext().

That matters for users who feed generated JSON into Selenium internals or extension points. A missing comma should fail loudly. A trailing comma is still lenient, which keeps some existing inputs working.

Concrete parser behavior changed around:

  • Missing separators in arrays and objects
  • Leading commas before the first element
  • A single trailing comma before ] or }
  • Repeated hasNext() calls before reading the next element

The number lexer was tightened in the RFC 8259 aligned number parsing commit. Selenium no longer treats +5, 01, .5, 5., 1e, or a bare minus sign as valid JSON numbers. It also rejects values that would turn into non finite doubles, such as huge exponents.

The same parser work closes two string traps. The EOF sentinel fix changes the internal input reader so U+FFFF is not confused with end of input. The old sentinel used a char value that could collide with a valid UTF-16 code unit. The new path returns an int, matching Reader.read().

Then the control character rejection commit makes raw control characters illegal inside JSON strings. Escaped versions still work. Literal newline and tab characters inside quotes now fail as they should.

These are not flashy changes. They stop odd bug reports where a payload works in one parser, fails in another, and costs two hours because the real problem is hidden in a string byte.

Constructor based JSON coercion is now useful

The JSON work was not only about rejection. Selenium also added constructor argument support for JSON coercion. The new coercer can build objects through constructors when parameter names are visible at runtime.

For Java users, the detail to remember is javac -parameters. Without runtime parameter names, Selenium cannot map JSON fields to constructor arguments. With them, classes without no arg constructors can be populated directly. Optional constructor parameters are handled through Optional, and fromJson still wins when a type declares it.

The change also trims hand written fromJson style code in BiDi and Grid data types. That is mostly internal cleanup, but it matters because immutable values become easier to keep immutable.

Watch these cases if custom Selenium JSON coercers are in play:

  • Required constructor parameters must be present
  • Non optional constructor parameters cannot be null
  • Ambiguous matching constructors now raise a JSON error
  • Optional<T> can represent absent or null fields

Selenium Manager gets more honest about local browsers

Selenium Manager saw two useful Rust side fixes. In the browser path mismatch change, an explicit browser path is no longer ignored when a specific browser version is requested. If the binary at that path reports a different version, Selenium Manager now reports the detected version and the requested version instead of silently drifting into a download or cache path.

That is a better failure mode for CI. A job that passes --browser-path usually has a reason. If it also passes --browser-version, the two inputs should not fight quietly.

Firefox discovery also improved. The Linux Firefox binary name change teaches Selenium Manager to look for names like firefox-beta, firefox-devedition, firefox-trunk, and firefox-esr before falling back to firefox. The code sits in rust/src/firefox.rs, with shared discovery behavior in rust/src/lib.rs.

This is mainly for Linux users running beta, dev edition, nightly, or ESR builds from distro packages. It reduces the need for manual paths when the desired binary is already installed under its channel specific name.

Grid, Python, and build hygiene

Grid got a targeted session queue fix. The Redis backed SessionQueue packaging commit adds a --sessionqueue-implementation flag and wires the Redis session queue dependency into the relevant Bazel target. This is operator visible because external queue implementations loaded through --ext need a way to declare the implementation class and reach the needed classes at runtime.

Python remote connection routing also picked up a small correctness fix. Safari, Safari Technology Preview, and WebView2 now route to their proper handlers. The previous matching covered fewer browser names. If code depends on remote connection handler behavior for those browsers, this is worth checking before the next upgrade.

The build side is quieter. The Node.js toolchain update adjusts release workflow settings, and the automated browser version update refreshes pins in common/repositories.bzl.

What to watch

If a test fixture sends loose JSON into Selenium Java internals, rerun it against trunk. The parser now rejects malformed numbers, raw control characters, and missing comma separators.

If CI calls Selenium Manager with both --browser-path and --browser-version, check for new mismatch errors. That error is useful, but it may expose jobs that were only passing because the wrong browser was silently accepted.

For Grid deployments using Redis backed session queue support, track the new --sessionqueue-implementation path. It is the sort of flag that should be pinned in deployment docs, not left as tribal memory.



denis256 at denis256.dev