Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndirectPromise seems to become undefined in the compiled code #2

Closed
jbhoot opened this issue Dec 6, 2020 · 3 comments
Closed

IndirectPromise seems to become undefined in the compiled code #2

jbhoot opened this issue Dec 6, 2020 · 3 comments

Comments

@jbhoot
Copy link

jbhoot commented Dec 6, 2020

Note that I have barely spent a couple of days on OCaml, let alone on jsoo or promise_jsoo. So forgive me for any stupid mistakes or poor code conventions.

Preface: I am writing a Firefox WebExtension using jsoo. To work smoothly with the Promise-dominant WE API, I opted for promise_jsoo.

On running the compiled code, I see an error ax is undefined bg.js:542, where bg.js is the compiled file spit by jsoo. The working of the ax variable is as follows:

ax=D.IndirectPromise,bI=D.Promise,ay=function(a){return bI.resolve(ax.wrap(a))};({});({"value":bB});var
bJ={"value":bC},bK=function(c,b){var
a=D.browser.browserSettings.useDocumentFonts.set(bJ);return ay(a.then(bZ(function(a){ax.unwrap(a);return ay(0)})))};D.browser.browserAction.onClicked.addListener(bK);var

If you notice, ax is set to be IndirectPromise. Thereafter, accessing it (most likely) in ax.wrap results in undefined error.

Are you aware why this might be happening?

For reference, following is the relevant portion of OCaml code:

let use_document_fonts = object%js
    val value = Js._true
end

let dont_use_document_fonts = object%js
    val value = Js._false
end

let handler tab event =
    let open Promise.Syntax in
    let useDocumentFonts = Unsafe.global##.browser##.browserSettings##.useDocumentFonts in

    let result = Promise.bind
        (fun result -> Promise.resolve None)
        (useDocumentFonts##set dont_use_document_fonts)
    in
    Promise.resolve result

useDocumentFonts##set returns a Promise as documented here:

browser.browserSettings.useDocumentFonts.set({value: false}).
  then(logResult);

I tried the let* binding too:

let handler tab event =
    let open Promise.Syntax in
    let useDocumentFonts = Unsafe.global##.browser##.browserSettings##.useDocumentFonts in
    let* result = useDocumentFonts##set dont_use_document_fonts in
    let () = Firebug.console##log result in
    Promise.resolve result

but in this case, the 'then' part of the code, or the 'in' part of the code where, console.log should print, is never invoked. So no error, but nothing else happens too.

Note that the useDocumentFonts##set dont_use_document_fonts actually works in both cases - I can see the relevant Firefox config value changing. Its just the then part that seems problematic.

Compile command:

 ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx \
          -package promise_jsoo -linkpkg -o bg.byte bg.ml

I read the Promise section of your blog https://mnxn.github.io/blog/ocaml/vscode-jsoo/, which makes me think that I am doing something wrong in terms of wrap and unwrap.

@jbhoot jbhoot changed the title IndirectPromise seems to become undefined in my codebase IndirectPromise seems to become undefined in the compiled code Dec 6, 2020
@jbhoot jbhoot closed this as completed Dec 6, 2020
@jbhoot jbhoot reopened this Dec 6, 2020
@mnxn
Copy link
Owner

mnxn commented Dec 6, 2020

which makes me think that I am doing something wrong in terms of wrap and unwrap.

Your code looks fine, my guess is that the build isn't including the dependencies in the final output. I assume you're just doing js_of_ocaml bg.byte to generate the JS file, but that won't include promise_jsoo in the final output.

I'm not very familiar with the details of using ocamlfind+ocamlc+js_of_ocaml directly, could you try using Dune to build your program? It what we use in the VSCode extension, which includes promise_jsoo successfully.

Writing this in a dune file should be sufficient:

(executable
 (name bg)
 (modes js)
 (libraries js_of_ocaml  js_of_ocaml-ppx promise_jsoo)
 (preprocess
  (pps js_of_ocaml-ppx)))

Afterwards, you can do dune build bg.bc.js in a shell, which will generate the JS to _build/default/bg.bc.js. This file will likely be larger that your bg.js, but that would be because it's including all the dependencies. To check, if you open the JS file, it should begin with something close to the following:

Expand Me

//# 1 "bg.bc.runtime.js"
// Generated by js_of_ocaml 3.8.0
(function(joo_global_object)
   {joo_global_object.IndirectPromise
    =
    function(promise){this.underlying = promise};
    joo_global_object.IndirectPromise.wrap
    =
    function(value)
     {return value
              !==
              undefined
              &&
              value
              !==
              null
              &&
              typeof value.then
              ===
              "function"
              ?new IndirectPromise(value)
              :value};
    joo_global_object.IndirectPromise.unwrap
    =
    function(value)
     {return value instanceof joo_global_object.IndirectPromise
              ?value.underlying
              :value}}
  (function(){return this}()));

@jbhoot
Copy link
Author

jbhoot commented Dec 6, 2020

That was it. ocamlfind + js_of_ocaml didn't include promise_jsoo in the compiled bg.js file, even though the ocamlfind ocamlc command clearly lists it as -package. I will ask around.

For now, dune works. Though even its --release build is a whopping 2.2MB. But it works atleast. Moving one step at a time.

@mnxn
Copy link
Owner

mnxn commented Dec 6, 2020

Great! Glad you got it working.

@mnxn mnxn closed this as completed Dec 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants