We would want to bind to a global object with methods as a OCaml module with js.scope.
Sometimes, however, the global object is a "callable" one, which can also be called as a function.
A good example is the Number class/global object in ES5. Number is a global object which can be used as a constructor and can also be used as a function. Today we would have to bind to it as:
(* number.mli *)
type t = private Ojs.t
val toString: t -> ?radix:int -> unit -> float [@@js.call]
val toFixed: t -> ?fractionDigits:int -> unit -> float [@@js.call]
val toExponential: t -> ?fractionDigits:int -> unit -> float [@@js.call]
val toPrecision: t -> ?precision:int -> unit -> float [@@js.call]
val valueOf: t -> float [@@js.call]
module [@js.scope "Number"] Static : sig
val create: 'any -> t [@@js.create]
val min_value: float [@@js.global "MIN_VALUE"]
val max_value: float [@@js.global "MAX_VALUE"]
val nan: float [@@js.global "NaN"]
val negative_infinity: float [@@js.global "NEGATIVE_INFINITY"]
val positive_infinity: float [@@js.global "POSITIVE_INFINITY"]
end
val number: 'any -> float [@@js.global "Number"]
The problem is we can't js.scope the entire file because we lack the function counterpart of js.create, which calls the global object as a constructor.
This PR introduces a new attribute js.invoke to fill the gap:
as a function
as a constructor
call the first argument
[@@js.apply]
[@@js.apply_newable]
call the global object
[@@js.invoke](NEW)
[@@js.create]
call a member of the first argument
[@@js.call "name"]
N/A
call a member of the global object
[@@js.global "name"]
[@@js.new "name"]
With this, we would be able to rewrite the above binding as:
[@@@js.scope "Number"]
type t = private Ojs.t
val toString: t -> ?radix:int -> unit -> float [@@js.call]
val toFixed: t -> ?fractionDigits:int -> unit -> float [@@js.call]
val toExponential: t -> ?fractionDigits:int -> unit -> float [@@js.call]
val toPrecision: t -> ?precision:int -> unit -> float [@@js.call]
val valueOf: t -> float [@@js.call]
val create: 'any -> t [@@js.create]
val number: 'any -> float [@@js.invoke]
val min_value: float [@@js.global "MIN_VALUE"]
val max_value: float [@@js.global "MAX_VALUE"]
val nan: float [@@js.global "NaN"]
val negative_infinity: float [@@js.global "NEGATIVE_INFINITY"]
val positive_infinity: float [@@js.global "POSITIVE_INFINITY"]
We would want to bind to a global object with methods as a OCaml module with
js.scope
. Sometimes, however, the global object is a "callable" one, which can also be called as a function.A good example is the
Number
class/global object in ES5.Number
is a global object which can be used as a constructor and can also be used as a function. Today we would have to bind to it as:The problem is we can't
js.scope
the entire file because we lack the function counterpart ofjs.create
, which calls the global object as a constructor.This PR introduces a new attribute
js.invoke
to fill the gap:[@@js.apply]
[@@js.apply_newable]
[@@js.invoke]
(NEW)[@@js.create]
[@@js.call "name"]
[@@js.global "name"]
[@@js.new "name"]
With this, we would be able to rewrite the above binding as: