Return value wrapping
In general, the FFI code is error prone, and potentially will leak in undefined
or null
values.
So we introduced auto coercion for return values to gain two benefits:
More safety for FFI code without performance cost (explained later).
More idiomatic OCaml code for users to consume the FFI.
Below is a contrived core example:
type element;
type dom;
[@bs.send] [@bs.return nullable]
external getElementById: (dom, string) => option(element) = "getElementById";
let test = dom => {
let elem = dom->(getElementById("haha"));
switch (elem) {
| None => 1
| Some(ui) =>
Js.log(ui);
2;
};
};
type element
type dom
external getElementById : dom -> string -> element option = "getElementById"
[@@bs.send] [@@bs.return nullable]
let test dom =
let elem = dom |. getElementById "haha" in
match elem with
| None -> 1
| Some ui -> Js.log ui ; 2
return nullable
attribute will automatically convert null and undefined to option
Output:
```js
function test(dom) {
var elem = dom.getElementById("haha");
if (elem == null) {
return 1;
} else {
console.log(elem);
return 2;
}
}
Currently 4 directives are supported: `null_to_opt`, `undefined_to_opt`, `nullable`(introduced in @1.9.0) and `identity`. `null_undefined_to_opt` works the same as `nullable`, but it is deprecated, `nullable` is encouraged
`null_to_opt`, `undefined_to_opt` and `nullable` will *semantically* convert a nullable value to `option` which is a boxed value, but the compiler will do smart optimizations to *remove such boxing overhead* when the returned value is destructed in the same routine.
The three directives above require users to write literally `_ option`. It is in theory not necessary, but it is required to reduce user errors.
When the return type is `unit`: the compiler will append its return value with an OCaml `unit` literal to make sure it does return `unit`. Its main purpose is to make the user consume FFI in idiomatic OCaml code, the cost is *very very small* and the compiler will do smart optimizations to remove it when the returned value is not used (mostly likely).
`identity` will make sure that compiler will do nothing about the returned value. It is rarely used, but introduced here for debugging purpose.