-
Notifications
You must be signed in to change notification settings - Fork 224
Closed
Description
Description
According to the JavaScript specification, parseFloat("1e"), parseFloat("1e+"), and parseFloat("1e-") should all return 1 by backtracking when no valid digit follows the exponent marker. However, QuickJS returns NaN instead.
Expected Behavior (per ECMA-262 / TC39 Test262)
parseFloat("1e") // should return 1
parseFloat("1e+") // should return 1
parseFloat("1e-") // should return 1
parseFloat("1E") // should return 1
parseFloat("42e") // should return 42
parseFloat("3.14e+") // should return 3.14Current Behavior
All of the above return NaN.
Root Cause
In dtoa.c, the js_atod function has this code (around line 1534):
c = to_digit(*p);
if (c >= 10)
goto fail; /* XXX: could stop before the exponent part */The comment even acknowledges the issue. When there's no valid digit after the exponent marker (and optional sign), the parser should backtrack to before the e character and return the parsed number, not fail entirely.
Proposed Fix
Save the position before entering the exponent parsing block and restore it if no valid digit is found:
const char *p_before_exp = p; /* save position before exponent */
is_bin_exp = (*p == 'p' || *p == 'P');
p++;
exp_is_neg = 0;
if (*p == '+') {
p++;
} else if (*p == '-') {
exp_is_neg = true;
p++;
}
c = to_digit(*p);
if (c >= 10) {
/* No valid digit after exponent marker: backtrack to before 'e'.
JavaScript spec: parseFloat("1e") === 1, parseFloat("1e+") === 1 */
p = p_before_exp;
goto after_exp; /* skip exponent processing, continue with result */
}Then add after_exp: label before the if (p == p_start) check.
References
- ECMA-262 Section 21.1.1.1 (ToNumber Applied to the String Type)
- TC39 Test262
test/built-ins/parseFloat/ - Found while running Test262 tests via quickjs.ml
Metadata
Metadata
Assignees
Labels
No labels