@@ -529,7 +529,7 @@ <h1><a href="https://github.com/bloomberg/bucklescript">BuckleScript</a> User Ma
529
529
< li > < a href ="#_js_calling_ocaml "> JS Calling OCaml</ a > </ li >
530
530
< li > < a href ="#_bucklescritp_annotations_for_unicode_and_js_ffi_support "> BuckleScritp annotations for Unicode and JS FFI support</ a >
531
531
< ul class ="sectlevel2 ">
532
- < li > < a href ="#_unicode_support "> Unicode support</ a > </ li >
532
+ < li > < a href ="#_unicode_support_since_1_5_1 "> Unicode support (@since 1.5.1) </ a > </ li >
533
533
< li > < a href ="#_ffi "> FFI</ a > </ li >
534
534
< li > < a href ="#_binding_to_simple_js_functions_values "> Binding to simple JS functions values</ a >
535
535
< ul class ="sectlevel3 ">
@@ -583,6 +583,7 @@ <h1><a href="https://github.com/bloomberg/bucklescript">BuckleScript</a> User Ma
583
583
< li > < a href ="#_object_label_translation_convention "> Object label translation convention</ a > </ li >
584
584
</ ul >
585
585
</ li >
586
+ < li > < a href ="#_return_value_checking_since_1_5_1 "> Return value checking (@since 1.5.1)</ a > </ li >
586
587
< li > < a href ="#_embedding_raw_javascript_code "> Embedding raw Javascript code</ a >
587
588
< ul class ="sectlevel3 ">
588
589
< li > < a href ="#_embedding_raw_js_code_as_an_expression "> Embedding raw JS code as an expression</ a > </ li >
@@ -1390,7 +1391,7 @@ <h2 id="_bucklescritp_annotations_for_unicode_and_js_ffi_support"><a class="anch
1390
1391
improve the generated code.</ p >
1391
1392
</ div >
1392
1393
< div class ="sect2 ">
1393
- < h3 id ="_unicode_support "> < a class ="anchor " href ="#_unicode_support "> </ a > Unicode support</ h3 >
1394
+ < h3 id ="_unicode_support_since_1_5_1 "> < a class ="anchor " href ="#_unicode_support_since_1_5_1 "> </ a > Unicode support (@since 1.5.1) </ h3 >
1394
1395
< div class ="admonitionblock warning ">
1395
1396
< table >
1396
1397
< tr >
@@ -3230,6 +3231,113 @@ <h4 id="_object_label_translation_convention"><a class="anchor" href="#_object_l
3230
3231
</ div >
3231
3232
</ div >
3232
3233
< div class ="sect2 ">
3234
+ < h3 id ="_return_value_checking_since_1_5_1 "> < a class ="anchor " href ="#_return_value_checking_since_1_5_1 "> </ a > Return value checking (@since 1.5.1)</ h3 >
3235
+ < div class ="paragraph ">
3236
+ < p > In general, the FFI code is error prone, and potentially will leak in
3237
+ < code > undefined</ code > or < code > null</ code > values.</ p >
3238
+ </ div >
3239
+ < div class ="paragraph ">
3240
+ < p > So we introduced auto coercion for return values for two benefits:</ p >
3241
+ </ div >
3242
+ < div class ="olist arabic ">
3243
+ < ol class ="arabic ">
3244
+ < li >
3245
+ < p > More safety for FFI code without performance cost(explained later)</ p >
3246
+ </ li >
3247
+ < li >
3248
+ < p > More idiomatic OCaml code for users to consume the FFI.</ p >
3249
+ </ li >
3250
+ </ ol >
3251
+ </ div >
3252
+ < div class ="paragraph ">
3253
+ < p > Below is a contrived core example:</ p >
3254
+ </ div >
3255
+ < div class ="listingblock ">
3256
+ < div class ="content ">
3257
+ < pre class ="pygments highlight "> < code data-lang ="ocaml "> < span class ="tok-k "> type</ span > < span class ="tok-n "> element</ span >
3258
+ < span class ="tok-k "> type</ span > < span class ="tok-n "> dom</ span >
3259
+ < span class ="tok-k "> external</ span > < span class ="tok-n "> getElementById</ span > < span class ="tok-o "> :</ span > < span class ="tok-kt "> string</ span > < span class ="tok-o "> -></ span > < span class ="tok-n "> element</ span > < span class ="tok-n "> option</ span > < span class ="tok-o "> =</ span > < span class ="tok-s2 "> ""</ span >
3260
+ < span class ="tok-o "> [@@</ span > < span class ="tok-n "> bs</ span > < span class ="tok-o "> .</ span > < span class ="tok-n "> send</ span > < span class ="tok-o "> .</ span > < span class ="tok-n "> pipe</ span > < span class ="tok-o "> :</ span > < span class ="tok-n "> dom</ span > < span class ="tok-o "> ]</ span > < span class ="tok-o "> [@@</ span > < span class ="tok-n "> bs</ span > < span class ="tok-o "> .</ span > < span class ="tok-n "> return</ span > < span class ="tok-o "> {</ span > < span class ="tok-n "> null_to_opt</ span > < span class ="tok-o "> }]</ span > < b class ="conum "> (1)</ b >
3261
+
3262
+ < span class ="tok-k "> let</ span > < span class ="tok-n "> test</ span > < span class ="tok-n "> dom</ span > < span class ="tok-o "> =</ span >
3263
+ < span class ="tok-k "> let</ span > < span class ="tok-n "> elem</ span > < span class ="tok-o "> =</ span > < span class ="tok-n "> dom</ span > < span class ="tok-o "> |></ span > < span class ="tok-n "> getElementById</ span > < span class ="tok-s2 "> "haha"</ span > < span class ="tok-k "> in</ span >
3264
+ < span class ="tok-k "> match</ span > < span class ="tok-n "> elem</ span > < span class ="tok-k "> with</ span >
3265
+ < span class ="tok-o "> |</ span > < span class ="tok-nc "> None</ span > < span class ="tok-o "> -></ span > < span class ="tok-mi "> 1</ span >
3266
+ < span class ="tok-o "> |</ span > < span class ="tok-nc "> Some</ span > < span class ="tok-n "> ui</ span > < span class ="tok-o "> -></ span > < span class ="tok-nn "> Js</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> log</ span > < span class ="tok-n "> ui</ span > < span class ="tok-o "> ;</ span > < span class ="tok-mi "> 2</ span > </ code > </ pre >
3267
+ </ div >
3268
+ </ div >
3269
+ < div class ="colist arabic ">
3270
+ < ol >
3271
+ < li >
3272
+ < p > < code > null_to_opt</ code > attriute will automatically convert null to < code > option</ code > </ p >
3273
+ </ li >
3274
+ </ ol >
3275
+ </ div >
3276
+ < div class ="listingblock ">
3277
+ < div class ="title "> Output</ div >
3278
+ < div class ="content ">
3279
+ < pre class ="pygments highlight "> < code data-lang ="js "> < span class ="tok-kd "> function</ span > < span class ="tok-nx "> test</ span > < span class ="tok-p "> (</ span > < span class ="tok-nx "> dom</ span > < span class ="tok-p "> )</ span > < span class ="tok-p "> {</ span >
3280
+ < span class ="tok-kd "> var</ span > < span class ="tok-nx "> elem</ span > < span class ="tok-o "> =</ span > < span class ="tok-nx "> dom</ span > < span class ="tok-p "> .</ span > < span class ="tok-nx "> getElementById</ span > < span class ="tok-p "> (</ span > < span class ="tok-s2 "> "haha"</ span > < span class ="tok-p "> );</ span >
3281
+ < span class ="tok-k "> if</ span > < span class ="tok-p "> (</ span > < span class ="tok-nx "> elem</ span > < span class ="tok-o "> !==</ span > < span class ="tok-kc "> null</ span > < span class ="tok-p "> )</ span > < span class ="tok-p "> {</ span > < b class ="conum "> (1)</ b >
3282
+ < span class ="tok-nx "> console</ span > < span class ="tok-p "> .</ span > < span class ="tok-nx "> log</ span > < span class ="tok-p "> (</ span > < span class ="tok-nx "> elem</ span > < span class ="tok-p "> );</ span >
3283
+ < span class ="tok-k "> return</ span > < span class ="tok-mi "> 2</ span > < span class ="tok-p "> ;</ span >
3284
+ < span class ="tok-p "> }</ span >
3285
+ < span class ="tok-k "> else</ span > < span class ="tok-p "> {</ span >
3286
+ < span class ="tok-k "> return</ span > < span class ="tok-mi "> 1</ span > < span class ="tok-p "> ;</ span >
3287
+ < span class ="tok-p "> }</ span >
3288
+ < span class ="tok-p "> }</ span > </ code > </ pre >
3289
+ </ div >
3290
+ </ div >
3291
+ < div class ="colist arabic ">
3292
+ < ol >
3293
+ < li >
3294
+ < p > nullable checking without boxing due to compiler optimizations</ p >
3295
+ </ li >
3296
+ </ ol >
3297
+ </ div >
3298
+ < div class ="paragraph ">
3299
+ < p > Currently, 4 directives are supported: < code > null_to_opt</ code > , < code > undefined_to_opt</ code > ,
3300
+ , < code > null_undefined_to_opt</ code > and < code > identity</ code > .</ p >
3301
+ </ div >
3302
+ < div class ="admonitionblock note ">
3303
+ < table >
3304
+ < tr >
3305
+ < td class ="icon ">
3306
+ < div class ="title "> Note</ div >
3307
+ </ td >
3308
+ < td class ="content ">
3309
+ < div class ="paragraph ">
3310
+ < p > < code > null_to_opt</ code > , < code > undefined_to_opt</ code > and < code > null_undefined_to_opt</ code > will < strong > semantically</ strong >
3311
+ convert nullable value to < code > option</ code > which is a boxed value, but the compiler will
3312
+ do smart optimizations to < strong > remove such boxing overhead</ strong > when the returned value is destructed
3313
+ in the same routine.</ p >
3314
+ </ div >
3315
+ < div class ="paragraph ">
3316
+ < p > The three directives above require users to write literally < code > _ option</ code > , it is
3317
+ in theory not necessary, but it is required to reduce user errors.</ p >
3318
+ </ div >
3319
+ < div class ="paragraph ">
3320
+ < p > When return type is < code > unit</ code > : the compiler will append its return value
3321
+ with an OCaml < code > unit</ code > literal to make sure it does return < code > unit</ code > , its main purpose
3322
+ is to make user consume FFI in idiomatic OCaml code, the cost is < strong > very very small</ strong > and
3323
+ the compiler will do smart optimizations to remove it when the returned value is not used (mostly likely)</ p >
3324
+ </ div >
3325
+ < div class ="paragraph ">
3326
+ < p > When return type is < code > bool</ code > , the compiler will coerce its return value from
3327
+ JS boolean to OCaml boolean. The cost is also < strong > very small</ strong > and compiler will remove
3328
+ such coercison when it is not needed. Note even if your external FFI does return OCaml < code > bool</ code > or < code > unit</ code > ,
3329
+ such implicit coercion will < strong > cause no harm</ strong > .</ p >
3330
+ </ div >
3331
+ < div class ="paragraph ">
3332
+ < p > < code > identity</ code > will make sure that compiler will do nothing about returned value, it
3333
+ is rarely used but introduced here for debugging purpose.</ p >
3334
+ </ div >
3335
+ </ td >
3336
+ </ tr >
3337
+ </ table >
3338
+ </ div >
3339
+ </ div >
3340
+ < div class ="sect2 ">
3233
3341
< h3 id ="_embedding_raw_javascript_code "> < a class ="anchor " href ="#_embedding_raw_javascript_code "> </ a > Embedding raw Javascript code</ h3 >
3234
3342
< div class ="admonitionblock warning ">
3235
3343
< table >
0 commit comments