Skip to content

Float parsing differs across targets: 1f / 1d / 0x1p3 accepted on JVM and Native, 0x2 on JS #29

Description

@IRus

YamlScalar.toFloat() / toDouble() delegate to String::toFloat / String::toDouble (src/commonMain/kotlin/com/charleskorn/kaml/YamlNode.kt:97,124). The accepted input set of those stdlib functions is not the same on every target, so the same document parses on one target and throws on another.

Measured

Probe ran YamlScalar(content, path).toDouble() / .toFloat() / .toInt() on jvm, macosArm64, jsNode and wasmJsNode.

content JVM Native JS Wasm
1f 1d 1F 1D 1.0 1.0 throws throws
0x1p3 8.0 8.0 throws throws
0x2 as float/double throws throws 2.0 throws
Infinity -Infinity NaN accepted accepted accepted accepted
1e5 .5 100000.0 / 0.5 same same same

Two separate splits:

  1. 1f, 1d, 1F, 1D, 0x1p3 — accepted on JVM and Native, rejected on JS and Wasm. Java's Double.parseDouble accepts the f/d type suffix and the hexadecimal float form; +"1f" in JS is NaN. Not documented anywhere.
  2. 0x2 as a float — accepted on JS only, because Kotlin/JS String.toDouble() is unary plus and JS number conversion reads hexadecimal. Already known: YamlScalarTest.kt:251-265 disables the "invalid float" assertion for 0x2 and 0o2 on JS. That is a test workaround, not a fix.

None of 1f, 1d, 0x1p3, Infinity, NaN are floats under the YAML 1.2 core schema. Only .inf / .nan are, and those are already handled explicitly before the stdlib call.

Repro

Yaml.default.decodeFromString(Double.serializer(), "1f")     // 1.0 on jvm/native, throws on js/wasm
Yaml.default.decodeFromString(Double.serializer(), "0x1p3")  // 8.0 on jvm/native, throws on js/wasm
Yaml.default.decodeFromString(Double.serializer(), "0x2")    // 2.0 on js, throws elsewhere

Fix

Scan content against the YAML 1.2 core schema float grammar before calling the stdlib, the same way ScalarClassifier in kotaml-json already does for the conversion path. That removes both splits at once and drops the JS carve-out in YamlScalarTest.

Behaviour change: input that decodes today on some targets stops decoding. Every affected form is outside the YAML float schema, so nothing that is valid YAML is lost.

Related: #28.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions