js_of_ocaml
js_of_ocaml copied to clipboard
Add option to not include undefined values in resulting object literal
Using
let obj = object%js (self)
val z = Js.undefined [@@jsoo.optdef]
end
It still includes {z: undefined} in the resulting object literal. It'd be helpful to have an option (or a new attribute) to just not include the property altogether if it's undefined.
BuckleScript has something similar with bs.obj (example).
cc @Drup
What would you expect the following to do ?
let f x =
object%js (self)
val z = x [@@jsoo.optdef]
end
@hhugo I don't think the current behavior of [@@jsoo.optdef] is totally unexpected, but I was hoping to have a way for the property to not be included in the resulting literal if the value is undefined.
So in the snippet you shared, calling f Js.undefined would return an empty object {}.
In case it helps, this is the part of the BuckleScript codebase where the external ... = "" [@@bs.obj] case is handled.
Here's the documentation for it.
As you can see, it walks through the args of the external declaration, and then calls Ffi_obj_create. The functionality provided by external + [@@bs.obj] has been extremely helpful in my experience, as it allows to create these literals with optional properties in a very ergonomic way using function labels.
I know this kind of design with annotations for externals is not common in jsoo... but I thought it'd be worth mentioning for more context.
I'm not against the idea. What do you expect the generated javascript to be. Creating an empty object and and have a bunch of if-then to set fields if not undefined?
This is a sample implementation I did using the existing APIs:
let optInj prop opt =
match opt with
| Some (s) -> [|(prop, Js.Unsafe.inject s)|]
| None -> [||]
let create ?x:(x : string option) ?y:(y : int option) ?z:(z : int option) () =
optInj "x" x
|> Array.append (optInj "y" y)
|> Array.append (optInj "z" z)
let obj = Js.Unsafe.obj (create ~x:"2" ~y:2 ()) (* {x: "2", y: 2} *)
let obj2 = Js.Unsafe.obj (create ()) (* {} *)
What do you expect the generated javascript to be. Creating an empty object and and have a bunch of if-then to set fields if not undefined?
@hhugo Yes, in the same vein as this.
As a side question, I'm not sure how BuckleScript does it but it inlines most of the usages. I guess this is an optimization that already exists in the OCaml compiler, right?
Was there any action taken as a result of this question? I would find that capability quite useful.