-
Notifications
You must be signed in to change notification settings - Fork 481
Description
Bug: Switch pattern matching on JSON.Array and JSON.Object generates incorrect JS when Null case is omitted
When pattern matching on JSON values with both Array and Object cases, the generated JavaScript incorrectly omits the null check, causing runtime failures
when the value is null.
Reproducible Example
This ReScript code generates incorrect JavaScript (missing null check):
let getSchedule = (dict, key) => {
dict
->Dict.get(key)
->Option.mapOr(None, schedule => {
switch schedule {
| JSON.Array(array) =>
Some(
array->Array.map(finalJson => {
let finalDict = finalJson->getDictFromJsonObject
mappingScheduleWithDict(finalDict)
}),
)
| JSON.Object(dict) => Some([mappingScheduleWithDict(dict)])
| _ => None
}
})
}Incorrect Output (Bug): this is not handling the null case which should go to the None
function getSchedule(dict, key) {
return Stdlib_Option.mapOr(dict[key], undefined, schedule => {
if (Array.isArray(schedule)) { // <-- Crashes if schedule is null!
return schedule.map(finalJson => mappingScheduleWithDict(LogicUtils.getDictFromJsonObject(finalJson)));
}
switch (typeof schedule) {
case "object" :
return [mappingScheduleWithDict(schedule)];
default:
return;
}
});
}Workaround - Adding explicit Null case generates correct code:
| Null | _ => NoneCorrect Output (with Null case):
if (schedule === null) {
return;
}Additional Evidence - Only Object case generates correct guards:
switch schedule {
| JSON.Object(dict) => Some([mappingScheduleWithDict(dict)])
| _ => None
}Correctly generates:
if (typeof schedule === "object" && schedule !== null && !Array.isArray(schedule))Expected Behavior
When both Array and Object cases are present without explicit Null, the compiler should still emit the null check before Array.isArray() to prevent runtime
errors, consistent with the single Object case behavior.
Environment
- ReScript version: 12.0.0
- OS: macOS / Linux