[
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: daily\n"
  },
  {
    "path": ".github/workflows/workflow.yml",
    "content": "name: Builds, tests & co\n\non:\n  - push\n  - pull_request\n\npermissions: read-all\n\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        os:\n          - ubuntu-latest\n          - macos-latest\n          - windows-latest\n        ocaml-compiler:\n          - 5\n          - 4\n        include:\n          - os: ubuntu-latest\n            ocaml-compiler: \"4.13\"\n\n    runs-on: ${{ matrix.os }}\n\n    steps:\n      - name: Checkout tree\n        uses: actions/checkout@v6\n\n      - name: Set-up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: latest\n\n      - name: Set-up OCaml\n        uses: ocaml/setup-ocaml@v3\n        with:\n          ocaml-compiler: ${{ matrix.ocaml-compiler }}\n\n      - run: opam install . --deps-only --with-test\n\n      - run: opam exec -- make\n\n      - run: opam exec -- make test\n\n  # lint-doc:\n  #   runs-on: ubuntu-latest\n  #   steps:\n  #     - name: Checkout tree\n  #       uses: actions/checkout@v6\n  #     - name: Set-up OCaml\n  #       uses: ocaml/setup-ocaml@v3\n  #       with:\n  #         ocaml-compiler: 5\n  #     - uses: ocaml/setup-ocaml/lint-doc@v3\n\n  # lint-fmt:\n  #   runs-on: ubuntu-latest\n  #   steps:\n  #     - name: Checkout tree\n  #       uses: actions/checkout@v6\n  #     - name: Set-up OCaml\n  #       uses: ocaml/setup-ocaml@v3\n  #       with:\n  #         ocaml-compiler: 5\n  #     - uses: ocaml/setup-ocaml/lint-fmt@v3\n\n  lint-opam:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout tree\n        uses: actions/checkout@v6\n      - name: Set-up OCaml\n        uses: ocaml/setup-ocaml@v3\n        with:\n          ocaml-compiler: 5\n      - uses: ocaml/setup-ocaml/lint-opam@v3\n"
  },
  {
    "path": ".gitignore",
    "content": "gen_js_api.install\nojs.install\n*.merlin\n_build\n_opam\n.vscode\n"
  },
  {
    "path": ".ocp-indent",
    "content": "match_clause=4\nstrict_with=auto\n"
  },
  {
    "path": "CHANGES.md",
    "content": "Changelog\n=========\n\nUnreleased\n----------\n\n- Support for binding to js_of_ocaml runtime primitives via `@`-prefixed payloads on `[@@js.global]` and `[@@@js.scope \"@...\"]`, enabling generated bindings to target values supplied by the JavaScript runtime.\n- Test suite updates adapted for wasm_of_ocaml.\n\nVersion 1.1.6\n-------------\n\n- GPR#181: Upgrade ppxlib dependency to 0.37.0 (=> support OCaml 5.4)\n\nVersion 1.1.5\n-------------\n\n- GPR#180: Fix for OCaml 5.3.0\n\nVersion 1.1.4\n-------------\n\n- GPR#176: Remove references to joo_global_object (@hhugo)\n- GPR#175: Support for simple module construction (@sbriais)\n\nVersion 1.1.3\n-------------\n\n- GPR#173: Compatibility with Wasm_of_ocaml (@vouillon)\n- GPR#171: Update build badge and remove unused travis config (@tmcgilchrist)\n\n\nVersion 1.1.2\n-------------\n\n- GPR#170: Make Ojs.iter_properties compatible with jsoo/effects (@vouillon)\n\nVersion 1.1.1\n-------------\n\n- GPR#167: Fix CI (@cannorin)\n- GPR#166: Support first class modules to treat type variables safely (@cannorin)\n\nVersion 1.1.0\n-------------\n\n- GPR#164:  Switch to js_of_ocaml.4.0 (@hhugo)\n- GPR#165:  Allow n-ary constructors in [@js.union] (@cannorin)\n\nVersion 1.0.9\n-------------\n\n- GPR#161: Fix broken link to VALUES.md (@joelburget)\n- GPR#154: Upgrade to ocaml/setup-ocaml@v2 (@smorimoto)\n- GPR#153: Support recursive modules (@cannorin)\n- GPR#152: [@@js.invoke] attribute to call the global object as a function (@cannorin)\n\nVersion 1.0.8\n-------------\n\n- GPR#149: Stop using OMP directly (@mlasson)\n- GPR#145: Add support for \"newable\" functions to [@@js.apply] (@cannorin)\n- GPR#143: Disable eta reduction for of_js and to_js of type aliases (@cannorin)\n- GPR#144: Disable \"Spurious js.\\* attribute\" error for @js.dummy (@cannorin, @mlasson)\n- GPR#146: Fix an edge-case bug of prepare_args\n\n\nVersion 1.0.7\n-------------\n\n- GPR#140: Adds a deprecation warning the automatic heuristic is used (@mlasson)\n- GPR#139: Rename things for backward compatibility (@mlasson)\n- GPR#135: UTF-8 support for (Ojs.get/set/delete) adaptions (@mlasson)\n- GPR#132: Add support for indexers and \"callable\" objects (@cannorin)\n- GPR#130: Javascript -> JavaScript (@smorimoto)\n- GPR#129: Add GitHub Actions workflow (@smorimoto)\n- GPR#128: Bucklescript -> ReScript (also add genType ppx as a resource) (@ryyppy)\n- GPR#127: Support boolean \"enum\"s and boolean union discriminators (@cannorin)\n- GPR#125: js.custom attribute for type declaration to support custom mapping #125 (@cannorin)\n- GPR#123: Upgrade ppx to the ocaml 4.11 ast (@hhugo)\n- GPR#120: Split runtime library to own package (@rgrinberg)\n- GPR#118: Add ppx tests setup (@jchavarri, @mlasson)\n- GPR#115: Support for functors and module inclusion (@mlasson)\n- GPR#114: Dependency tweaks (@rgrinberg)\n- GPR#113: Add support for type variables (@jchavarri, @mlasson)\n- GPR#111: Better ppxlib integration (@hhugo)\n- GPR#110: Include payload in extension node (@nojb)\n\nVersion 1.0.6\n-------------\n\n- GPR #101: Adds travis support + use ocaml-migrate-parsetree (@mlasson)\n- GPR #94: Typo: correct wrong 'apply_arr' to 'apply' (@facelesspanda)\n- GPR #89: Update the opam file (@hhugo)\n- GPR #87: Switch to dune (@hhugo)\n- GPR #88: Fix some warnings (@hhugo)\n- GRP #85: Adapt to 4.08 (@nojb)\n\nVersion 1.0.5\n-------------\n\n- Adapt to OCaml 4.06\n\n\nVersion 1.0.4\n-------------\n\n- Adapt to OCaml 4.05.\n"
  },
  {
    "path": "CLASSES.md",
    "content": "Class wrapping in gen_js_api\n============================\n\ngen_js_api can bind JavaScript objects into OCaml abstract types with\nassociated functions (to get/set property and to call methods).  This\nform of binding is quite efficient, since the opaque OCaml values are\njust the underlying JavaScript objects, with no mapping or wrapping.\nIn addition to that, gen_js_api provides ways to **wrap JavaScript\nobjects into OCaml objects**.  This adds some runtime overhead, but\nallows users to use standard OO syntax in OCaml and to rely on\ninheritance (to mimic similar hierarchy on the JS side).\n\nIn addition to the runtime overhead, wrapping JS objects as OCaml\nobjects also forces to define all methods at once.  With opaque\nbindings, methods of a given JS \"class\" can be spread over multiple\nOCaml modules.  This can be especially useful to mimic the behavior of\nJS library addins that extends the library's object prototype with\nmore methods.\n\n\n\n\nClass wrapping\n--------------\n\nAn interface processed by js_of_ocaml can define an OCaml class used\nto wrap some JavaScript objects:\n\n    ````\n    class my_class: Ojs.t ->\n      object\n        inherit Ojs.obj\n        (* method declarations *)\n        ....\n      end\n    ````\n\nThe class must inherit from `Ojs.obj` directly or indirectly.  This class\nsimply defines a `to_js` method (returning the underlying `Ojs.t` object).\n\nSuch a class declaration produces in the implementation a class\ndefinition with the list of `inherit` clauses (passing the `Ojs.t`\nhandle to each of them) and a definition for all listed methods.  It\nalso produces a standard pair of `*_to_js`/`*_of_js` functions (the\n`*_to_js` function calls the `to_js` method inherited from `Ojs.obj`,\nand `*_of_js` calls the constructor of the class).\n\n\nMethod binding\n--------------\n\n- Property getter:\n\n  ````\n    method foo: t\n       [@@js.get \"foo\"]\n  ````\n\n\n- Property setter:\n\n  ````\n    method set_foo: t -> unit\n       [@@js.set \"foo\"]\n  ````\n\n\n- Method call:\n\n  ````\n    method f: t -> unit\n      [@@js.call \"f\"]\n  ````\n\nAs always, the names can be omitted if they correspond to the implicit\nnaming scheme.\n\nPrior to version 1.0.7, as for value bindings, some implicit rules applied,\nso that `[@@js.*]` attributes could often be omitted (in particular, in\nall the examples above).\n\nThe following rules were applied in order:\n\n- If the method is a function with one argument `t -> unit` and its\n  name starts with `set_`, then the declaration is assumed to be a\n  `[@@js.set]` property setter (on the property whose name is obtained\n  by dropping the `set_` prefix).\n\n- If the method is a function, then the definition is assumed to be a\n  `[@@js.call]` method call.\n\n- Otherwise, the method is assumed to be a `[@@js.get]` property getter.\n\nBut since version 1.0.7, *this feature has been deprecated*; all method\nshould be explicitly annotated or a preprocessor warning will be emitted.\n\nConstructors\n------------\n\nThe default constructor for a class wrapper is necessarily an `Ojs.t` object\n(see above).  (Note: it would be easy to allow such classes to take a\nvalue of an arbitrary JS-able type, but this would make it more\ndifficult to support inheritance.)\n\nIt is possible to bind to actual JS constructors declarations such as:\n\n ````\n  class foo: string -> my_class\n ````\n\nCalling this constructor is then implemented by calling the JavaScript\nconstructor of the same name, and wrapping the resulting object with\nthe `my_class` wrapper.  This is similar to defining:\n\n  ````\n    val foo: string -> my_class\n      [@@js.new]\n  ````\n\nbut allows writing `new foo(...)` instead of `foo(...)`.\n\nA custom name can be provided with a `[@@js.new]` attribute:\n\n ````\n  class foo: string -> my_class\n    [@@js.new \"MyConstr\"]\n ````\n"
  },
  {
    "path": "IMPLGEN.md",
    "content": "gen_js_api: generate implementations from interfaces\n====================================================\n\nThe primary operating mode for gen_js_api is to generate .ml\nimplementation from annotated .mli interfaces.  These interfaces must\nfollow a certain shape.  They describe both the JavaScript components\nto be imported and how they should be reflected within OCaml.\n\nUsage\n-----\n\n\n```\n  $ gen_js_api my_module.mli\n```\n\nor with findlib:\n\n```\n  $ ocamlfind gen_js_api/gen_js_api my_module.mli\n```\n\nThis generates my_module.ml.\n\n\n\nSupported declarations\n----------------------\n\nInterfaces processed by gen_js_api can currently contain:\n\n  - [Type declarations](TYPES.md):\n\n    ````\n    type t = ...\n    ````\n\n    See [this page](TYPES.md) for a description of supported types.\n    Such a type declaration produces in the implementation an identical\n    defininition, and associated `*_to_js` and `*_of_js` functions\n    (which can be manually exported if needed).\n\n\n  - [Value declarations](VALUES.md):\n\n    ````\n    val f: tyexpr\n    ````\n\n    This produces in the implementation a definition for such a value,\n    whose content depends on three elements: the name of the value\n    (`f` in the example), its declared type (`tyexpr`), and possible\n    `[@@js.xxx]` attributes attached to the declaration in the interface.\n\n    See [this page](VALUES.md) for supported forms of value declarations.\n\n\n  - Sub-modules:\n\n    ````\n    module M : sig\n      ...\n    end\n    ````\n\n    This naturally produces in the implementation a corresponding sub-module:\n\n    ````\n    module M = struct\n      ...\n    end\n    ````\n\n  - Module aliases:\n\n    If a module alias is declared in the interface, like:\n\n    ```ocaml\n    module M = <Module Path>\n    ```\n\n    it is directly reflected in the generated implementation without modifications.\n\n  - Module inclusion:\n\n    To include a module `M` in the generated implementation, simply add\n\n    ```ocaml\n    include (module type of M)\n    ```\n    in the corresponding interface.\n\n  - [Class declarations](CLASSES.md)\n\n\n\nVerbatim sections\n-----------------\n\nA floating attribute `[@@@js.stop]` tells the tool to ignore the\nremaining items until the end of the current (possibly nested)\nsignature.  This can be reverted with a floating attribute\n`[@@@js.start]`.  This system makes it possible to specify fragments\nof the interface that should not generate any code in the\nimplementation.\n\nA floating `[@@@js.implem ...]` tells the tool to generate some custom\ncode in the implementation. The payload `...` is an OCaml structure,\nwhich is processed in the same way as in [ppx mode](PPX.md).\n\n\nExample:\n\n```ocaml\n\n  [@@@js.stop]\n     val foo: int -> unit\n  [@@@js.start]\n\n  [@@@js.implem\n\n       val foo_internal: string -> int -> unit\n         [@@js.global \"foo\"]\n       let foo = foo_internal \"\"\n\n  ]\n```\n\n\nFor the common case where verbatim sections are used to create custom\nvalue bindings, a `[@@js.custom]` attribute can be applied to a `val`\ndeclaration.  The effect is that the `val` declaration itself is ignored\n(nothing is generated in the implementation), and a structure can be\nprovided as the payload of the attribute.  The example above is equivalent\nto:\n\n```ocaml\n  val foo: int -> int\n  [@@js.custom\n       val foo_internal: string -> int -> unit\n         [@@js.global \"foo\"]\n       let foo = foo_internal \"\"\n  ]\n```\n\nand to:\n\n```ocaml\n  val foo: int -> int\n  [@@js.custom]\n\n  [@@js.implem\n        ...\n  ]\n```\n"
  },
  {
    "path": "INSTALL_AND_USE.md",
    "content": "gen_js_api: installation and usage instructions\n===============================================\n\n\nDependencies\n------------\n\ngen_js_api does not have any external build-time dependency except\nthe OCaml compiler (version 4.03).  Of course, it will be used\nin conjuncion with the js_of_ocaml compiler and runtime support.\n\n\nInstallation (with OPAM)\n------------------------\n\n````\nopam install gen_js_api\n````\n\nOr, to track the development version:\n\n````\nopam pin add gen_js_api https://github.com/LexiFi/gen_js_api.git\n````\n\nManual installation\n-------------------\n\n````\ngit clone https://github.com/LexiFi/gen_js_api.git\ncd gen_js_api\nmake all\nmake install  # assuming opam-installer is installed\n````\n\nUsage (with dune)\n-----------------\n\n - Invoking the [standalone tool](IMPLGEN.md) (`.mli` -> `.ml` generator):\n\n   ```\n   (rule\n     (targets my_unit.ml)\n     (deps my_unit.mli)\n     (action (run %{bin:gen_js_api} %{deps})))\n   ```\n\n - Compiling binding (`.mli` and generated `.ml` files), user\n   code which rely on the `Ojs` or with the [ppx processor](PPX.md):\n\n   ```\n   (executables\n     (names test_jquery)\n     (js_of_ocaml)\n     (libraries ojs js_of_ocaml)\n     (preprocess (pps gen_js_api.ppx))\n     (modes byte)\n   )\n   ```\n\n - Compiling into JavaScript: Just ask dune to build the `*.bc.js`\n   target. (e.g. `dune build test_jquery.bc.js`)\n\nUsage (with ocamlfind)\n----------------------\n\n - Invoking the [standalone tool](IMPLGEN.md) (`.mli` -> `.ml` generator):\n\n   ```\n   ocamlfind gen_js_api/gen_js_api my_unit.mli\n   ```\n\n - Compiling binding (`.mli` and generated `.ml` files) and user\n   code which rely on the `Ojs` module:\n\n   ```\n   ocamlfind ocamlc -package gen_js_api my_unit.mli\n   ocamlfind ocamlc -package gen_js_api my_unit.ml\n   ```\n\n - Compiling with the [ppx processor](PPX.md):\n\n   ```\n   ocamlfind ocamlc -c -package gen_js_api my_prog.ml\n   ```\n\n - Linking the bytecode program:\n\n   ```\n   ocamlfind ocamlc -o my_prog -package gen_js_api -linkpkg ...\n   ```\n\n - Compiling into JavaScript:\n\n   ```\n   js_of_ocaml -o my_prog.js +gen_js_api/ojs_runtime.js my_prog\n   ```\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright 2015 by LexiFi.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "LOW_LEVEL_BINDING.md",
    "content": "gen_js_api: low-level binding to JavaScript\n===========================================\n\nThe code generated by gen_js_api relies on a `Ojs` module (the runtime\nsupport library).  In the same way that OCaml `Obj` module exposes\n(unsafe) operations to manipulate arbitrary OCaml values (after\ncasting them to a universal type `Obj.t`), `Ojs` allows to manipulate\narbitrary JavaScript values through an `Ojs.t` universal type.\n\n`Ojs` encourages to think of native JS values as being \"foreign\"\nvalues, even though in practice, all OCaml values are represented as\nJS values when the OCaml code is compiled with js_of_ocaml.  In\nparticular, `Ojs` does not expose a function allowing to cast an\narbitrary OCaml value to `Ojs.t` (this can always be done with\n`Obj.magic`).\n\n`Ojs.t` is similar to `Js.Unsafe.any` type, but it abstracts away from\nspecific properties of how js_of_ocaml represents OCaml values.  For\ninstance the fact, that OCaml integers are encoded directly as JS\nnumbers is not apparent in `Ojs`, and if this property was to change,\nclient code would be unaffected.\n\nAbstracting away from js_of_ocaml encoding would also make it easy to\nchange the way OCaml and JS are connected (either because of changes\nin js_of_ocaml's encoding of OCaml values, or because an entirely\ndifferent technology is used, such as an OCaml bytecode interpreter\nwritten in JavaScript or a JavaScript engine linked with native OCaml\ncode).\n\nNote that code generated by gen_js_api doesn't depend on js_of_ocaml's\nstandard library (`Js` module), only on js_of_ocaml's runtime system.\nOur local `Ojs` interface maps directly to primitives provided by\njs_of_ocaml's runtime.\n\n\nUsers of gen_js_api would not use `Ojs` very often, except to define\n\"opaque sub-types\" of `Ojs.t` in order to represent JS \"classes\" or\n\"interfaces\":\n\n```ocaml\ntype t = private Ojs.t\n```\n\nOccasionnaly, it it useful to go down to `Ojs` in order to define\n**custom mappings** between JS and OCaml.  For instance, one can\ndefine a type for association lists indexed on strings in OCaml that\nare mapped to JS objects:\n\n```ocaml\nmodule Dict : sig\n  type 'a t = (string * 'a) list\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\nend = struct\n  type 'a t = (string * 'a) list\n\n  let t_to_js ml2js l =\n    let o = Ojs.empty_obj () in\n    List.iter (fun (k, v) -> Ojs.set o k (ml2js v)) l;\n    o\n\n  let t_of_js js2ml o =\n    let l = ref [] in\n    Ojs.iter_properties o\n      (fun k -> l := (k, js2ml (Ojs.get o k)) :: !l);\n    !l\nend\n```\n"
  },
  {
    "path": "Makefile",
    "content": "# The package gen_js_api is released under the terms of an MIT-like license.\n# See the attached LICENSE file.\n# Copyright 2015 by LexiFi.\n\n.PHONY: all examples test test-promote clean install uninstall doc reindent publish\n\nall:\n\tdune build @install @DEFAULT\n\nexamples:\n\tdune build @examples/DEFAULT\n\ndoc:\n\tdune build @doc\n\ntest:\n\tdune build @runtest\n\ntest-promote:\n\tdune build @runtest --auto-promote\n\nclean:\n\tdune clean\n\nPREFIX := $$(opam config var prefix)\n\ninstall:\n\topam-installer --prefix $(PREFIX) gen_js_api.install\n\nuninstall:\n\topam-installer -u --prefix $(PREFIX) gen_js_api.install\n\nreindent:\n\tgit ls-files *.ml *.mli | grep -v expected | xargs ocp-indent -i\n\nVERSION := $$(opam show . | grep \"^version\" | sort -u | sed 's/version *//')\n\npublish: all\n\techo \"Publishing v$(VERSION) ...\" \n\tgit tag -a v$(VERSION)\n\tgit push origin v$(VERSION)\n\topam publish\n\n\n\n\t\n\t\n"
  },
  {
    "path": "NAMING.md",
    "content": "gen_js_api: default naming convention\n=====================================\n\nJavaScript names corresponding to bound components can always be\nspecified explicitly (with the use of attributes).  When the naming is\nleft implicit, a JavaScript name is automatically derived from the\nOCaml name by applying the following rules:\n\n  1. uppercasing every character following an underscore;\n\n  2. removing every underscore;\n\n  3. uppercasing the first character when generating object constructor names.\n\nThis automatic naming convention can be partially disabled by adding\nan attribute `[@js.verbatim_names]` on outer structures. When the attribute\n`[@js.verbatim_names]` is inherited from the context, the rule 1 and 2 are\ndisabled.\n\nFor instance,\n\n```ocaml\ntype myType = { x_coord : int; y_coord : int [@js \"Y\"]}\n```\n\nis mapped to a JS record with two fields named \"xCoord\" and \"Y\" whereas\n\n```ocaml\ntype myType = { x_coord : int; y_coord : int [@js \"Y\"]} [@@js.verbatim_names]\n```\n\nis mapped to a JS record with two fields named \"x_coord\" and \"y\".\n"
  },
  {
    "path": "NODE_RUNTIME_BINDINGS.md",
    "content": "# Binding Node.js Modules with Runtime Primitives\n\nThis guide shows how to use the new runtime primitive support in `gen_js_api` to bind Node.js libraries that are usually obtained with `require(...)`. The feature hinges on two additions:\n\n- any `[@@js.global \"@primitive_name\"]` binding returns an `Ojs.t` pointing to a primitive exported by the JavaScript runtime;\n- a scope string that starts with `@` (for example `[@@@js.scope \"@node_fs.promises\"]`) resolves the first path component through the runtime primitives before following regular properties.\n\nTogether, those tools let you keep your bindings declarative while delegating the actual `require` calls to a tiny JavaScript stub.\n\n## Example layout\n\n```\nruntime_primitives/\n  dune\n  imports.js\n  imports.wat\n  bindings.mli\n  example.ml\n```\n\n### Step 1 - expose the runtime primitives\n\nCreate a JavaScript file that `require`s the Node modules you need and publishes them as js_of_ocaml runtime primitives. The js_of_ocaml linker recognises `//Provides: <name>` comments and registers the value under that name at startup.\n\n```javascript\n// runtime_primitives/imports.js\n'use strict';\n\n//Provides: node_path\nvar node_path = require('path');\n\n//Provides: node_fs\nvar node_fs = require('fs');\n\n//Provides: node_version\nvar node_version = require('process').version;\n\n//Provides: node_console\nvar node_console = console.log;\n\n```\n\nWhen targeting WebAssembly you also need to expose the primitives through a `.wat` shim so that `wasm_of_ocaml` can import them at runtime:\n\n```wat\n;; runtime_primitives/imports.wat\n(global (export \"_node_path\") (import \"js\" \"node_path\") anyref)\n(global (export \"_node_fs\") (import \"js\" \"node_fs\") anyref)\n(global (export \"_node_version\") (import \"js\" \"node_version\") anyref)\n(global (export \"_node_console\") (import \"js\" \"node_console\") anyref)\n```\n\nList this file in your dune stanza so that js_of_ocaml ships it with the compiled artefacts:\n\n```\n; runtime_primitives/dune\n(rule\n (targets bindings.ml)\n (deps bindings.mli)\n (action (run gen_js_api %{deps})))\n\n(executable\n (name example)\n (libraries ojs)\n (preprocess (pps gen_js_api.ppx))\n (modes js wasm)\n (js_of_ocaml (javascript_files imports.js))\n (wasm_of_ocaml (javascript_files imports.js imports.wat)))\n```\n\nAdding the file to both `js_of_ocaml` and `wasm_of_ocaml` makes the primitives available in browser and wasm builds alike.\n\n### Step 2 - bind module functions with `[@js.scope \"@...\"]`\n\nUse `module [@js.scope \"@primitive\"]` blocks to call methods on runtime primitives without manually threading the module objects. The interface below covers the synchronous filesystem API used in the reference JavaScript while keeping the underlying modules abstract.\n\n```ocaml\n(* runtime_primitives/bindings.mli *)\nmodule [@js.scope \"@node_fs\"] Fs : sig\n  val write_file_sync : string -> string -> unit [@@js.global \"writeFileSync\"]\n  val read_file_sync : string -> encoding:string -> string [@@js.global \"readFileSync\"]\n  val readdir_sync : string -> string array [@@js.global \"readdirSync\"]\n  val append_file_sync : string -> string -> unit [@@js.global \"appendFileSync\"]\nend\n\nmodule [@js.scope \"@node_path\"] Path : sig\n  val separator: string [@@js.global \"sep\"]\n  val join : (string list [@js.variadic]) -> string [@@js.global \"join\"]\nend\n```\nEach module-level scope starts with `@`, so the ppx turns calls like `Fs.write_file_sync` into direct invocations on the corresponding Node module (`node_fs.writeFileSync` in this case) without requiring you to pass the module object around.\n\n### Step 3 - bind direct values with `@`-prefixed `[@@js.global]`\n\nWhen you only need the primitive itself—such as a constant exported by a Node module—use the `@` prefix inside `[@@js.global]` to obtain it directly as an OCaml value.\n\n```ocaml\n(* runtime_primitives/primitives_bindings.mli continued *)\n\nval node_version : string [@@js.global \"@node_version\"]\nval log : string -> unit [@@js.global \"@node_console\"]\n```\n\nThese expand to `Jsoo_runtime.Js.runtime_value ...` calls and convert the results to the requested OCaml types, so you can expose constants or functions alongside the scoped modules described above.\n\n### Step 4 - port the JavaScript example\n\n`main.ml` mirrors the original JavaScript snippet that writes, reads, appends, and re-reads a file while logging progress to the Node console. It relies on the scoped `Fs`/`Path` modules plus the direct `log`, `path_separator`, and `node_version` values.\n\n```ocaml\nopen Bindings\n\nlet initial_content = \"Hello, Node.js!\"\nlet appended_line = \"\\nAppending a new line.\"\nlet encoding = \"utf-8\"\nlet filename = \"example.txt\"\n\nlet run () =\n  let file = Path.join [\".\"; filename] in\n\n  Fs.write_file_sync file initial_content;\n\n  let content = Fs.read_file_sync file ~encoding in\n  if content <> initial_content then\n    failwith \"Unexpected initial content\";\n  log (\"File content: \" ^ content);\n\n  let files = Fs.readdir_sync \".\" |> Array.to_list in\n  if not (List.mem filename files) then\n    failwith \"example.txt missing from directory listing\";\n  log (\"Files in current directory: \" ^ String.concat \", \" files);\n\n  Fs.append_file_sync file appended_line;\n\n  let updated = Fs.read_file_sync file ~encoding in\n  if updated <> initial_content ^ appended_line then\n    failwith \"Append failed\";\n  log (\"Updated content: \" ^ updated);\n  log (\"Path separator reported by Node: \" ^ Path.separator);\n  log (\"Node.js version: \" ^ node_version)\n\n\nlet () = run ()\n```\n\n### Putting it together\n\n1. Declare each required Node module once in `imports.js` (and mirror them in `imports.wat` for wasm) using the js_of_ocaml `//Provides:` convention.\n2. Export the files through dune so that the js_of_ocaml toolchain registers those primitives at runtime.\n3. Map node modules in OCaml with `module [@js.scope \"@primitive\"]` blocks, and use `@`-prefixed `[@@js.global]` bindings for direct values.\n4. Consume the generated modules from OCaml exactly as you would in JavaScript, as shown in `example.ml`.\n\nWith these pieces in place you can keep writing high-level `gen_js_api` bindings while relying on the new runtime primitive support to bridge your OCaml code to Node-specific libraries provided via `require`.\n"
  },
  {
    "path": "PPX.md",
    "content": "gen_js_api: ppx mode\n====================\n\nWhile the primary mode of operation for gen_js_api is to generate an\n.ml file from an annotated .mli file, it is also possible to use it as\na ppx preprocessor on an .ml file directly to insert local JS bindings.\n\nThe `-ppx` command-line option must be the first argument passed\nto gen_js_api to enable the ppx mode:\n\n```\n  $ ocamlc -c -ppx \"gen_js_api -ppx\" my_prog.ml\n```\n\nor with findlib:\n\n```\n  $ ocamlfind ocamlc -c -package gen_js_api my_prog.ml\n```\n\n\nNote: the ppx currently does nothing on `.mli` files.\n\n\nSeveral forms are supported:\n\n - `[%js: <signature>]` extension as a module expression.  Examples:\n\n   ````\n     include [%js: <signature>]\n\n     module M = [%js: <signature>]\n   ````\n\n   The signature is processed as if it were found in an .mli file, and\n   the resulting structure is inserted in place of the `[%js: ...]`\n   extension.  See [this page](IMPLGEN.md) for a list\n   of declarations supported in such interfaces.\n\n - `[@@js]` attributes on type declarations.\n\n   Example:\n\n   ````\n     type t = { x : int; y : int } [@@js]\n   ````\n\n   This generates the corresponding `*_of_js` and `*_to_js` functions.\n   In case of a multi-type declaration, each type must be annotated\n   with `[@@js]` (if needed). See [this page](TYPES.md) for a description\n   of support forms of type declarations.\n\n - `[%js.to: ty]` and `[%js.of: ty]` extensions on expressions.\n\n   Example:\n\n   ````\n     let x : Ojs.t = [%js.of: int list]  [ 10; 20; 30 ]\n   ````\n\n   This form generates the mapping function associated to a JS-able type.\n   See [this page](TYPES.md) for a description of JS-able type.\n"
  },
  {
    "path": "README.md",
    "content": "gen_js_api: easy OCaml bindings for JavaScript libraries\n========================================================\n\n[![Build Status](https://github.com/LexiFi/gen_js_api/actions/workflows/workflow.yml/badge.svg)](https://github.com/LexiFi/gen_js_api/actions/workflows/workflow.yml)\n\nOverview\n--------\n\ngen_js_api aims at simplifying the creation of OCaml bindings for\nJavaScript libraries.  It must currently be used with the [js_of_ocaml\ncompiler](https://github.com/ocsigen/js_of_ocaml), although other ways\nto run OCaml code \"against\" JavaScript might be supported later with\nthe same binding definitions (for instance,\n[Bucklescript](https://github.com/bloomberg/bucklescript),\nor direct embedding of a JS engine in a native OCaml application).\n\ngen_js_api is based on the following ideas:\n\n - Authors of bindings write OCaml signatures for JavaScript libraries\n   and the tool generates the actual binding code with a combination\n   of implicit conventions and explicit annotations.\n\n - The generated binding code takes care of translating values between\n   OCaml and JavaScript and of dealing with JavaScript calling\n   conventions.\n\n - All syntactic processing is done by authors of bindings: the client\n   code is normal OCaml code and does not depend on custom syntax nor\n   on JS-specific types.\n\n\ngen_js_api can be used in two complementary ways:\n\n  - [Generating .ml implementations from annotated .mli interfaces](IMPLGEN.md),\n    in order to create the code for stub libraries.\n\n  - As a [ppx preprocessor on implementations](PPX.md) to define local\n    bindings.\n\n\n\nExamples\n--------\n\nThe repository contains some examples of OCaml bindings to JavaScript\nlibraries created with gen_js_api:\n\n - Very partial [bindings to jQuery](examples/misc/jquery.mli), with\n   some [example client code](examples/misc/test_jquery.ml).\n\n - Partial bindings to JavaScript [strings and\n   regexps](examples/misc/js_str.mli) and JavaScript\n   [dates](examples/js_date.mli).\n\n - Some [ad hoc test](examples/test) to exercise various features.\n\n - An example of a self-contained program, a [simple\n   calculator](examples/calc/calc.ml), implementing local .bindings\n\nDocumentation\n-------------\n\n  - [Install and use](INSTALL_AND_USE.md)\n  - [Low-level binding to JavaScript](LOW_LEVEL_BINDING.md)\n  - [Using gen_js_api to generate .ml from .mli](IMPLGEN.md)\n  - [Using gen_js_api as a ppx processor](PPX.md)\n  - [Default naming convention](NAMING.md)\n  - [JS-able types and type declarations](TYPES.md)\n  - [Value bindings](VALUES.md)\n  - [Class-wrapping bindings](CLASSES.md)\n  - [TODO list](TODO.md)\n\n\nRelated projects\n----------------\n\n  - [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml): The compiler\n    and runtime system on which gen_js_api relies. (Note: gen_js_api\n    doesn't depend on js_of_ocaml's OCaml library, nor on its language\n    extension.)\n\n  - [goji](https://github.com/klakplok/goji): A DSL to describe OCaml\n    bindings for JavaScript libraries.\n\n  - [DefinitelyMaybeTyped](https://github.com/andrewray/DefinitelyMaybeTyped):\n    A project to parse\n    [DefinitelyTyped](https://github.com/borisyankov/DefinitelyTyped)\n    interfaces and produce OCaml interfaces.\n\n  - [ReScript](https://github.com/rescript-lang/rescript-compiler):\n    Another compiler from OCaml to JavaScript, featuring the [genType](https://github.com/reason-association/genType) ppx for generating TS / Flow types and runtime converters.\n\nAbout\n-----\n\ngen_js_api has been created by LexiFi for porting a web application\nfrom JavaScript to OCaml.  The tool has been used in production since\n2015.\n\nThis gen_js_api package is licensed by LexiFi under the terms of the\nMIT license.\n\nSee see [Changelog](CHANGES.md)\n\nContact: alain.frisch@lexifi.com\n\nContributors:\n\n - Alain Frisch\n - Sebastien Briais\n"
  },
  {
    "path": "TODO.md",
    "content": "TODO list for gen_js_api\n========================\n\n- Create reasonably complete bindings for JavaScript's stdlib\n  (string, regexp), for the DOM, for jQuery, etc.\n\n- Add a safe mode, where the generated code is augmented with explicit\n  checks (e.g. when casting a JS value to a string or integer, when\n  accessing a property, etc).\n\n- Optimize generated code (for instance, lift calls to string_of_js on\n  literals).\n\n- Idea: to facilitate binding and calling multiple methods at once,\n  provide something like (jQuery example):\n\n    ```ocaml\n    val set: ?text:string -> ?hide:unit -> ?css:(string * string) -> t -> unit\n     [@@js.multicall]\n    ```\n\n\n  One can then write:\n\n     ```ocaml\n     set\n       ~text:\"Hello\"\n       ~hide:()\n       node\n     ```\n\n  Each provided argument yields one method call (in the order where\n  arguments are declared, of course).  This is mostly interesting when\n  methods are used to \"set\" internal properties, and when the different\n  calls commute.\n\n  This could be simulated with:\n\n  ```ocaml\n\n    val set: ?text:string -> ?hide:unit -> ?css:(string * string) -> t -> unit\n      [@@@js.custom\n      val set_text: t -> string -> unit\n        [@@js.meth \"text\"]\n\n      let set ?text ... x =\n        Option.iter (set_text x) text;\n        ...\n      ]\n  ```\n\n\n- Optional arguments on JS methods are usually at the end.  But this\n  forces to add a `unit` pseudo-argument.  One could have an\n  (optional) convention to push optional arguments at the end of the JS\n  call even though there are not in the OCaml type.  This would also\n  work for instance methods:\n\n  ```ocaml\n  val foo: ?bla:int -> t -> int\n  ```\n\n  instead of:\n\n  ```ocaml\n  val foo: t -> ?bla:int -> unit -> int\n  ```\n\n- When defining a binding to a function with `[@@js.global\n  \"foo.bar\"]`, this is currently interpreted as calling this global\n  function.  One could interpret it as calling the bar method on\n  object foo, which would have the effect of assigning `this` during\n  the function evaluation.\n"
  },
  {
    "path": "TYPES.md",
    "content": "Types supported in gen_js_api\n=============================\n\nJS-able types\n-------------\n\nA JS-able type is an OCaml type whose values can be mapped to and from\nJavaScript objects.\n\nThe following types are supported out-of-the-box:\n\n - Basic built-in types: `string`, `int`, `bool`, `float` and `Ojs.t`.\n\n - Tuples of JS-able types (mapped to JS arrays).\n\n - Sequences of JS-able types: `array` and `list`, both mapped to JS\n   arrays (which are assumed to be indexed by integers 0..length-1).\n\n - Options on JS-able types.  They are mapped to the same type as\n   their parameter: `None` is mapped to JS `null` value, and both\n   `null` and `undefined` are mapped back to `None`.  This encoding\n   doesn't support nested options in a faithful way.\n\n - Arrows (see section below).\n\n - Polymorphic variants with only constant variants are supported\n   (see the section on enums below).\n\n - Polymorphic variants can also be used to encode non-discriminated\n   unions on the JS side (see the section on union types below).\n\n - Polymorphic variants can also be used to encode discriminated\n   unions on the JS side (see the section on discriminated union types\n   below).\n\n - Free type variables like `'a`, they will involve no runtime\n   mapping when moving between OCaml and JS (see type variable section).\n\nAn arbitrary non-parametrized type with path `M.t` is JS-able if the\nfollowing two values are available in module `M`:\n\n```ocaml\nval t_to_js: t -> Ojs.t\nval t_of_js: Ojs.t -> t\n```\n\nThe name of these values is obtained by appending `_of_js` or `_to_js`\nto the local name of the type.  It is thus possible to define JS-able\nmanually by defining these two functions.  Type and class declarations\nprocessed by gen_js_api (see sections below) create JS-able type (by\ngenerating those functions automatically).\n\nParametrized types can also be JS-able.  It is currently assumed that\nsuch types are covariant in each of their parameter.  Mapping\nfunctions take extra arguments corresponding to the mapper for each\nparameter.  For instance, a type `'a t` would need to come with the following\nfunctions:\n\n```ocaml\nval t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\nval t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n```\n\nArrow types\n-----------\n\nArrow types can also be used in contexts that expect JS-able types.\nAll arguments must be JS-able types, and a final `unit`\npseudo-argument is allowed (and mandatory when there is no real\nargument).  The function's result can be either a JS-able type or\n`unit`.  Note that `unit` is not considered as a proper JS-able type:\nit is only allowed in these two contexts (as the result, or the final\npseudo-argument).\n\nArguments can be **labelled or optional**.  Labels are simply ignored\non the JS side.  Optional arguments have different treatments:\n\n - When mapping an OCaml function to JS (e.g. a callback), optional\n   arguments are treated as normal values of an option type (i.e.\n   both `null` and `undefined` are mapped to `None`).\n\n - When mapping a JS function to OCaml, it is possible to specify\n   a default value to fill in a missing argument:\n\n   ```ocaml\n   val f: t -> ?x:(int [@js.default 0]) -> unit -> t\n   ```\n\n   If no default value is provided and the argument is missing, the\n   argument is *dropped* from the list of arguments passed to the JS\n   call (this apply to function/method/constructor calls).\n\n - In `[@@js.builder]` values, missing optional arguments are ignored\n   (they don't create any property on the object).\n\n\nThere is a special treatment for optional argument on a\n`[@js.variadic]` argument (see below), in which case a missing value\nis interpreted as an empty list (i.e. no extra arguments).\n\n\nWhen mapping an OCaml function to JS, the **function arity** is the\nnumber of real arguments (not counting the final `unit`) and the\nsemantics is the standard one for JS functions: missing arguments are\nfilled with `undefined` and extra arguments are dropped.  The correct\nway to support a calling convention where the JS caller might not\nprovide all arguments to a function defined in OCaml is to use\noptional arguments (or just arguments with option types) on the OCaml\nside.\n\nIn order to define **functions that return functions**, one can put a\n`[@js.dummy]` attribute (or any arbitrary attribute) on the resulting type :\n\n```ocaml\nt1 -> (t2 -> t3 [@js.dummy])\n```\n\nWithout the attribute, such a type would be parsed as a function of\narity 2 (returning type `t3`).\n\n\n**Variadic functions** are supported, by adding a `[@js.variadic]`\nattribute on the last parameter (which will represent all remaining\narguments):\n\n```ocaml\nval sep: string -> (string list [@js.variadic]) -> string\n```\n\nType declarations\n-----------------\n\nAll type declarations processed by gen_js_api create JS-able types,\ni.e.  associated `*_to_js` and `*_to_js` mapping functions.  A\noptional \"private\" modifier is allowed on the type declaration (in the\ninterface) and dropped from the generated definition (in the\nimplementation).  Mutually recursive type declarations are supported.\n\n\n- \"Abstract\" subtype of `Ojs.t`:\n\n    ```ocaml\n    type t = private Ojs.t\n    ```\n\n  This is used to bind to JS \"opaque\" objects, with no runtime mapping\n  involved when moving between OCaml and JS (mapping functions are the\n  identity).\n\n- Abstract type\n\n   ```ocaml\n   type t\n   ```\n\n  This will generate `type t = Ojs.t` in the implementation.  This\n  is very similar to the case above.\n\n- Type abbreviation:\n\n    ```ocaml\n    type t = tyexp\n    ```\n\n  (formally, abstract types with a manifest).  This assumes that the\n  abbreviated type expression is itself JS-able.  Note that the first\n  kind of type declaration above (abstract subtypes of `Ojs.t`) are\n  a special kind of such declaration, since `abstract` is always dropped\n  and `Ojs.t` is JS-able.\n\n- Record declaration:\n\n    ```ocaml\n    type t = { .... }\n    ```\n\n  This assumes that the type for all fields are JS-able.  Fields can\n  be mutable (but conversions still create copies).\n  Polymorphic fields are not yet supported.\n\n  OCaml record values of this type are mapped to JS objects (one\n  property per field).  By default, property names are equal to OCaml\n  labels, but this can be changed manually with a `[@js]` attribute.\n\n  ```ocaml\n  type myType = { x : int; y : int [@js \"Y\"]}\n  ```\n\n- Parametrized Type:\n\n  It is allowed to parametrize types processed by gen_js_api as long as\n  type variables does not occur at contravariant positions.\n\n  For instance :\n  ```ocaml\n    type ('a, 'b) coord = { x : 'a; y : 'b}\n  ```\n  is accepted while :\n  ```ocaml\n    type 'a t = 'a -> int\n  ```\n  is rejected.\n\n- Sum type declaration, mapped to enums (see Enums section).\n\n- Sum type declaration with non constant constructors, mapped to records with a discriminator field (see Sum types section).\n\n- Arbitrary type with custom mappings\n\n  If you want to use a type that is not supported by gen_js_api, you can make it JS-able by providing\n  your own `*_of_js` and `*_to_js` functions (custom mappings) with a `[@@js.custom ...]` attribute.\n\n  ```ocaml\n  type t = ... [@@js.custom\n    {\n      of_js = (fun ... -> ...);\n      to_js = (fun ... -> ...)\n    }\n  ]\n  ```\n\n  This is particularly useful when the type is mutually recursive with other types which can be processed by gen_js_api.\n  See the [section on manually created bindings](LOW_LEVEL_BINDING.md) for more information on writing custom mappings by hand.\n\n  Not to be confused with [the `[@@js.custom]` attribute for `val` declarations](IMPLGEN.md#verbatim-sections).\n\nEnums mapped to polymorphic variants or sum types\n-------------------------------------------------\n\nEither polymorphic variants or normal sum types (all with constant\nconstructors) can be used to bind to \"enums\" in JavaScript.  By\ndefault, constructors are mapped to the JS string equal to their OCaml\nname, but a custom translation can be provided with a `[@js]`\nattribute.  This custom translation can be a string or an integer\nliteral or a float literal.\n\n```ocaml\ntype t =\n  | Foo [@js \"foo\"]\n  | Bar [@js 42]\n  | Baz [@js 4.2]\n  | Qux\n    [@@js.enum]\n\ntype t = [`foo | `bar [@js 42] | `baz [@js 4.2] | `Qux] [@@js.enum]\n```\n\n\nIt is possible to specify constructors with one argument of\ntype (int or float or string), used to represent \"all other cases\" of JS values.\n\n```ocaml\ntype status =\n  | OK [@js 1]\n  | KO [@js 2]\n  | OO [@js 1.5]\n  | OtherS of string [@js.default]\n  | OtherI of int [@js.default]\n    [@@js.enum]\n```\n\nThere cannot be two default constructors with the same argument type.\nAlso, there cannot be default constructors of type int and float at the same time.\n\nSum types mapped to records with a discriminator field\n------------------------------------------------------\n\nEither polymorphic variants or sum types can be mapped to JS records\nwith a discriminator field.\n\nBy default, the name of the discriminator field is `kind`, but this\ncan be changed by specifying a field name as attribute value of the\n`[@@js.sum]` attribute. The value of the discriminator field is set to\nthe representation of the constructor name: it is derived\nautomatically from the constructor name but can also be specified with\na `[@js]` attribute. In this latter case, it can be either a string or\nan integer.\n\nA constant constructor is simply mapped to a record containing the\ndiscriminator field.\n\nA unary constructor is mapped to a record containing two fields: the\ndiscriminator field and an argument field representing the unique\nargument of the constructor. The argument field name is by default\n`arg`, but this can be changed with a `[@js.arg]` attribute.\n\nAt most one unary constructor may have the attribute `[@js.default]`\nand the argument of this constructor must be of type `Ojs.t`. In this\ncase, this constructor is used to handle the default case when either\nthe discriminator field is equal to an unexpected value or even worse\nwhen the discriminator field is absent (from JS to ML). In the other\ndirection (from ML to JS), the unique argument is used as JavaScript\nrepresentation.\n\nA nary constructor is mapped to a record containing two fields: the\ndiscriminator field and an argument field set to an array representing\nthe arguments of the constructor. Once again, the argument field name\nis by default `arg`, but this can be changed with a `[@js.arg]`\nattribute. In the case of polymorphic variant, if the argument is a\ntuple, then the polymorphic variant constructor is considered to be\nn-ary.\n\nFinally, an inline record constructor is mapped to a record containing\nall the field of the record in addition of the discriminator\nfield. The name of the fields are derived from the name of the record\nfields. As usual, these names can be customized using a `[@js]`\ndirective. This last case only applies to sum types.\n\n```ocaml\ntype t =\n  | A\n  | B of int\n  | C of int * string\n  | D of {age: int; name: string}\n  | Unknown of Ojs.t [@js.default]\n    [@@js.sum]\n```\n\nThe following declaration is equivalent to the previous one.\n\n```ocaml\ntype t =\n  | A [@js \"A\"]\n  | B of int [@js.arg \"arg\"]\n  | C of int * string [@js.arg \"arg\"]\n  | D of {age: int [@js \"age\"]; name: string}\n  | Unknown of Ojs.t [@js.default]\n    [@@js.sum \"kind\"]\n```\n\nUnion types\n-----------\n\nIt is common for JS functions to allow arguments of several different\ntypes (for instance, a string or an object).  To represent this calling\nconvention, one can use polymorphic variants:\n\n```\nval f: t -> ([`Str of string | `Obj of t | `Nothing] [@js.union]) -> ...\n```\n\nWhen the `[@js.union]` attribute is used without any other option,\nonly the ML to JS function is generated. The ML to JS conversion\nfunction simply maps constant constructors to the `null` value,\nunary constructors to the value of the constructor argument,\nand n-ary constructors to the array of the constructor argument values\n(i.e. treated as a tuple).\n\nFor generating the converse function, one needs to have a way to\ndistinguish JS values in the union type. At the moment, union types\nwith a discriminator field argument are supported. To indicate the\nname of the field, one can add extra option `on_field \"kind\"` (where\n\"kind\" is the name of the field) to the `[@js.union]` attribute. In\nthis case, the JS to ML conversion function will inspect the value of\nthe field named \"kind\" and will map the JS value to the corresponding\nunary constructor. As for sum types, the value of the discriminator\nfield is deduced from the name of the constructors but it can always\nbe overridden by using a `[@js]`attribute.\n\n```\ntype close_path\n\ntype moveto_abs\n\ntype svg_path_seg =\n  | Unknown of Ojs.t         [@js.default]\n  | Close_path of close_path [@js 1]\n  | Moveto_abs of moveto_abs [@js 2]\n  [@@js.union on_field \"pathSegType\"]\n```\n\nAs for sum types, at most one unary constructor may have the\n`[@js.default]` attribute and the argument of this constructor must be\nof type `Ojs.t`. In this case, this constructor is used to handle the\ndefault case when either the discriminator field is equal to an\nunexpected value or even worse when the discriminator field is absent\n(from JS to ML).\n\nDiscriminated union types\n-------------------------\n\nIt is common for JS functions to allow arguments of several different\ntypes (for instance, a string or an object), whose type depends on a\npreceding argument.  To represent this calling convention, one can use\npolymorphic variants:\n\n```\nval f: t -> ([`Str of string | `Obj of t | `Nothing] [@js.enum]) -> ...\n```\n\nThis generalisation of the `[@js.enum]` attribute can only be used on\npolymorphic variant used in contravariant context (i.e. to describe\nmapping from OCaml to JavaScript, not the other way around).  With\nthis calling convention, first the representation of the constructor\n(which can be an integer or a float or a string, which is derived\nautomatically if not specified with a `[@js]` attribute) is passed,\nfollowed by the n arguments of the constructor.\n\nType variables\n--------------\n\nUnbound type variable are processed implicitly coerced from and to\n`Ojs.t` using unsafe coercion.\n\nThis is useful when writing bindings to JS functions that rely on data structures\nthat can contain OCaml values as is. For example, to directly use the JS\narrays to store OCaml values in their original runtime representation, a\n`JsArray` module could be defined:\n\n```ocaml\nmodule JsArray : sig\n  type 'a t = private Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n\n  val create: int -> 'a t [@@js.new \"Array\"]\n  val push: 'a t -> 'a -> unit [@@js.call]\n  val pop: 'a t -> 'a option [@@js.call]\nend\n```\n\n**Important:** the functions generated from types with variables will only apply\nthe identity function when converting to or from JS. So this approach should\nnever be used to interface with a JS function that expects the types to be\nconverted. For example, the following would break if we used it as a binding\nto the [`Array.join`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join)\nfunction:\n```ocaml\nval join: string JsArray.t -> string -> string\n```\nIndeed, the objects contained in the JsArray.t are not JavaScript strings but\nrepresentation of caml strings.\nTo properly do this, we would want the strings contained in the data structure\nto be converted /to JS types, this would require conversion functions not\nignoring their first argument that are manually implemented.\n\nOne approach is to use functors instead:\n```ocaml\n(* Ojs.T is defined as follows:\n\n  module type T = sig\n    type t\n    val t_to_js : t -> Ojs.t\n    val t_of_js : Ojs.t -> t\n  end\n*)\n\nmodule JsArray (E: Ojs.T): sig\n  type t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val create: unit -> t [@@js.new \"Array\"]\n  val push: t -> E.t -> unit [@@js.call]\n  val pop: t -> E.t option [@@js.call]\nend\n\nmodule StringArray : sig\n  include (module type of JsArray(Ojs.String))\n\n  val join: t -> string -> string [@@js.call]\nend\n```\nBy moving the type parameters to the functor arguments, you can enforce the\nvalue conversion between JS types and OCaml types.\n\nYou can also use [first-class modules](VALUES.md#first-class-modules) for value bindings,\nwhich will be used to convert the polymorphic values and thus making the binding safe:\n```ocaml\nmodule[@js.scope \"console\"] Console: sig\n  val log: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global]\nend\n```\n\nYou can also create safe bindings manually with the low level functions\nprovided by `Ojs` module. See the [section on manually created bindings](LOW_LEVEL_BINDING.md)\nfor more information.\n\n"
  },
  {
    "path": "VALUES.md",
    "content": "Value bindings in gen_js_api\n============================\n\n\nSupported forms\n---------------\n\n- Method call:\n\n  ```ocaml\n  val my_method: t -> T1 -> ... -> Tn -> T\n  [@@js.call]\n  ```\n\n  Calling the function on a first argument `o` of type `t` corresponds\n  to calling the method `myMethod` on the underlying JS object, with\n  other arguments passed to it.\n\n  By default, the name of the method on the JS side is derived from\n  the name of the OCaml value (`myMethod` above).  It is possible to\n  specify a custom name explicitly, for instance for cases where the\n  JS name is not a valid OCaml (lowercase-)identifier, or to support\n  overloading (exposing multiple OCaml functions that correspond to\n  different types given to the same JS method):\n\n\n  ```ocaml\n  val my_method: t -> T1 -> ... -> Tn -> T\n  [@@js.call \"JavaScriptMethodName\"]\n  ```\n\n- Function Application\n\n  ```ocaml\n  val apply: t -> T1 -> ... -> Tn\n  [@@js.apply]\n  ```\n\n  Calling the function on a first argument `f` of type `t` corresponds\n  to calling the underlying JS function object directly, with\n  other arguments passed to it.\n\n  This is particularly useful when binding to a \"callable\" JS object (an object that is also a function), or [a function type in a TypeScript interface](https://www.typescriptlang.org/docs/handbook/interfaces.html#function-types).\n\n  The name of the function need not necessarily be `apply` as long as the `[@@js.apply]` attribute is present.\n\n  When the function you want to bind is a \"newable\" one (a function that must be called with a prefix `new`, e.g. constructors), use `[@@js.apply_newable]` instead. This is especially useful to bind to constructor interfaces in TypeScript.\n\n  ```ocaml\n  module FooConstructor: sig\n    type t\n    val new_: t -> Foo.t [@@js.apply_newable]\n  end\n  val fooConstructor: FooConstructor.t [@@js.global \"Foo\"]\n  ```\n\n  When the \"callable\" object you want to bind to is a global object, the `[@@js.invoke]`\n  attribute along with the `[@js.scope]` attribute (see below) may be used to call it.\n\n  For instance, you can write\n  ```ocaml\n    module[@js.scope \"JavaScriptClassName\"] C : sig\n      val invoke: T1 -> ... -> Tn -> t [@@js.invoke]\n    end\n\n    (* usage *)\n    let x = C.invoke arg1 ... argn\n  ```\n  instead of\n  ```ocaml\n    module C : sig\n      type t\n      val apply: t -> T1 -> ... -> Tn -> t [@@js.apply]\n    end\n    val c: C.t [@@js.global \"JavaScriptClassName\"]\n\n    (* usage *)\n    let x = C.apply c arg1 ... argn\n  ```\n\n- Object constructor:\n\n  ```ocaml\n  val new_my_class: T1 -> ... -> Tn -> t\n  [@@js.new]\n  ```\n\n  Corresponds to calling a JS constructor with arguments\n  passed to it.\n\n  By default, the name of the class on the JS side is derived from the\n  name of the OCaml value (`MyClass` above): in this case, the value\n  name must start with the `new_` prefix which is dropped and the\n  remaining name is capitalize to obtain the class name.  It is\n  also possible to specify a custom name explicitly.\n\n  ```ocaml\n  val f: T1 -> ... -> Tn -> t\n  [@@js.new \"JavaScriptClassName\"]\n  ```\n  As for global values, it is possible to indicate the access path by\n  using `[@js.scope]` attributes on englobing modules (see below).\n\n  When the global object is itself an object constructor, the `[@@js.create]`\n  attribute may be used to instantiate it.\n\n  For instance,\n  ```ocaml\n    module[@js.scope \"JavaScriptClassName\"] C : sig\n      val create: T1 -> ... -> Tn -> t [@@js.create]\n    end\n  ```\n  is the same as\n  ```ocaml\n    module C : sig\n      val create: T1 -> ... -> Tn -> t [@@js.new \"JavaScriptClassName\"]\n    end\n  ```\n\n- Global value or function:\n\n  ```ocaml\n  val x: t\n  [@@js.global]\n  ```\n\n  This creates an OCaml value that corresponds to a globally accessible\n  JavaScript value.  This is used to access both global objects (e.g.\n  the `window` object) and global functions (e.g. `alert`).  It is also\n  possible to specify a custom name for the JavaScript variable:\n\n  ```ocaml\n  val x: t\n  [@@js.global \"JavaScriptValueName\"]\n  ```\n\n  Example:\n  ```ocaml\n  val alert: string -> unit\n  [@@js.global]\n  ```\n\n  By default, a global value or function is taken from the global\n  object. However, it is possible to specify an access path by using\n  `[@js.scope]` attribute on englobing modules (see the Scope section).\n\n- Property getter\n\n  ```ocaml\n  val prop: t -> T\n  [@@js.get]\n  ```\n\n  Calling the function on a first argument `o` of type `t` corresponds\n  to getting the `prop` property of the underlying JS object. A custom\n  name for the JS property can be specified:\n\n  ```ocaml\n  val get_property: t -> T\n  [@@js.get \"MyProp\"]\n  ```\n\n\n- Property setter\n\n  ```ocaml\n  val set_prop: t -> T -> unit\n  [@@js.set]\n  ```\n\n  Calling the function on a first argument `o` of type `t` corresponds\n  to setting the `prop` property of the underlying JS object.  Note that\n  the value name must start with the `set_` prefix, which is dropped to\n  obtain the property name.\n\n  A custom name for the JS property can also be specified (in which\n  case the name of the value can be arbitrary):\n\n  ```ocaml\n  val modify_prop: t -> T -> unit\n  [@@js.set \"prop\"]\n  ```\n\n- Index getter\n\n  ```ocaml\n  val get: t -> index -> T option\n  [@@js.index_get]\n  ```\n\n  Corresponds to getting from an index accessor or [an index signature in a TypeScript interface](https://www.typescriptlang.org/docs/handbook/interfaces.html#indexable-types).\n\n  The return type may be `T` or `T option`, depending on whether the property is optional or not.\n\n  The name of the function need not necessarily be `get` as long as the `[@@js.index_get]` attribute is present.\n\n  `index` must be `int`, `string`, or abstract types holding a JavaScript `number` or `string` value.\n\n- Index setter\n\n  ```ocaml\n  val set: t -> index -> T -> unit\n  [@@js.index_set]\n  ```\n  Corresponds to setting to an index accessor or [an index signature in a TypeScript interface](https://www.typescriptlang.org/docs/handbook/interfaces.html#indexable-types).\n\n  The name of the function need not necessarily be `set` as long as the `[@@js.index_set]` attribute is present.\n\n  `index` must be `int`, `string`, or abstract types holding a JavaScript `number` or `string` value.\n\n\n- Global getter\n\n  ```ocaml\n  val get_x: unit -> T\n  [@@js.get \"x\"]\n\n  val get_sub_x: unit -> T\n  [@@js.get \"MyObject.x\"]\n  ```\n\n  This creates a function which returns the current value of a\n  global variable or of a (possibly nested) inner field of a global variable.\n\n  As for global values, it is possible to indicate the access path by\n  using `[@js.scope]` attributes on englobing modules.\n\n- Global setter\n\n  ```ocaml\n  val set_x: T -> unit\n  [@@js.set \"x\"]\n\n  val set_sub_x: T -> unit\n  [@@js.set \"MyObject.x\"]\n  ```\n\n  This creates a function which sets the value of a\n  global variable or of a (possibly nested) inner field of a global variable.\n\n  As for global values, it is possible to indicate the access path by\n  using `[@js.scope]` attributes on englobing modules.\n\n- Cast\n\n  ```ocaml\n  val cast: t1 -> t2\n  [@@js.cast]\n  ```\n\n  Calling this function performs an unchecked cast from type `t1` to\n  type `t2`, going through the JavaScript representation (i.e.\n  applying mapper from `t1` to the underlying JS object, and back\n  using the mapper for `t2`).\n\n\n- Literal object builder:\n\n  ```ocaml\n  val make: l1:T1 -> ... -> ln:tn -> t\n  [@@js.builder]\n  ```\n\n  Corresponds to creating a JS plain object with fields initialized\n  with the provided values.  The name of the function (`make` in the\n  example) does not correspond to any concept in JS.  By default, the\n  JS field names are derived from OCaml labels, but it is also\n  possible to override that with a `[@js]` attribute on the argument's\n  type.  All fields must be labeled or optional, or come with such an\n  attribute.\n\n  Optional arguments (but not non-optional argument with optional\n  type) are treated in a special way: no field is created in the JS\n  object if the parameter is not provided on the call site (without\n  this special behavior, the treatment would be to set the field to\n  `null`, which is the encoding of `None`).\n\n  Example:\n\n  ```ocaml\n  type t  = private Ojs.t\n\n  val mk: ?children:t list -> age:int -> (string[@js \"name\"]) -> t\n  [@@js.builder]\n  ```\n\n\n- Custom binding:\n\n  ```ocaml\n  val f: ...\n    [@@js.custom\n          let f = ...\n    ]\n  ```\n\n  The val declaration itself doesn't produce anything in the\n  implementation.  Instead, custom OCaml code that goes into the\n  implementation must be provided explicitly.\n\n  See [Verbatim section](IMPLGEN.md) for more details and examples.\n\nCalling a function/constructor by different means\n-------------------------------------------------\n\n|                                     | as a function          | as a constructor       |\n|-------------------------------------|------------------------|------------------------|\n| call the first argument             | `[@@js.apply]`         | `[@@js.apply_newable]` |\n| call the global object              | `[@@js.invoke]`        | `[@@js.create]`        |\n| call a member of the first argument | `[@@js.call \"methodName\"]`   | N/A                    |\n| call a member of the global object  | `[@@js.global \"funcName\"]` | `[@@js.new \"ClassName\"]`    |\n\nScope\n-----\n\nThe signature attribute `[@@@js.scope \"property\"]` changes the reference to the current global\nobject by following the property provided as payload. Nested scopes work as if the\naccess path were composed by concatenation of all the names indicated by [@js.scope]\nattribute, separated by a '.'.\n\nA simple use case is to bind to JavaScript values packed in singleton objects or classes.\n\nFor instance,\n\n```ocaml\n  module[@js.scope \"console\"] Console: sig\n    val log: string -> unit [@@js.global]\n  end\n```\n\nis equivalent to\n\n```ocaml\n  module Console: sig\n    val log: string -> unit [@@js.global \"console.log\"]\n  end\n```\n\nWhen attached directly to a module, the payload of `[@@js.scope]`\nmay be omitted, it will be implicitly filled with the module name\n(preserving the capitalization !).\n\nBefore version 1.0.7, the presence of `[@@js.scope]` used to change\nthe behavior of automatic bindings. It is no longer the case.\n\nAn experimental feature also allows to pass an expression of type `Ojs.t` as\na payload to replace the global object. The intended use case is to allow\ndynamic loading of modules.\n\nThere is also a tuple notation `[@js.scope (s1, ..., sn)]` that helps\nwriting nested scopes. It is equivalent to `[@js.scope sn]...[@js.scope s1]`.\n\nFor instance, the following annotated modules will generate the same code:\n```ocaml\n  module NestedScope0 : sig\n    val f: string -> unit [@@js.global \"outer.inner.f\"]\n  end\n  module [@js.scope (\"outer\", \"inner\")] NestedScope1 : sig\n    val f: string -> unit [@@js.global]\n  end\n  module NestedScope2 : sig\n    val f: string -> unit [@@js.global]\n  end [@js.scope \"inner\"] [@js.scope \"outer\"]\n```\n\nFirst-class modules\n-------------------\n\nAs introduced in [Type variables](TYPES.md#type-variables), you can use\nfirst-class modules to enforce JS/OCaml value conversion on polymorphic functions.\n\n```ocaml\nmodule[@js.scope \"console\"] Console: sig\n  val log: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global]\nend\n```\n\nThere are several restrictions when using first-class modules:\n\n* First-class modules must be annotated with `@js`.\n  - This attribute indicates that it should only be used to convert values\n    and should not be passed directly to the JS function.\n\n* First-class modules must come before any other normal types.\n  - The following is invalid because the first-class module comes after a normal type `'a`:\n    ```ocaml\n    val log: 'a -> (module[@js] Ojs.T with type t = 'a) -> unit [@@js.global]\n    ```\n\n* A first-class module to convert a type variable `'x` must be in the form of\n  `(module[@js] Ojs.T with type t = 'x)`.\n  - The following is invalid because it has a different form (though the meaning is equivalent):\n    ```ocaml\n    module type MyOjsT = Ojs.T\n\n    val log: (module[@js] MyOjsT with type t = 'a]) -> 'a -> unit [@@js.global]\n    ```\n\n* First-class modules can't be used outside of value bindings.\n  - The following is invalid because it is used in a type alias:\n    ```ocaml\n    type 'a logger = (module[@js] Ojs.T with type t = 'a) -> 'a -> unit\n\n    val log: 'a logger [@@js.global]\n    ```\n\nTo use bindings with first-class modules, you just have to pass the enclosing modules of the types:\n```ocaml\nmodule[@js.scope \"Person\"] Person : sig\n  type t\n\n  (* these functions must be present *)\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val create: string -> t [@@js.create]\nend\n\nlet p = Person.create \"Foo\";;\n\nConsole.log (module Person) p;; (* Person { name: 'Foo' } *)\n```\n\nFor built-in types, there are pre-defined modules available in the `Ojs` module:\n```ocaml\nConsole.log (module Ojs.String) \"hello, world!\";;\nConsole.log (module Ojs.Int) 42;;\nConsole.log (module Ojs.List(Ojs.String)) [\"hello\"; \"world!\"];;\n```\n\nAutomatic binding (Deprecated since 1.0.7)\n------------------------------------------\n\nSome conventions, based on the declared value names and their types,\nallow to infer implicitly the `[@@js.xxx]` attributes on value\ndeclarations in most cases.\n\n*This feature has been deprecated starting from version 1.0.7*. All values\ndeclaration should be annotated with an explicit attribute. Otherwise\na preprocessor warning will be emitted.\n\nNote that in all modes the declaration of conversion functions generated\nfrom types are ignored in order to expose the generated functions.\n\nThis means all value of declarations of the form:\n```ocaml\nval τ_to_js: ... -> Ojs.t\n```\nor the form\n```ocaml\nval τ_of_js: ... -> τ\n```\n\nThe rules are applied in order:\n\n- If the value is a function whose result is a named type `... -> τ`\n  and the name is `create`, then the declaration is assumed to\n  be a `[@@js.create]` object creation.\n\n- If the value is a function whose result is a named type `... -> τ`\n  and its name starts with `new_`, then the declaration is assumed to\n  be a `[@@js.new]` object creation (on the class whose name is\n  obtained by dropping the `new_`prefix).\n\n- If the value is a function with a single argument `τ1 -> unit` and\n  its name starts with `set_`, then the declaration is assumed to be a\n  `[@@js.set]` global setter (whose name is obtained by dropping the\n  `set_` prefix).\n\n- If the value is a function returning `unit` with three arguments\n  whose first argument is a named type `τ -> τ2 -> τ3 -> unit` and the\n  name is `set`, then the declaration is assumed to be a\n  `[@@js.set_index]` index setter.\n\n- If the value is a function with two arguments `τ1 -> τ2 -> unit` and\n  its name starts with `set_`, then the declaration is assumed to be a\n  `[@@js.set]` property setter (on the property whose name is obtained\n  by dropping the `set_` prefix).\n\n- If the value is a function with a single argument (named type) `τ ->\n  unit`, then the declaration is assumed to be a `[@@js.call]` method\n  call.\n\n- If the value is a function with two arguments whose first argument is\n  a named type `τ -> τ2 -> τ3` (and `τ3` is not `unit`) and the name is\n  `get`, then the declaration is assumed to be a `[@@js.index_get]`\n  index getter.\n\n- If the value is a function with a single argument (named type) `τ ->\n  τ2` (and `τ2` is not `unit`), then the declaration is assumed to be\n  a `[@@js.get]` property getter.\n\n- If the value is a function with a single argument `unit -> τ2`, then\n  the declaration is assumed to be a `[@@js.get]` global getter.\n\n- If the value is a function whose first argument is a named type `τ\n  -> ...` and the name is `apply`, then the definition is assumed to\n  be a `[@@js.apply]` function object application.\n\n- If the value is a function whose first argument is a named type `τ\n  -> ...` (and the name is not `apply`), then the definition is assumed\n  to be a `[@@js.call]` method call.\n\n- Otherwise, the declaration is assumed to be a `[@@js.global]` value.\n  This applies in particular for any non-functional type.\n"
  },
  {
    "path": "dune",
    "content": "(env\n (dev\n  (flags (:standard))))\n\n(deprecated_library_name\n (old_public_name gen_js_api)\n (new_public_name ojs))\n"
  },
  {
    "path": "dune-project",
    "content": "(lang dune 3.17)\n(name gen_js_api)\n(version 1.1.7)\n\n(maintainers \"Alain Frisch <alain.frisch@lexifi.com>\")\n(authors\n \"Alain Frisch <alain.frisch@lexifi.com>\"\n \"Sebastien Briais <sebastien.briais@lexifi.com>\")\n\n(source (github LexiFi/gen_js_api))\n\n(generate_opam_files true)\n\n(license MIT)\n\n(package\n (name ojs)\n (synopsis \"Runtime Library for gen_js_api generated libraries\")\n (description \"To be used in conjunction with gen_js_api\")\n (depends\n   (ocaml (>= 4.13))\n   (js_of_ocaml-compiler (>= 6.3.0)))\n )\n\n(package\n (name gen_js_api)\n (synopsis \"Easy OCaml bindings for JavaScript libraries\")\n (description \"\ngen_js_api aims at simplifying the creation of OCaml bindings for\nJavaScript libraries.  Authors of bindings write OCaml signatures for\nJavaScript libraries and the tool generates the actual binding code\nwith a combination of implicit conventions and explicit annotations.\n\ngen_js_api is to be used with the js_of_ocaml compiler.\n \")\n (conflicts (js_of_ocaml-compiler (< 6.3.0)))\n (depends\n  (ocaml (>= 4.13))\n  (ppxlib (>= 0.37))\n  (js_of_ocaml-compiler :with-test)\n  (ojs (= :version)))\n)\n"
  },
  {
    "path": "examples/calc/calc.html",
    "content": "<html>\n  <head>\n    <title>Calculator</title>\n  </head>\n  <body>\n    <script src=\"calc.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/calc/calc.ml",
    "content": "module Element = [%js:\n  type t\n\n  val t_of_js: Ojs.t -> t\n\n  val append_child: t -> t -> unit [@@js.call]\n\n  val set_attribute: t -> string -> string -> unit [@@js.call]\n\n  val set_onclick: t -> (unit -> unit) -> unit [@@js.set]\n]\n\nmodule Window = [%js:\n  type t\n\n  val instance: t [@@js.global \"window\"]\n\n  val set_onload: t -> (unit -> unit) -> unit [@@js.set]\n]\n\nmodule Document = [%js:\n  type t\n\n  val instance: t [@@js.global \"document\"]\n\n  val create_element: t -> string -> Element.t [@@js.call]\n\n  val create_text_node: t -> string -> Element.t [@@js.call]\n\n  val body: t -> Element.t [@@js.get]\n]\n\nlet element tag children =\n  let elt = Document.create_element Document.instance tag in\n  List.iter (Element.append_child elt) children;\n  elt\n\nlet textnode s = Document.create_text_node Document.instance s\n\nlet td ?colspan child =\n  let elt = element \"td\" [child] in\n  begin match colspan with\n  | None -> ()\n  | Some n -> Element.set_attribute elt \"colspan\" (string_of_int n)\n  end;\n  elt\n\nlet tr = element \"tr\"\nlet table = element \"table\"\nlet center x = element \"center\" [x]\n\nlet button x f =\n  let elt = element \"button\" [textnode x] in\n  Element.set_attribute elt \"type\" \"button\";\n  Element.set_onclick elt f;\n  elt\n\nmodule Engine = struct\n  type op = Add | Sub | Mul | Div\n\n  type state =\n    {\n      x: float;\n      y: float;\n      operator: op option;\n      input: bool;\n      equal: bool;\n      comma: int;\n    }\n\n  let initial = { x = 0.; y = 0.; operator = None; input = false; equal = false; comma = 0 }\n\n  let make_op op x y =\n    match op with\n    | Add -> x +. y\n    | Sub -> x -. y\n    | Mul -> x *. y\n    | Div -> x /. y\n\n  let of_digit d = float_of_int d\n  let add_digit x comma d =\n    if comma = 0 then 10. *. x +. float_of_int d, comma\n    else x +. float_of_int d /. (10. ** (float_of_int comma)), comma + 1\n\n  let input_digit ({x; y; operator = _; input; equal; comma} as state) d =\n    let y = if equal then y else x in\n    let x, comma =\n      if input then add_digit x comma d\n      else of_digit d, 0\n    in\n    {state with x; y; comma; input = true}\n\n  let apply_comma ({input; comma; _} as state) =\n    if comma = 0 then\n      if input then {state with comma = 1}\n      else {(input_digit state 0) with comma = 1}\n    else state\n\n  let apply_equal ({x; y; operator; input; equal; comma = _} as state) =\n    match operator with\n    | None -> {state with y = x; input = false; equal = true}\n    | Some o ->\n        if input && not equal then {state with x = make_op o y x; y = x; input = false; equal = true}\n        else {state with x = make_op o x y; equal = true}\n\n  let apply_op ({input; equal; _} as state) op =\n    if input && not equal then {(apply_equal state) with operator = Some op; equal = false}\n    else {state with operator = Some op; equal= false; input = false}\n\n  let print_op ppf = function\n    | None -> Printf.fprintf ppf \" \"\n    | Some Add -> Printf.fprintf ppf \"+\"\n    | Some Sub -> Printf.fprintf ppf \"-\"\n    | Some Mul -> Printf.fprintf ppf \"*\"\n    | Some Div -> Printf.fprintf ppf \"/\"\n\n  let print ppf {x; y; operator; input; equal; comma} =\n    Printf.fprintf ppf \"x = %g, y = %g, op = %a, input = %b, equal = %b, comma = %d\" x y print_op operator input equal comma\nend\n\n\nlet widget () =\n  let open Engine in\n  let state = ref initial in\n  let res, set_value =\n    let elt = element \"input\" [] in\n    Element.set_attribute elt \"type\" \"text\";\n    Element.set_attribute elt \"readonly\" \"\";\n    let set_value v = Element.set_attribute elt \"value\" (string_of_float v) in\n    elt, set_value\n  in\n  let update st =\n    Printf.printf \"%a\\n\" print st;\n    state := st;\n    set_value !state.x\n  in\n  let reset() = update initial in\n  reset();\n  let binop op () = update (apply_op !state op) in\n  let equal () = update (apply_equal !state) in\n  let comma () = update (apply_comma !state) in\n  let figure digit =\n    let f () = update (input_digit !state digit) in\n    button (string_of_int digit) f\n  in\n  let c l = td l in\n  let nothing () = element \"div\" [] in\n  table [tr [td ~colspan:4 res];\n         tr (List.map c [nothing(); button \"C\" reset; nothing(); button \"/\" (binop Div)]);\n         tr (List.map c [figure 7; figure 8; figure 9; button \"*\" (binop Mul)]);\n         tr (List.map c [figure 4; figure 5; figure 6; button \"-\" (binop Sub)]);\n         tr (List.map c [figure 1; figure 2; figure 3; button \"+\" (binop Add)]);\n         tr (List.map c [nothing(); figure 0; button \".\" comma; button \"=\" equal])]\n\nlet go () =\n  Element.append_child (Document.body Document.instance) (center (widget()))\n\nlet () =\n  Window.set_onload Window.instance go\n"
  },
  {
    "path": "examples/calc/dune",
    "content": "(executables\n (names calc)\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes js))\n\n(rule\n (targets calc.js)\n (deps calc.bc.js)\n (action\n  (run cp %{deps} %{targets})))\n\n(alias\n (name DEFAULT)\n (deps calc.js calc.html))\n"
  },
  {
    "path": "examples/misc/dune",
    "content": "(executables\n (names test_jquery)\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes js))\n\n(rule\n (targets jquery.ml)\n (deps jquery.mli)\n (action\n  (run %{bin:gen_js_api} %{deps})))\n\n(rule\n (targets js_date.ml)\n (deps js_date.mli)\n (action\n  (run %{bin:gen_js_api} %{deps})))\n\n(rule\n (targets js_str.ml)\n (deps js_str.mli)\n (action\n  (run %{bin:gen_js_api} %{deps})))\n\n(rule\n (targets test_jquery.js)\n (deps test_jquery.bc.js)\n (action\n  (run cp %{deps} %{targets})))\n\n(alias\n (name DEFAULT)\n (deps test_jquery.js test_jquery.html))\n"
  },
  {
    "path": "examples/misc/jquery.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** Partial binding to jQuery, serving as an illustration\n    of gen_js_api.  The binding is far from complete! *)\n\n[@@@js.implem [@@@ocaml.warning \"-22\"]]\n\n(** {2 Sets of elements} *)\n\ntype t = private Ojs.t\n\nval selector: string -> t\n  [@@js.global \"jQuery\"]\n(** Either select a set of elements from the current document, or\n    create a new element (if given a string such as \"<div>\". *)\n\nval wrap: Ojs.t -> t [@@js.global \"jQuery\"]\n\nval explode: t -> t list\n    [@@js.custom let explode x = Ojs.list_of_js wrap x]\n\nval find: t -> string -> t list\n    [@@js.custom\nval find: t -> string -> t [@@js.call \"find\"]\n\nlet find x sel = explode (find x sel)\n    ]\n\n\nval text: t -> string\n  [@@js.call]\n\nval set_text: t -> string -> unit\n  [@@js.call \"text\"]\n\nval update_text: t -> (int -> string -> string) -> unit\n  [@@js.call \"text\"]\n\nval append_html: t -> string -> unit\n  [@@js.call \"append\"]\n\nval append: t -> (t list [@js.variadic]) -> unit\n  [@@js.call \"append\"]\n\nval prepend: t -> (t list [@js.variadic]) -> unit\n  [@@js.call]\n\nval after: t -> t -> unit\n  [@@js.call]\n\nval before: t -> t -> unit\n  [@@js.call]\n\nval get_val: t -> string\n  [@@js.call \"val\"]\n\nval hide: t -> unit\n  [@@js.call]\n\nval show: t -> unit\n  [@@js.call]\n\nval detach: t -> unit\n  [@@js.call]\n\nval remove: t -> unit\n  [@@js.call]\n\nval empty: t -> unit\n  [@@js.call]\n\nval focus: t -> unit\n\nval height: t -> int [@@js.call]\nval set_height: t -> ([`String of string | `Int of int] [@js.union]) -> unit [@@js.call \"height\"]\n\nval width: t -> int [@@js.call]\nval set_width: t -> ([`String of string | `Int of int] [@js.union]) -> unit [@@js.call \"width\"]\n\nval string_value: t -> string [@@js.call \"val\"]\nval set_string_value: t -> string -> unit [@@js.call \"val\"]\n\nval add_class: t -> string -> unit [@@js.call]\nval remove_class: t -> string -> unit [@@js.call]\n\nval css: t -> string -> Ojs.t [@@js.call]\n\nval set_css_value: t -> string -> ([`String of string | `Float of float] [@js.union]) -> unit [@@js.call \"css\"]\n\nval set_css: t -> Ojs.t -> unit [@@js.call \"css\"]\n\nval clone: t -> t [@@js.call]\n\nval html: t -> string\n  [@@js.call \"html\"]\n\nval set_html: t -> string -> unit\n  [@@js.call \"html\"]\n\n\n(** {2 Properties} *)\n\nval prop: t -> string -> Ojs.t\n  [@@js.call]\n\nval set_prop:\n  t -> string ->\n  ([`String of string | `Int of int | `Bool of bool | `Any of Ojs.t] [@js.union]) ->\n  unit\n  [@@js.call \"prop\"]\n\n(** {2 Data} *)\n\nval data: t -> string -> Ojs.t\n  [@@js.call]\n\nval set_data: t -> string -> Ojs.t -> unit\n  [@@js.call \"data\"]\n\n(** {2 Attributes} *)\n\nval attr: t -> string -> string option\n  [@@js.call]\n\nval set_attr: t -> string -> string -> unit\n  [@@js.call \"attr\"]\n\nval remove_attr: t -> string -> unit\n  [@@js.call]\n\n\n(** {2 Animations} *)\n\nval fade_in: t -> ?duration:int -> ?finished:(unit -> unit) -> unit -> unit\n  [@@js.call]\nval fade_out: t -> ?duration:int -> ?finished:(unit -> unit) -> unit -> unit\n  [@@js.call]\n\n(** {2 Events} *)\n\nmodule Event : sig\n  type t\n\n  val page_x: t -> float\n  val page_y: t -> float\n  val type_: t -> string\n  val target: t -> Ojs.t\n  val which: t -> int\n  val stop_propagation: t -> unit [@@js.call]\n  val prevent_default: t -> unit [@@js.call]\nend\n\nval on: t -> string -> (Event.t -> unit) -> unit\nval off: t -> string -> unit\n\nval trigger: t -> string -> unit\n  [@@js.call]\n\nval ready: (unit -> unit) -> unit\n  [@@js.global \"jQuery\"]\n\nmodule Dialog: sig\n  type button\n\n  val button:\n    text:string ->\n    click:(unit -> unit) ->\n    unit -> button\n    [@@js.builder]\n\n  type settings\n\n  val settings:\n    ?modal:bool ->\n    ?title:string ->\n    ?buttons:button list ->\n    unit -> settings\n    [@@js.builder]\nend\n\nmodule UI : sig\n\n  module Datepicker : sig\n    type settings\n\n    val settings:\n      ?date_format:string ->\n      unit -> settings\n      [@@js.builder]\n  end\n\n  val datepicker: t -> Datepicker.settings -> unit\nend\n\nval dialog: t -> ([`Dialog of Dialog.settings | `String of string] [@js.union]) -> unit\n\n(** {2 AJAX} *)\n\nmodule Ajax: sig\n  type settings\n  (** The type describing all settings of an AJAX call. *)\n\n  type t\n  (** Corresponds to jQuery's jqXHR object. *)\n\n  val settings:\n    ?async:bool ->\n    ?cache:bool ->\n    ?complete:(t -> string -> unit) ->\n    ?error:(t -> string -> string -> unit) ->\n    ?success:(Ojs.t -> string -> t -> unit) ->\n    ?data:Ojs.t -> ?data_type:string ->\n    ?meth:([`GET | `POST | `PUT] [@js \"method\"] [@js.enum]) ->\n    ?content_type:string ->\n    ?url:string ->\n    unit -> settings\n      [@@js.builder]\n\n  val run: settings -> unit\n      [@@js.global \"jQuery.ajax\"]\n\n  val response_text: t -> string\n\n  val status: t -> int\nend\n"
  },
  {
    "path": "examples/misc/js_date.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** JS dates *)\n\n(** {2 Type definitions} *)\n\ntype t = private Ojs.t\nval t_of_js: Ojs.t -> t\nval t_to_js: t -> Ojs.t\n\nval now: unit -> t [@@js.new \"Date\"]\nval from_milliseconds: float -> t [@@js.new \"Date\"]\nval from_string: string -> t [@@js.new \"Date\"]\n\nval create: year:int -> month:int -> ?day:(int [@js.default 1]) -> ?hours:(int [@js.default 0]) -> ?minutes:(int [@js.default 0]) -> ?seconds:(int [@js.default 0]) -> ?ms:(int [@js.default 0]) -> unit -> t [@@js.new \"Date\"]\n\nval get_UTC_date: t -> int [@@js.call]\nval get_UTC_day: t -> int [@@js.call]\nval get_UTC_full_year: t -> int [@@js.call]\nval get_UTC_hours: t -> int [@@js.call]\nval get_UTC_milliseconds: t -> int [@@js.call]\nval get_UTC_minutes: t -> int [@@js.call]\nval get_UTC_month: t -> int [@@js.call]\nval get_UTC_seconds: t -> int [@@js.call]\n\nval set_UTC_date: t -> int -> unit [@@js.call]\nval set_UTC_full_year: t -> int -> unit [@@js.call]\nval set_UTC_hours: t -> int -> unit [@@js.call]\nval set_UTC_milliseconds: t -> int -> unit [@@js.call]\nval set_UTC_minutes: t -> int -> unit [@@js.call]\nval set_UTC_month: t -> int -> unit [@@js.call]\nval set_UTC_seconds: t -> int -> unit [@@js.call]\n\nval get_date: t -> int [@@js.call]\nval get_day: t -> int [@@js.call]\nval get_full_year: t -> int [@@js.call]\nval get_hours: t -> int [@@js.call]\nval get_milliseconds: t -> int [@@js.call]\nval get_minutes: t -> int [@@js.call]\nval get_month: t -> int [@@js.call]\nval get_seconds: t -> int [@@js.call]\n\nval set_date: t -> int -> unit [@@js.call]\nval set_full_year: t -> int -> unit [@@js.call]\nval set_hours: t -> int -> unit [@@js.call]\nval set_milliseconds: t -> int -> unit [@@js.call]\nval set_minutes: t -> int -> unit [@@js.call]\nval set_month: t -> int -> unit [@@js.call]\nval set_seconds: t -> int -> unit [@@js.call]\n\nval get_time: t -> float [@@js.call]\nval set_time: t -> float -> unit [@@js.call]\n\nval get_timezone_offset: t -> int [@@js.call]\n\nval to_locale_date_string: t -> string [@@js.call]\nval to_locale_string: t -> string [@@js.call]\nval to_locale_time_string: t -> string [@@js.call]\n\nval to_date_string: t -> string [@@js.call]\nval to_time_string: t -> string [@@js.call]\n\nval to_UTC_string: t -> string [@@js.call]\n\nval to_string: t -> string [@@js.call]\n"
  },
  {
    "path": "examples/misc/js_str.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** JS string and regexp objects *)\n\n(** {2 Type definitions} *)\n\ntype t = private Ojs.t\nval t_of_js: Ojs.t -> t\nval t_to_js: t -> Ojs.t\n\ntype regexp = private Ojs.t\nval regexp_of_js: Ojs.t -> regexp\nval regexp_to_js: regexp -> Ojs.t\n\n(** {2 Conversion between JS strings and OCaml string} *)\n\nval to_string: t -> string [@@js.cast]\nval of_string: string -> t [@@js.cast]\n\n(** {2 JS strings} *)\n\nval from_char_code: (int list [@js.variadic]) -> t\n    [@@js.global \"String.fromCharCode\"]\n\nval char_at: t -> int -> t\nval char_code_at: t -> int -> int\nval concat: t -> (t list [@js.variadic]) -> t\nval index_of: t -> t -> ?start:int -> unit -> int\nval last_index_of: t -> t -> ?start:int -> unit -> int\nval length: t -> int\nval locale_compare: t -> t -> int\nval match_: t -> regexp -> t array option\nval replace: t -> regexp -> t -> t\nval search: t -> regexp -> int\nval slice: t -> start:int -> ?end_:int -> unit -> t\nval split: t -> ?separator:t -> ?limit:int -> unit -> t array\nval substr: t -> start:int -> ?length:int -> unit -> t\nval substring: t -> start:int -> ?end_:int -> unit -> t\nval to_locale_lower_case: t -> t [@@js.call]\nval to_locale_upper_case: t -> t [@@js.call]\nval to_lower_case: t -> t [@@js.call]\nval to_upper_case: t -> t [@@js.call]\nval trim: t -> t [@@js.call]\n\n\n(** {2 Regexps} *)\n\nval regexp: t -> ?global:unit -> ?ignore_case:unit -> ?multiline:unit -> unit -> regexp\n [@@js.custom\n\n      val regexp_internal: t -> ?flags:t -> unit -> regexp [@@js.new \"RegExp\"]\n\n      let regexp txt ?global ?ignore_case ?multiline () =\n        let l = [] in\n        let l = match global with Some () -> of_string \"g\" :: l | None -> l in\n        let l = match ignore_case with Some () -> of_string \"i\" :: l | None -> l in\n        let l = match multiline with Some () -> of_string \"m\" :: l | None -> l in\n        regexp_internal txt ~flags:(concat (of_string \"\") l) ()\n ]\n\n\nval global: regexp -> bool\nval ignore_case: regexp -> bool\nval multiline: regexp -> bool\nval source: regexp -> string\nval last_index: regexp -> int\nval exec: regexp -> t -> t array option\nval test: regexp -> t -> bool\n"
  },
  {
    "path": "examples/misc/test_jquery.html",
    "content": "<html>\n  <head>\n  </head>\n  <body>\n    <span class=\"tofill\">One</span>\n    <span class=\"tofill\">Two</span>\n    <div id=\"main\">Blabla</div>\n\n    <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"test_jquery.js\">\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/misc/test_jquery.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** A toy application built with jQuery *)\n\nopen Jquery\n\ninclude [%js:\nval alert: string -> unit\n  [@@js.global]\n]\n\nlet ( !! ) = Jquery.selector\n\nlet block s ?text ?(classes = []) ?(ons = []) ?(css = []) ?(props = []) children =\n  let element = Jquery.selector (Printf.sprintf \"<%s>\" s) in\n  begin match text with\n  | None -> ()\n  | Some text -> Jquery.set_text element text\n  end;\n  List.iter (fun c -> Jquery.add_class element c) classes;\n  List.iter (fun (key, value) -> Jquery.set_css_value element key value) css;\n  List.iter (fun (key, value) -> Jquery.set_prop element key value) props;\n  List.iter (fun (event, f) -> Jquery.on element event f) ons;\n  begin match children with\n    | [] -> ()\n    | _ :: _-> Jquery.append element children\n  end;\n  element\n\nlet ajax_test () =\n  let open Ajax in\n  let complete h = function\n    | \"success\" ->\n        let pre = block \"pre\" ~text:(response_text h) [] in\n        hide pre;\n        append !!\"body\" [pre];\n        fade_in pre ~duration:2000\n          ~finished:(fun () ->\n              fade_out pre ~finished:(fun () -> detach pre) ()\n            )\n          ()\n    | status -> alert (Printf.sprintf \"status = %s\" status)\n  in\n  run (settings ~meth:`GET ~url:\"test_jquery.ml\" ~data_type:\"text\" ~complete ())\n\n\nlet on_ready () =\n  let main = !!\"#main\" in\n  print_endline (text main);\n  set_text main \"Hello world!\";\n  append_html main \"<b>in bold</b>\";\n\n  let elts = !!\".tofill\" in\n  update_text elts (Printf.sprintf \"[%i:%s]\");\n\n  append main [elts; !! \"<b>XXX</b>\"];\n\n  let on_click evt =\n    let open Event in\n    append_html main\n      (Printf.sprintf \"<br/>x=%f,y=%f,type=%s\"\n         (page_x evt)\n         (page_y evt)\n         (type_ evt)\n      )\n  in\n  on main \"click\" on_click;\n\n  let div = block \"div\" [] in\n  let input = block \"input\" [] in\n  on input \"input\" (fun _ -> set_text div (get_val input));\n  append main [input; div];\n\n  let btn =\n    block \"button\" ~text:\"SHOW SOURCE CODE\" []\n      ~ons:[\"click\", (fun _ -> ajax_test ())]\n  in\n  append main [btn]\n\nlet () =\n  ready on_ready\n"
  },
  {
    "path": "examples/test/dune",
    "content": "(executables\n (names main)\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes js))\n\n(rule\n (targets test_bindings.ml)\n (deps test_bindings.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (targets main.js)\n (deps main.bc.js)\n (action\n  (run cp %{deps} %{targets})))\n\n(alias\n (name DEFAULT)\n (deps main.js main.html))\n"
  },
  {
    "path": "examples/test/main.html",
    "content": "<html>\n  <head>\n  </head>\n  <body>\n    <div class=\"myClass\">Blabla</div>\n    <canvas id=\"canvas\" width=\"200\" height=\"200\">\n      Bla\n    </canvas>\n    <script type=\"text/javascript\">\n      var myArray = [1, 2, 3];\n\n      function wrapper(f) {\n          return function (x, y) {\n              console.log(\"Before\");\n              var r = f(x, y);\n              console.log(\"Result 1 = \" + r);\n              var r = f(r, y);\n              console.log(\"Result 2 = \" + r);\n              return r;\n          }\n      }\n      function caller(f) {\n        console.log(\"Before call\");\n        var r = f();\n        console.log(\"After call\");\n        return r;\n      }\n\n      function Person(name, foo) {\n        console.log(arguments);\n        this.name = name;\n        this.foo = foo;\n        this.get = function () {\n          return [this.name, this.foo];\n        };\n        this.set = function (a) {\n          this.name = a[0];\n          this.foo = a[1];\n        };\n        console.log(\"New Person object created\");\n      }\n\n      function testVariadic(f) {\n        console.log(f());\n        console.log(f(0));\n        console.log(f(0, 1));\n        console.log(f(0, 1, 2));\n        console.log(f(0, 1, 2, 3));\n        console.log(f(0, 1, 2, 3, 4));\n      }\n\n      function testVariadic2(f) {\n        console.log(f(\"Hello\"));\n        console.log(f(\"Hello\", 0));\n        console.log(f(\"Hello\", 0, 1));\n        console.log(f(\"Hello\", 0, 1, 2));\n        console.log(f(\"Hello\", 0, 1, 2, 3));\n        console.log(f(\"Hello\", 0, 1, 2, 3, 4));\n      }\n\n      function testOptArgs(f) {\n        console.log(f());\n        console.log(f(10));\n        console.log(f(10, 10));\n      }\n\n      function test_sum() {\n        print_sum({kind:\"A\"});\n        print_sum({kind:\"B\", arg:806});\n        print_sum({kind:\"C\", arg:[806, \"bar\"]});\n        print_sum({kind:\"D\", age:24, name:\"Toto\"});\n      }\n\n      var myDict = { \"gen_js_api\": \"OK\", \"js_of_ocaml\": \"OK\" };\n\n      function test_flatten(kind) {\n        switch(kind) {\n        case \"A\": {\n          console.log(\"A\");\n          break;\n        }\n        case \"B\": {\n          console.log(\"B \"+arguments[1]);\n          break;\n        }\n        case \"C\": {\n          console.log(\"C \"+arguments[1]);\n          break;\n        }\n        case \"D\": {\n          console.log(\"D (\"+arguments[1]+\", \"+arguments[2]+\")\");\n          break;\n        }\n        }\n      }\n\n      function test_typvars(anything) {\n        return [anything, anything]\n      }\n\n      function makeRef(anything) {\n        return {current: anything}\n      }\n\n      function eitherLeft(anything) {\n        return {left: anything};\n      }\n      function eitherRight(anything) {\n        return {right: anything};\n      }\n      function eitherDestruct(x, left, right) {\n        if (x.hasOwnProperty(\"left\")) {\n          return left(x.left);\n        } else {\n          return right(x.right);\n        }\n      }\n    </script>\n    <script type=\"text/javascript\" src=\"main.js\">\n    </script>\n    <script type=\"text/javascript\">\n      console.log(myArray);\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/test/main.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** Some ad hoc code to illustrate and test various aspects\n    of gen_js_api *)\n\n[@@@ocaml.warning \"-32-34\"]\n\nopen Test_bindings\n\n[@@@ocaml.warning \"-22\"]\n\ninclude\n  [%js:\n    val wrapper: (int -> int -> int) -> (int -> int -> int [@js.dummy])\n    [@@js.global \"wrapper\"]\n\n    val caller: (unit -> int) -> int\n    [@@js.global \"caller\"]\n\n    val caller_unit: (unit -> unit) -> unit\n    [@@js.global \"caller\"]\n\n    val test_variadic: ((int list [@js.variadic]) -> int) -> unit\n    val test_variadic2: (string -> (int list [@js.variadic]) -> int) -> unit\n  ]\n\nmodule LocalBindings = [%js:\n  type myType = { x : a; y : b [@js \"Y\"]}\n  and a = int option\n  and b = { s : string; i : int }\n]\n\n\nlet () =\n  let s = [%js.of: int list] [10; 20; 30] in\n  Printf.printf \"%i\\n%!\" ([%js.to: int] (Ojs.array_get s 0));\n  Printf.printf \"%i\\n%!\" ([%js.to: int] (Ojs.array_get s 1));\n  Printf.printf \"%i\\n%!\" ([%js.to: int] (Ojs.array_get s 2))\n\nlet () =\n  let sum xs = List.fold_left ( + ) 0 xs in\n  test_variadic sum;\n  test_variadic2 (fun msg xs -> Printf.printf \"%s\\n%!\" msg; sum xs)\n\ninclude [%js:\nval myArray: int array\n    [@@js]\n\nval myArray2: Ojs.t\n    [@@js.global \"myArray\"]\n\nval alert_bool: bool -> unit\n    [@@js.global \"alert\"]\n\nval alert_float: float -> unit\n    [@@js.global \"alert\"]\n\n\nval test_opt_args: (?foo:int -> ?bar:int -> unit-> string) -> unit\n  [@@js.global]\n]\n\nlet doc = Window.document window\n\nlet elt name ?(attrs = []) ?onclick subs =\n  let e = Document.createElement doc name in\n  List.iter (fun (k, v) -> Element.setAttribute e k v) attrs;\n  List.iter (Element.appendChild e) subs;\n  begin match onclick with\n  | Some f -> Element.set_onclick e f\n  | None -> ()\n  end;\n  e\n\nlet txt =\n  Document.createTextNode doc\n\nlet button ?attrs s onclick =\n  elt \"button\" ?attrs ~onclick [ txt s ]\n\nlet div = elt \"div\"\n\nlet () =\n  Array.iter (Printf.printf \"[%i]\\n\") myArray;\n\n  Ojs.array_set myArray2 0 (Ojs.int_to_js 10);\n  Ojs.array_set myArray2 1 (Ojs.array_to_js Ojs.int_to_js [| 100; 200; 300 |]);\n(*  Ojs.array_set myArray2 1 ([%to_js: int array] [| 100; 200; 300 |]); *)\n\n(*\n  Printf.printf \"%0.2f\\n\" 3.1415;\n*)\n(*\n  Document.set_title doc \"MyTitle\";\n  Document.set_title doc (Document.title doc ^ \" :-)\");\n*)\n\n(*  let main = Document.getElementById doc \"main\" in *)\n(*  print_endline (Element.innerHTML main); *)\n(*  alert (Element.innerHTML main); *)\n(*  Element.set_innerHTML main \"<b>Bla</b>blabla\"; *)\n\n\n  let draw () =\n    let canvas_elt = Document.getElementById doc \"canvas\" in\n    let canvas = Canvas.of_element canvas_elt in\n    let ctx = Canvas.getContext_2d canvas in\n    Canvas.RenderingContext2D.(begin\n        set_fillStyle ctx \"rgba(0,0,255,0.1)\";\n        fillRect ctx 30 30 50 50\n      end);\n    Element.set_onclick canvas_elt (fun () -> alert \"XXX\");\n  in\n  alert_bool true;\n  alert_float 3.1415;\n  let f =\n    wrapper\n      (fun x y ->\n         Printf.printf \"IN CALLBACK, x = %i, y = %i\\n%!\" x y;\n         x + y\n      )\n  in\n  Printf.printf \"Result -> %i\\n%!\" (f 42 1);\n\n  let uid = ref 0 in\n  let f () =\n    incr uid;\n    Printf.printf \"uid = %i\\n%!\" !uid;\n    !uid\n  in\n  Printf.printf \"Caller result -> %i, %i, %i\\n%!\" (caller f) (caller f) (caller f);\n  caller_unit (fun () -> ignore (f ()));\n  caller_unit (fun () -> ignore (f ()));\n  caller_unit (fun () -> ignore (f ()));\n\n  let alice = Person.create \"Alice\" Person.Foo.Foo in\n  let bob = Person.create \"Bob\" Person.Foo.Bar in\n  let charlie = Person.create \"Charlie\" (Person.Foo.OtherString \"bla\") in\n  let eve = Person.create \"Eve\" (Person.Foo.OtherInt 2713) in\n\n  Ojs.iter_properties (Person.cast alice) (Format.printf \"%s\\n%!\");\n\n  let alice_obj = PersonObj.create \"Alice\" Person.Foo.Foo in\n  let bob_obj = PersonObj.of_person bob in\n  let dave_obj = new PersonObj.person \"Dave\" Person.Foo.Bar [1; 2; 3] in\n\n  let string_of_foo = function\n    | Person.Foo.Foo -> \"foo\"\n    | Person.Foo.Bar -> \"bar\"\n    | Person.Foo.OtherInt n -> Printf.sprintf \"other = %d\" n\n    | Person.Foo.OtherString s -> Printf.sprintf \"other = %s\" s\n  in\n  let string_of_name_foo name foo = Printf.sprintf \"%s <%s>\" name (string_of_foo foo) in\n  let string_of_person x = string_of_name_foo (Person.name x) (Person.foo x) in\n  let string_of_person_obj x = string_of_name_foo (x # name) (x # foo) in\n  let hack_person x =\n    let name, foo = Person.get x () in\n    Printf.printf \"before: %s <%s>\\n\" name (string_of_foo foo);\n    Person.set x (\"Dave\", Person.Foo.OtherString \"bar\");\n    let name, foo = Person.get x () in\n    Printf.printf \"after: %s <%s>\\n\" name (string_of_foo foo);\n  in\n\n  let body = Document.body doc in\n  setTimeout (fun () -> Element.setAttribute body \"bgcolor\" \"red\") 2000;\n  Element.appendChild body (Document.createTextNode doc \"ABC\");\n  Element.appendChild body\n    (div ~attrs:[\"style\", \"color: blue\"] [ txt \"!!!!\"; elt \"b\" [txt \"XXX\"]]);\n\n  Element.appendChild body\n    (div (List.map (fun x -> txt (string_of_person x)) [alice; bob; charlie; eve]));\n  hack_person eve;\n  Element.appendChild body\n    (div (List.map (fun x -> txt (string_of_person x)) [alice; bob; charlie; eve]));\n  Element.appendChild body\n    (div (List.map (fun x -> txt (string_of_person_obj x)) [alice_obj; bob_obj; dave_obj]));\n\n  let s = (new Str.str \"\") # concat [Str.create \"Hello\"; Str.create \", \"; Str.create \"world\"; Str.create \"!\"] in\n  Console.log_string console (s # to_string);\n\n  Console.log_string console (Date.to_string (Date.create ~year:2015 ~month:4 ~day:10 ()));\n\n  let l = Document.getElementsByClassName doc \"myClass\" in\n  Array.iter\n    (fun e ->\n       Printf.printf \"- [%s]\\n\" (Element.innerHTML e); (* OK *)\n       print_string (Printf.sprintf \"+ [%s]\\n\" (Element.innerHTML e)); (* BAD *)\n\n       Element.appendChild e (button \"Click!\" draw);\n       Element.appendChild e (button \"XXX\" (fun () -> ()));\n    )\n    l;\n\n  test_opt_args\n    (fun ?(foo = 0) ?(bar = 0) () -> string_of_int foo ^ \"/\" ^ string_of_int bar);\n\n  print_endline Person2.(to_json (mk ~children:[mk ~age:6 \"Johnny\"] ~age:42 \"John Doe\"))\n\n\n\n(* Custom mapping between association lists and JS objects *)\n\nmodule Dict : sig\n  type 'a t = (string * 'a) list\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\nend = struct\n  type 'a t = (string * 'a) list\n\n  let t_to_js ml2js l =\n    let o = Ojs.empty_obj () in\n    List.iter (fun (k, v) -> Ojs.set_prop o (Ojs.string_to_js k) (ml2js v)) l;\n    o\n\n  let t_of_js js2ml o =\n    let l = ref [] in\n    Ojs.iter_properties o\n      (fun k -> l := (k, js2ml (Ojs.get_prop o (Ojs.string_to_js k))) :: !l);\n    !l\nend\n\ninclude [%js:\nval int_dict_to_json_string: int Dict.t -> string\n  [@@js.global \"JSON.stringify\"]\n\nval myDict: string Dict.t\n  [@@js.global \"myDict\"]\n\nval set_x: int -> unit\n    [@@js.set \"x\"]\n\nval get_x: unit -> int\n    [@@js.get \"x\"]\n]\n\nlet () =\n  print_endline (int_dict_to_json_string [\"hello\", 1; \"world\", 2]);\n  List.iter (fun (k, v) -> Printf.printf \"%s -> %s\\n%!\" k v) myDict;\n  set_x 42;\n  print_endline (string_of_int (get_x ()))\n\nmodule Sum = struct\n  include [%js:\n    type t =\n      | A\n      | B of int\n      | C of int * string\n      | D of {age:int; name:string}\n    [@@js.sum]\n\n    val t_of_js: Ojs.t -> t\n    val t_to_js: t -> Ojs.t\n  ]\n\nlet print = function\n  | A -> print_endline \"A\"\n  | B n -> print_endline (Format.sprintf \"B %d\" n)\n  | C (n, s) -> print_endline (Format.sprintf \"C (%d, %S)\" n s)\n  | D {age; name} -> print_endline (Format.sprintf \"D {age = %d; name = %S}\" age name)\n\ninclude [%js:\nval set_print_sum: (t -> unit) -> unit\n    [@@js.set \"print_sum\"]\n\nval test_sum: unit -> unit\n    [@@js.global \"test_sum\"]\n]\n\nlet () =\n  set_print_sum print\n\nlet () = test_sum ()\n\nlet () =\n  Console.log console ([%js.of:t] A);\n  Console.log console ([%js.of:t] (B 42));\n  Console.log console ([%js.of:t] (C (42, \"foo\")));\n  Console.log console ([%js.of:t] (D {age=42; name=\"foo\"}))\n\nlet () =\n  Console3.log 1;\n  Console3.log2 1 \"two\";\n  Console3.log3 1 \"two\" [];\n  Console3.log4 1 \"two\" [] [|4|]\n\nlet () =\n  Console4.log  (module Ojs.Int) 1;\n  Console4.log2 (module Ojs.Int) (module Ojs.String) 1 \"two\";\n  Console4.log3 (module Ojs.Int) (module Ojs.String) (module Ojs.List(Ojs.Int)) 1 \"two\" [3]\n\nend\n\ninclude [%js:\nval test_flatten: ([`A | `B of int | `C of string | `D of int * string] [@js.enum]) -> unit\n    [@@js.global \"test_flatten\"]\n]\n\nlet () =\n  test_flatten `A;\n  test_flatten (`B 42);\n  test_flatten (`C \"hello\");\n  test_flatten (`D (42, \"foo\"))\ninclude [%js:\nval make_string : 'a -> string [@@js.global \"String\"]\n]\n\nlet () =\n  Console3.log (make_string 1234);\n  Console3.log (make_string \"string\");\n  Console3.log (make_string [\"list\"]);\n  Console3.log (make_string [|\"array\"|])\n\ninclude [%js:\nval test_typvars: 'a -> 'a * 'a\n    [@@js.global \"test_typvars\"]\n]\n\nlet () =\n  Console3.log (test_typvars `A);\n  Console3.log (test_typvars 1234);\n  Console3.log (test_typvars \"string\");\n  Console3.log (test_typvars [\"list\"])\n\nlet () =\n  let t = Ref.make \"foo\" in\n  Console3.log (Ref.current t);\n  Ref.setCurrent t \"bar\";\n  Console3.log (Ref.current t)\n\nlet () =\n  let foo = Either.left \"foo\" in\n  let foobar = Either.right [\"foo\"; \"bar\"] in\n  let f x = Either.destruct x ~left:(fun s -> s) ~right:(String.concat \"-\") in\n  Console3.log (Ojs.string_to_js (f foo));\n  Console3.log (Ojs.string_to_js (f foobar))\n\nlet () =\n  let open Variants.M3 in\n  let rec of_list = function\n  | [] -> Empty\n  | hd :: tl -> Cons (hd, of_list tl)\n  in\n  Console3.log ([%js.of: int t] (of_list [1;2;3]))\n"
  },
  {
    "path": "examples/test/test_bindings.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** Some ad hoc code to illustrate and test various aspects\n    of gen_js_api *)\n\n[@@@js.implem [@@@ocaml.warning \"-22\"]]\n\nmodule Element : sig\n  type t = private Ojs.t\n\n  val appendChild: t -> t -> unit\n  val set_innerHTML: t -> string -> unit\n  val innerHTML: t -> string\n\n  val set_onclick: t -> (unit -> unit) -> unit\n  val setAttribute: t -> string -> string -> unit\nend\n\nmodule Canvas : sig\n  module RenderingContext2D : sig\n    type t = private Ojs.t\n\n    val set_fillStyle: t -> string -> unit\n    val fillRect: t -> int -> int -> int -> int -> unit\n  end\n\n  type t = private Ojs.t\n\n  val of_element: Element.t -> t\n      [@@js.cast]\n\n  val getContext_2d: t -> RenderingContext2D.t\n      [@@js.custom\n          val get_context: t -> string -> Ojs.t\n          [@@js.call]\n\n          let getContext_2d x =\n            get_context x \"2d\"\n      ]\nend\n\n\nmodule Document : sig\n  type t = private Ojs.t\n\n  val set_title: t -> string -> unit\n  val title: t -> string\n\n  val getElementById: t -> string -> Element.t\n  val getElementsByClassName: t -> string -> Element.t array\n\n  val createElement: t -> string -> Element.t\n  val createTextNode: t -> string -> Element.t\n\n  val body: t -> Element.t\nend\n\nmodule Window : sig\n  type t = private Ojs.t\n\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n\n  val document: t -> Document.t\n\n  val set_onload: t -> (unit -> unit) -> unit\nend\n\nval window: Window.t\n\nval alert: string -> unit\n  [@@js.global]\n\nval setTimeout: (unit -> unit) -> int -> unit\n\nmodule Console: sig\n  type t = private Ojs.t\n\n  val log: t -> Ojs.t -> unit\n\n  val log_string: t -> string -> unit\n  [@@js.call \"log\"]\nend\n\nval console: Console.t\n\nmodule Person: sig\n  module Foo: sig\n    type t =\n      | Foo\n      | Bar [@js 42]\n      | OtherInt of int [@js.default]\n      | OtherString of string [@js.default]\n            [@@js.enum]\n  end\n\n  type t = private Ojs.t\n\n  val create: string -> Foo.t -> t\n  [@@js.new \"Person\"]\n\n  val name: t -> string\n  val foo: t -> Foo.t\n  val get: t -> unit -> string * Foo.t\n  [@@js.call]\n  val set: t -> string * Foo.t -> unit\n      [@@js.call]\n\n  val cast: t -> Ojs.t [@@js.cast]\nend\n\nmodule PersonObj: sig\n  class t: Ojs.t ->\n     object\n       inherit Ojs.obj\n       method name: string\n       method set_name: string -> unit\n       method foo: Person.Foo.t\n       method set_foo: Person.Foo.t -> unit\n       method get: string * Person.Foo.t [@@js.call]\n       method set: string * Person.Foo.t -> unit [@@js.call]\n     end\n\n  class person: string -> Person.Foo.t -> (int list [@js.variadic]) -> t\n\n  val create: string -> Person.Foo.t -> t\n  [@@js.new \"Person\"]\n\n  val of_person: Person.t -> t\n  [@@js.cast]\nend\n\nmodule Str: sig\n  class t: Ojs.t ->\n    object\n      inherit Ojs.obj\n      method concat: (t list [@js.variadic]) -> t\n      method to_string: string [@@js.call]\n    end\n\n  class str: string -> t [@@js.new \"String\"]\n\n  val create: string -> t\n  [@@js.new \"String\"]\nend\n\nmodule Date: sig\n  type t = private Ojs.t\n\n  val create: year:int -> month:int -> ?day:(int[@js.default 0]) -> unit -> t [@@js.new \"Date\"]\n  val to_string: t -> string [@@js.call]\nend\n\nmodule Person2: sig\n  type t = private Ojs.t\n\n  val mk: ?children:t list -> age:int -> (string[@js \"name\"]) -> t\n  [@@js.builder]\n\n  val to_json:  t -> string\n  [@@js.global \"JSON.stringify\"]\nend\n\ntype int_or_string_or_null =\n  | Int of int\n  | String of string\n  | Nothing\n    [@@js.union]\n\nval f: ([`Int of int | `String of string | `Nothing] [@js.union]) -> unit\n\nval g: int_or_string_or_null -> unit [@@js.global]\n\nmodule Verb1: sig\n  type t1 =\n    { x_coord: int;\n      y_coord: int;\n    }\n\n  class t2: Ojs.t ->\n    object\n      inherit Ojs.obj\n      method x_coord: int\n      method y_coord: int\n    end\nend [@js.verbatim_names]\n\nmodule Verb2: sig\n  type t1 =\n    { x_coord: int;\n      y_coord: int;\n    } [@@js.verbatim_names]\n\n  class t2: Ojs.t ->\n    object\n      inherit Ojs.obj\n      method x_coord: int\n      method y_coord: int\n    end [@@js.verbatim_names]\nend\n\nmodule Console2: sig\n  val log: string -> unit\n    [@@js.global]\nend [@js.scope \"console\"]\n\nmodule Console3: sig\n  val log: 'a -> unit [@@js.global \"console.log\"]\n  val log2: 'a -> 'b -> unit [@@js.global \"console.log\"]\n  val log3: 'a -> 'b -> 'c -> unit [@@js.global \"console.log\"]\n  val log4: 'a -> 'b -> 'c -> 'd -> unit [@@js.global \"console.log\"]\nend\n\nmodule Console4: sig\n  val log: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global \"console.log\"]\n  val log2:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    'a -> 'b -> unit [@@js.global \"console.log\"]\n  val log3:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    (module[@js] Ojs.T with type t = 'c) ->\n    'a -> 'b -> 'c -> unit [@@js.global \"console.log\"]\nend\n\nmodule Location: sig\n  val hash: unit -> string\n  val set_hash: string -> unit\nend [@js.scope \"location\"]\n\nmodule Location2: sig\n  val hash: unit -> string [@@js.get]\n  val set_hash: string -> unit [@@js.set]\nend [@js.scope \"location\"]\n\nmodule Location3: sig\n  val assign: string -> unit\n  val reload: ?force:bool -> unit -> unit\n  val replace: string -> unit\nend [@js.scope \"location\"]\n\nmodule Union: sig\n  type close_path\n\n  type moveto_abs\n\n  type svg_path_seg =\n    | Unknown of Ojs.t         [@js.default]\n    | Close_path of close_path [@js 1]\n    | Moveto_abs of moveto_abs [@js 2]\n          [@@js.union on_field \"pathSegType\"]\nend\n\nmodule Ref : sig\n  type 'value t = private Ojs.t\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n\n  val make: 'value -> 'value t [@@js.global \"makeRef\"]\n\n  val current : 'value t -> 'value [@@js.get \"current\"]\n\n  val setCurrent : 'value t -> 'value -> unit [@@js.set \"current\"]\nend\n\nmodule Either : sig\n  type ('a, 'b) t\n  val t_to_js: ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('a, 'b) t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> Ojs.t -> ('a, 'b) t\n\n  val left: 'a -> ('a, 'b) t [@@js.global \"eitherLeft\"]\n  val right: 'b -> ('a, 'b) t [@@js.global \"eitherRight\"]\n  val destruct: ('a, 'b) t -> left:('a -> 'c) -> right:('b -> 'c) -> 'c [@@js.global \"eitherDestruct\"]\nend\n\nmodule Alias : sig\n  module Swap : sig\n    type ('a, 'b) t = ('b, 'a) Either.t\n    val t_to_js: ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('a, 'b) t -> Ojs.t\n    val t_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> Ojs.t -> ('a, 'b) t\n  end\n\n  (* Error: Contravariant type parameter !\n  module E : sig\n    type 'a t = 'a -> int\n  end *)\n\n  module Id : sig\n    type 'a t = 'a\n    val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n    val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n  end\n\n  module Arrow : sig\n    type 'a t = ('a -> int) -> string\n    val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n    val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n  end\n\n  module Record : sig\n    type ('a, 'b) t =\n      {\n        x: 'a;\n        y: 'b\n      }\n    val t_to_js: ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('a, 'b) t -> Ojs.t\n    val t_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> Ojs.t -> ('a, 'b) t\n  end\n\nend\n\nmodule Variants : sig\n\n  module M1 : sig\n    type 'a t =\n      | X of 'a\n      | Y of int\n      [@@js.sum]\n  end\n\n  module M2 : sig\n    type ('a, 'b) t =\n      | X of 'a\n      | Y of 'b\n      [@@js.sum]\n  end\n\n  module M3 : sig\n    type 'a t =\n      | Empty\n      | Cons of 'a * 'a t\n      [@@js.sum]\n\n    val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n    val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n  end\n\n(* Error: Contravariant type parameter !\n  module E : sig\n    type 'a t =\n      | F of ('a -> int)\n      [@@js.sum]\n  end\n*)\n  module M4 : sig\n    type 'a t =\n      | F of (('a -> int) -> int)\n      [@@js.sum]\n  end\n\nend\n"
  },
  {
    "path": "gen_js_api.opam",
    "content": "# This file is generated by dune, edit dune-project instead\nopam-version: \"2.0\"\nversion: \"1.1.7\"\nsynopsis: \"Easy OCaml bindings for JavaScript libraries\"\ndescription: \"\"\"\n\ngen_js_api aims at simplifying the creation of OCaml bindings for\nJavaScript libraries.  Authors of bindings write OCaml signatures for\nJavaScript libraries and the tool generates the actual binding code\nwith a combination of implicit conventions and explicit annotations.\n\ngen_js_api is to be used with the js_of_ocaml compiler.\n \"\"\"\nmaintainer: [\"Alain Frisch <alain.frisch@lexifi.com>\"]\nauthors: [\n  \"Alain Frisch <alain.frisch@lexifi.com>\"\n  \"Sebastien Briais <sebastien.briais@lexifi.com>\"\n]\nlicense: \"MIT\"\nhomepage: \"https://github.com/LexiFi/gen_js_api\"\nbug-reports: \"https://github.com/LexiFi/gen_js_api/issues\"\ndepends: [\n  \"dune\" {>= \"3.17\"}\n  \"ocaml\" {>= \"4.13\"}\n  \"ppxlib\" {>= \"0.37\"}\n  \"js_of_ocaml-compiler\" {with-test}\n  \"ojs\" {= version}\n  \"odoc\" {with-doc}\n]\nconflicts: [\n  \"js_of_ocaml-compiler\" {< \"6.3.0\"}\n]\nbuild: [\n  [\"dune\" \"subst\"] {dev}\n  [\n    \"dune\"\n    \"build\"\n    \"-p\"\n    name\n    \"-j\"\n    jobs\n    \"@install\"\n    \"@runtest\" {with-test}\n    \"@doc\" {with-doc}\n  ]\n]\ndev-repo: \"git+https://github.com/LexiFi/gen_js_api.git\"\n"
  },
  {
    "path": "lib/dune",
    "content": "(library\n (public_name ojs)\n (synopsis \"Runtime support for gen_js_api\")\n (libraries js_of_ocaml-compiler.runtime)\n (wrapped false)\n (foreign_stubs\n  (language c)\n  (names ojs_runtime_stubs))\n (modes byte)\n (js_of_ocaml\n  (javascript_files ojs_runtime.js)))\n"
  },
  {
    "path": "lib/ojs.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(* This module (mostly) abstracts away from js_of_ocaml encoding of\n   OCaml values.  It serves as a support library for the code generated\n   by gen_js_api.\n\n   The module could mostly be implemented on top of js_of_ocaml's Js module\n   (and in particular Js.Unsafe), but we prefer to drop the dependency\n   to js_of_ocaml's library and to rely only on its compiler and JS\n   runtime code.\n*)\n\n\ntype t\n\nexternal t_of_js: t -> t = \"%identity\"\nexternal t_to_js: t -> t = \"%identity\"\n\nexternal string_of_js: t -> string = \"caml_js_to_string\"\nexternal string_to_js: string -> t = \"caml_js_from_string\"\n\nexternal int_of_js: t -> int = \"%identity\"\nexternal int_to_js: int -> t = \"%identity\"\n\nexternal bool_of_js: t -> bool = \"caml_js_to_bool\"\nexternal bool_to_js: bool -> t = \"caml_js_from_bool\"\n\nexternal float_of_js: t -> float = \"caml_js_to_float\"\nexternal float_to_js: float -> t = \"caml_js_from_float\"\n\nexternal obj: (string * t) array -> t = \"caml_js_object\"\n\nexternal variable: string -> t = \"caml_js_var\"\n\nexternal get: t -> string -> t = \"caml_js_get\"\nexternal set: t -> string -> t -> unit = \"caml_js_set\"\nexternal delete: t -> string -> unit = \"caml_js_delete\"\n\nexternal get_prop: t -> t -> t = \"caml_js_get\"\nexternal set_prop: t -> t -> t -> unit = \"caml_js_set\"\nexternal delete_prop: t -> t -> unit = \"caml_js_delete\"\n\nexternal get_prop_ascii: t -> string -> t = \"caml_js_get\"\nexternal set_prop_ascii: t -> string -> t -> unit = \"caml_js_set\"\nexternal delete_prop_ascii: t -> string -> unit = \"caml_js_delete\"\n\nexternal internal_type_of: t -> t = \"caml_js_typeof\"\nlet type_of x = string_of_js (internal_type_of x)\n\nexternal internal_instance_of: t -> t -> t = \"caml_js_instanceof\"\nlet instance_of x ~constr = bool_of_js (internal_instance_of x constr)\n\nexternal pure_js_expr: string -> t = \"caml_pure_js_expr\"\nlet null = pure_js_expr \"null\"\nlet undefined = pure_js_expr \"undefined\"\n\nexternal equals: t -> t -> bool = \"caml_js_equals\"\n\nlet global = pure_js_expr \"globalThis\"\n\nexternal new_obj: t -> t array -> t = \"caml_js_new\"\n\nexternal call: t -> string -> t array -> t = \"caml_js_meth_call\"\nexternal apply: t -> t array -> t = \"caml_js_fun_call\"\n\nlet array_make n = new_obj (get_prop_ascii global \"Array\") [|int_to_js n|]\nlet array_get t i = get_prop t (int_to_js i)\nlet array_set t i x = set_prop t (int_to_js i) x\n\nlet array_of_js_from f objs start =\n  let n = int_of_js (get_prop_ascii objs \"length\") in\n  Array.init (n - start) (fun i -> f (array_get objs (start + i)))\n\nlet array_of_js f objs = array_of_js_from f objs 0\n\nlet array_to_js f arr =\n  let n = Array.length arr in\n  let a = array_make n in\n  for i = 0 to n - 1 do\n    array_set a i (f arr.(i))\n  done;\n  a\n\nlet list_of_js_from f objs start = Array.to_list (array_of_js_from f objs start)\n\nlet list_of_js f objs = list_of_js_from f objs 0\n\nlet list_to_js f l =\n  array_to_js f (Array.of_list l)\n\nlet option_of_js f x =\n  if equals x null then None\n  else Some (f x)\n\nlet option_to_js f = function\n  | Some x -> f x\n  | None -> null\n\nlet unit_to_js () = undefined\nlet unit_of_js _ = ()\n\nclass obj (x:t) =\n  object\n    method to_js = x\n  end\n\nexternal fun_to_js: int -> (t -> 'a) -> t = \"caml_js_wrap_callback_strict\"\nexternal fun_to_js_args: (t -> 'a) -> t = \"caml_ojs_wrap_fun_arguments\"\n\nlet has_property o x =\n  type_of o = \"object\" && o != null\n  && get_prop o (string_to_js x) != undefined\n\nexternal new_obj_arr: t -> t -> t = \"caml_ojs_new_arr\"\n\nlet empty_obj () = new_obj (get_prop_ascii global \"Object\") [||]\n\nexternal iter_properties_untyped : t -> t -> unit = \"caml_ojs_iterate_properties\"\nlet iter_properties x f =\n  iter_properties_untyped x (fun_to_js 1 (fun x -> f (string_of_js x)))\n\nlet apply_arr o arr = call o \"apply\" [| null; arr |]\nlet call_arr o s arr = call (get_prop o (string_to_js s)) \"apply\" [| o; arr |]\n\nlet is_null x =\n  equals x null\n\nlet obj_type x =\n  string_of_js (call (pure_js_expr \"Object.prototype.toString\") \"call\" [|x|])\n\nmodule type T = sig\n  type js := t\n  type t\n  val t_to_js : t -> js\n  val t_of_js : js -> t\nend\n\n(* Ojs.T instances for built-in types *)\nmodule Int = struct\n  type t = int\n  let t_to_js = int_to_js\n  let t_of_js = int_of_js\n end\nmodule String = struct\n  type t = string\n  let t_to_js = string_to_js\n  let t_of_js = string_of_js\nend\nmodule Bool = struct\n  type t = bool\n  let t_to_js = bool_to_js\n  let t_of_js = bool_of_js\nend\nmodule Float = struct\n  type t = float\n  let t_to_js = float_to_js\n  let t_of_js = float_of_js\nend\nmodule Array (A: T) = struct\n  type t = A.t array\n  let t_to_js = array_to_js A.t_to_js\n  let t_of_js = array_of_js A.t_of_js\nend\nmodule List (A: T) = struct\n  type t = A.t list\n  let t_to_js = list_to_js A.t_to_js\n  let t_of_js = list_of_js A.t_of_js\nend\nmodule Option (A: T) = struct\n  type t = A.t option\n  let t_to_js = option_to_js A.t_to_js\n  let t_of_js = option_of_js A.t_of_js\nend\n"
  },
  {
    "path": "lib/ojs.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** Binding with JS values. *)\n\ntype t\n(** The universal type representing arbitrary JS values. *)\n\n(** {2 Mapper for built-in types} *)\n\nexternal t_of_js: t -> t = \"%identity\"\nexternal t_to_js: t -> t = \"%identity\"\n\nexternal string_of_js: t -> string = \"caml_js_to_string\"\nexternal string_to_js: string -> t = \"caml_js_from_string\"\n\nexternal int_of_js: t -> int = \"%identity\"\nexternal int_to_js: int -> t = \"%identity\"\n\nexternal bool_of_js: t -> bool = \"caml_js_to_bool\"\nexternal bool_to_js: bool -> t = \"caml_js_from_bool\"\n\nexternal float_of_js: t -> float = \"caml_js_to_float\"\nexternal float_to_js: float -> t = \"caml_js_from_float\"\n\nval array_of_js: (t -> 'a) -> t -> 'a array\nval array_to_js: ('a -> t) -> 'a array -> t\n\nval list_of_js: (t -> 'a) -> t -> 'a list\nval list_to_js: ('a -> t) -> 'a list -> t\n\nval array_of_js_from: (t -> 'a) -> t -> int -> 'a array\nval list_of_js_from: (t -> 'a) -> t -> int -> 'a list\n\nval option_of_js: (t -> 'a) -> t -> 'a option\n(** Both [null] and [undefined] are mapped to [None]. *)\n\nval option_to_js: ('a -> t) -> 'a option -> t\n(** [None] is mapped to [null]. *)\n\nval unit_of_js: t -> unit\nval unit_to_js: unit -> t\n\n\n(** {2 Wrap OCaml functions as JS functions} *)\n\nexternal fun_to_js: int -> (t -> 'a) -> t = \"caml_js_wrap_callback_strict\"\n(** Wrap an OCaml function of known arity (>=1) into a JS function.\n    Extra arguments are discarded and missing argument are filled with\n    'undefined'.\n*)\n\nexternal fun_to_js_args: (t -> 'a) -> t = \"caml_ojs_wrap_fun_arguments\"\n(** Wrap an OCaml function taking JS arguments as a JS array. *)\n\n\n(** {2 JS objects} *)\n\nexternal get: t -> string -> t = \"caml_js_get\"\n  [@@ocaml.deprecated \"Use Ojs.get_prop_ascii instead.\"]\n\nexternal set: t -> string -> t -> unit = \"caml_js_set\"\n  [@@ocaml.deprecated \"Use Ojs.set_prop_ascii instead.\"]\n\nexternal delete: t -> string -> unit = \"caml_js_delete\"\n  [@@ocaml.deprecated \"Use Ojs.delete_prop_ascii instead.\"]\n\nexternal get_prop_ascii: t -> string -> t = \"caml_js_get\"\n  (** Get the property from an object (only works if the property key is a plain ascii string). *)\n\nexternal set_prop_ascii: t -> string -> t -> unit = \"caml_js_set\"\n  (** Set an object property (only works if the property key is a plain ascii string). *)\n\nexternal delete_prop_ascii: t -> string -> unit = \"caml_js_delete\"\n  (** Delete an object property (only works if the property key is a plain ascii string). *)\n\nexternal get_prop: t -> t -> t = \"caml_js_get\"\n  (** Get the property from an object. *)\n\nexternal set_prop: t -> t -> t -> unit = \"caml_js_set\"\n  (** Set an object property. *)\n\nexternal delete_prop: t -> t -> unit = \"caml_js_delete\"\n  (** Delete an object property. *)\n\nexternal obj: (string * t) array -> t = \"caml_js_object\"\n\nval empty_obj: unit -> t\n\nval has_property: t -> string -> bool\nval iter_properties: t -> (string -> unit) -> unit\n\n(** {2 Calling JS functions} *)\n\nexternal call: t -> string -> t array -> t = \"caml_js_meth_call\"\n(** Call a method on an object (binding 'this' to the object). *)\n\nexternal apply: t -> t array -> t = \"caml_js_fun_call\"\n(** Call a function. *)\n\nexternal new_obj: t -> t array -> t = \"caml_js_new\"\n(** Call a constructor *)\n\nval call_arr: t -> string -> t -> t\n(** Variant of [Ojs.call] where the arguments are passed as an already\n    built JS array. *)\n\nval apply_arr: t -> t -> t\n(** Variant of [Ojs.apply] where the arguments are passed as an already\n    built JS array. *)\n\nexternal new_obj_arr: t -> t -> t = \"caml_ojs_new_arr\"\n(** Variant of [Ojs.new_obj] where the arguments are passed as an already\n    built JS array. *)\n\n(** {2 Arrays} *)\n\nval array_make: int -> t\nval array_get: t -> int -> t\nval array_set: t -> int -> t -> unit\n\n(** {2 Misc} *)\n\nval global: t\nval null: t\n\nexternal variable: string -> t = \"caml_js_var\"\n\nval type_of: t -> string\n\nval instance_of: t -> constr:t -> bool\n\nclass obj: t ->\n  object\n    method to_js: t\n  end\n\nval is_null: t -> bool\n\nval obj_type: t -> string\n(** Returns:\n    \"[object Array]\"\n    \"[object Object]\"\n    \"[object Number]\"\n    \"[object String]\"\n    \"[object Null]\"\n    \"[object Boolean]\"\n*)\n\nmodule type T =\n  sig\n    type js := t\n    type t\n    val t_to_js : t -> js\n    val t_of_js : js -> t\n  end\n\n(* Ojs.T instances for built-in types *)\nmodule Int : T with type t = int\nmodule String : T with type t = string\nmodule Bool : T with type t = bool\nmodule Float : T with type t = float\nmodule Array (A: T) : T with type t = A.t array\nmodule List (A: T) : T with type t = A.t list\nmodule Option (A: T) : T with type t = A.t option\n"
  },
  {
    "path": "lib/ojs_exn.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\ntype t = Jsoo_runtime.Error.t\n\nexternal coerce : t -> Ojs.t = \"%identity\"\nlet name x = Ojs.string_of_js (Ojs.get_prop_ascii (coerce x) \"name\")\nlet message x = Ojs.string_of_js (Ojs.get_prop_ascii (coerce x) \"message\")\nlet stack x = Ojs.option_of_js Ojs.string_of_js (Ojs.get_prop_ascii (coerce x) \"stack\")\nlet to_string x = Ojs.string_of_js (Ojs.call (coerce x) \"toString\" [||])\n\nexception Error = Jsoo_runtime.Error.Exn\n\nlet () =\n  Printexc.register_printer (function\n      | Error x -> Some (to_string x)\n      | _ -> None\n    )\n"
  },
  {
    "path": "lib/ojs_exn.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n(** OCaml view on JS exceptions *)\n\ntype t\n\nval name: t -> string\nval message: t -> string\nval stack: t -> string option\nval to_string: t -> string\n\nexception Error of t\n"
  },
  {
    "path": "lib/ojs_runtime.js",
    "content": "//Provides: caml_ojs_wrap_fun_arguments\n//Requires: caml_js_wrap_callback\nfunction caml_ojs_wrap_fun_arguments(f) {\n  return function() {\n    return caml_js_wrap_callback(f)(arguments);\n  }\n}\n\n//Provides: caml_ojs_iterate_properties\n//Requires: caml_js_to_string\nfunction caml_ojs_iterate_properties(o, f) {\n  var name;\n  for(name in o) {\n    if(o.hasOwnProperty(name)) {\n      f(name);\n    }\n  }\n}\n"
  },
  {
    "path": "lib/ojs_runtime_stubs.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\nvoid caml_ojs_wrap_fun_arguments () {\n  fprintf(stderr, \"Unimplemented JavaScript primitive caml_ojs_wrap_fun_arguments!\\n\");\n  exit(1);\n}\nvoid caml_ojs_iterate_properties () {\n  fprintf(stderr, \"Unimplemented JavaScript primitive caml_ojs_iterate_properties!\\n\");\n  exit(1);\n}\n"
  },
  {
    "path": "node-test/bindings/arrays.mli",
    "content": "module JsArray (E: Ojs.T): sig\n  type t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val create: unit -> t [@@js.new \"Array\"]\n  val push: t -> E.t -> unit [@@js.call]\n  val pop: t -> E.t option [@@js.call]\nend\n\nmodule UntypedArray : sig\n  include (module type of JsArray(Ojs))\nend\n\nmodule StringArray : sig\n  include (module type of JsArray(Ojs.String))\n\n  val join: t -> string -> string [@@js.call]\nend\n\nmodule[@js.scope \"Array\"] JsArray2: sig\n  type 'a t\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n\n  val create: unit -> 'a t [@@js.create]\n  val create': (module[@js] Ojs.T with type t = 'a) -> ('a list [@js.variadic]) -> 'a t [@@js.create]\n\n  val push: (module[@js] Ojs.T with type t = 'a) -> 'a t -> 'a -> unit [@@js.call]\n  val pop:  (module[@js] Ojs.T with type t = 'a) -> 'a t -> 'a option [@@js.call]\n\n  val get: (module[@js] Ojs.T with type t = 'a) -> 'a t -> int -> 'a option [@@js.index_get]\n  val set: (module[@js] Ojs.T with type t = 'a) -> 'a t -> int -> 'a -> unit [@@js.index_set]\n\n  val join: string t -> string -> string [@@js.call]\nend"
  },
  {
    "path": "node-test/bindings/buffer.mli",
    "content": "[@@@js.scope \"Buffer\"]\n\ntype t = private Ojs.t\nval t_of_js: Ojs.t -> t\nval t_to_js: t -> Ojs.t\n\nval alloc: int -> t[@@js.global]\nval from: string -> t[@@js.global]\nval concat: t list -> t[@@js.global]\n\nval length: t -> int [@@js.get]\nval get: t -> int -> int option [@@js.index_get]\nval set: t -> int -> int -> unit[@@js.index_set]\nval write: t -> string -> int[@@js.call]\nval slice: t -> int -> int -> t[@@js.call]\nval to_string: t -> string[@@js.call]\nval copy: t -> dst:t -> start:int -> dst_start:int -> dst_end:int -> int[@@js.call]\n"
  },
  {
    "path": "node-test/bindings/console.mli",
    "content": "[@@@js.scope \"console\"]\n\nval log: 'a -> unit [@@js.global]\nval error: 'a -> unit [@@js.global]\n\nmodule T : sig\n  val log: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global]\n  val error: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global]\nend"
  },
  {
    "path": "node-test/bindings/container.ml",
    "content": "module StringMap = struct\n  include Map.Make(String)\n\n  let t_to_js ml2js l =\n    let o = Ojs.empty_obj () in\n    iter (fun k v -> Ojs.set_prop o (Ojs.string_to_js k) (ml2js v)) l;\n    o\n\n  let t_of_js js2ml o =\n    let l = ref empty in\n    Ojs.iter_properties o\n      (fun k -> l := add k (js2ml (Ojs.get_prop o (Ojs.string_to_js k))) !l);\n    !l\nend\n"
  },
  {
    "path": "node-test/bindings/container.mli",
    "content": "module StringMap : sig\n  include Map.S with type key = string\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\nend"
  },
  {
    "path": "node-test/bindings/dune",
    "content": "(library\n (name node)\n (synopsis \"Bindings\")\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes byte)\n (js_of_ocaml\n  (javascript_files imports.js))\n (wasm_of_ocaml\n  (javascript_files imports.js imports.wat)))\n\n(rule\n (targets imports.ml)\n (deps imports.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/imports.ml imports.ml)))\n\n(rule\n (targets errors.ml)\n (deps errors.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/errors.ml errors.ml)))\n\n(rule\n (targets global.ml)\n (deps global.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/global.ml global.ml)))\n\n(rule\n (targets promise.ml)\n (deps promise.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/promise.ml promise.ml)))\n\n(rule\n (targets buffer.ml)\n (deps buffer.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/buffer.ml buffer.ml)))\n\n(rule\n (targets fs.ml)\n (deps fs.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/fs.ml fs.ml)))\n\n(rule\n (targets path.ml)\n (deps path.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/path.ml path.ml)))\n\n(rule\n (targets process.ml)\n (deps process.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/process.ml process.ml)))\n\n(rule\n (targets console.ml)\n (deps console.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/console.ml console.ml)))\n\n(rule\n (targets arrays.ml)\n (deps arrays.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/arrays.ml arrays.ml)))\n\n(rule\n (targets number.ml)\n (deps number.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/number.ml number.ml)))"
  },
  {
    "path": "node-test/bindings/errors.mli",
    "content": "module [@js.scope] Error : sig\n  type t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val create: string -> t [@@js.create]\n  val stack_trace_limit: int [@@js.global]\n  val set_stack_trace_limit: int -> unit [@@js.set]\n\n  val code: t -> string [@@js.get]\n  val message: t -> string [@@js.get]\n  val stack: t -> string [@@js.get]\nend\n"
  },
  {
    "path": "node-test/bindings/expected/arrays.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule JsArray(E:Ojs.T) =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let create : unit -> t =\n      fun () ->\n        t_of_js (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||])\n    let push : t -> E.t -> unit =\n      fun (x4 : t) (x3 : E.t) ->\n        ignore (Ojs.call (t_to_js x4) \"push\" [|(E.t_to_js x3)|])\n    let pop : t -> E.t option =\n      fun (x5 : t) ->\n        Ojs.option_of_js E.t_of_js (Ojs.call (t_to_js x5) \"pop\" [||])\n  end\nmodule UntypedArray = struct include (JsArray)(Ojs) end\nmodule StringArray =\n  struct\n    include (JsArray)(Ojs.String)\n    let join : t -> string -> string =\n      fun (x8 : t) (x7 : string) ->\n        Ojs.string_of_js\n          (Ojs.call (t_to_js x8) \"join\" [|(Ojs.string_to_js x7)|])\n  end\nmodule JsArray2 =\n  struct\n    type 'a t = Ojs.t\n    let rec t_of_js : 'a . (Ojs.t -> 'a) -> Ojs.t -> 'a t =\n      fun (type __a) (__a_of_js : Ojs.t -> __a) -> fun (x10 : Ojs.t) -> x10\n    and t_to_js : 'a . ('a -> Ojs.t) -> 'a t -> Ojs.t =\n      fun (type __a) (__a_to_js : __a -> Ojs.t) -> fun (x9 : Ojs.t) -> x9\n    let create : unit -> 'a t =\n      fun () ->\n        t_of_js Obj.magic\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||])\n    let create' : (module Ojs.T with type t = 'a) -> 'a list -> 'a t =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x12 : a list) ->\n          t_of_js A.t_of_js\n            (Ojs.new_obj_arr (Ojs.get_prop_ascii Ojs.global \"Array\")\n               (let x13 =\n                  Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                List.iter\n                  (fun (x14 : a) ->\n                     ignore (Ojs.call x13 \"push\" [|(A.t_to_js x14)|])) x12;\n                x13))\n    let push : (module Ojs.T with type t = 'a) -> 'a t -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x17 : a t)\n          (x16 : a) ->\n          ignore\n            (Ojs.call (t_to_js A.t_to_js x17) \"push\" [|(A.t_to_js x16)|])\n    let pop : (module Ojs.T with type t = 'a) -> 'a t -> 'a option =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x19 : a t) ->\n          Ojs.option_of_js A.t_of_js\n            (Ojs.call (t_to_js A.t_to_js x19) \"pop\" [||])\n    let get : (module Ojs.T with type t = 'a) -> 'a t -> int -> 'a option =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x22 : a t)\n          (x24 : int) ->\n          Ojs.option_of_js A.t_of_js\n            (Ojs.array_get (t_to_js A.t_to_js x22) x24)\n    let set : (module Ojs.T with type t = 'a) -> 'a t -> int -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x26 : a t)\n          (x28 : int) (x29 : a) ->\n          Ojs.array_set (t_to_js A.t_to_js x26) x28 (A.t_to_js x29)\n    let join : string t -> string -> string =\n      fun (x31 : string t) (x30 : string) ->\n        Ojs.string_of_js\n          (Ojs.call (t_to_js Ojs.string_to_js x31) \"join\"\n             [|(Ojs.string_to_js x30)|])\n  end\n"
  },
  {
    "path": "node-test/bindings/expected/buffer.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\ntype t = Ojs.t\nlet rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\nand t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\nlet alloc : int -> t =\n  fun (x3 : int) ->\n    t_of_js\n      (Ojs.call (Ojs.get_prop_ascii Ojs.global \"Buffer\") \"alloc\"\n         [|(Ojs.int_to_js x3)|])\nlet from : string -> t =\n  fun (x4 : string) ->\n    t_of_js\n      (Ojs.call (Ojs.get_prop_ascii Ojs.global \"Buffer\") \"from\"\n         [|(Ojs.string_to_js x4)|])\nlet concat : t list -> t =\n  fun (x5 : t list) ->\n    t_of_js\n      (Ojs.call (Ojs.get_prop_ascii Ojs.global \"Buffer\") \"concat\"\n         [|(Ojs.list_to_js t_to_js x5)|])\nlet length : t -> int =\n  fun (x7 : t) -> Ojs.int_of_js (Ojs.get_prop_ascii (t_to_js x7) \"length\")\nlet get : t -> int -> int option =\n  fun (x8 : t) (x9 : int) ->\n    Ojs.option_of_js Ojs.int_of_js (Ojs.array_get (t_to_js x8) x9)\nlet set : t -> int -> int -> unit =\n  fun (x11 : t) (x12 : int) (x13 : int) ->\n    Ojs.array_set (t_to_js x11) x12 (Ojs.int_to_js x13)\nlet write : t -> string -> int =\n  fun (x15 : t) (x14 : string) ->\n    Ojs.int_of_js (Ojs.call (t_to_js x15) \"write\" [|(Ojs.string_to_js x14)|])\nlet slice : t -> int -> int -> t =\n  fun (x18 : t) (x16 : int) (x17 : int) ->\n    t_of_js\n      (Ojs.call (t_to_js x18) \"slice\"\n         [|(Ojs.int_to_js x16);(Ojs.int_to_js x17)|])\nlet to_string : t -> string =\n  fun (x19 : t) -> Ojs.string_of_js (Ojs.call (t_to_js x19) \"toString\" [||])\nlet copy : t -> dst:t -> start:int -> dst_start:int -> dst_end:int -> int =\n  fun (x24 : t) ~dst:(x20 : t) ~start:(x21 : int) ~dst_start:(x22 : int)\n    ~dst_end:(x23 : int) ->\n    Ojs.int_of_js\n      (Ojs.call (t_to_js x24) \"copy\"\n         [|(t_to_js x20);(Ojs.int_to_js x21);(Ojs.int_to_js x22);(Ojs.int_to_js\n                                                                    x23)|])\n"
  },
  {
    "path": "node-test/bindings/expected/console.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nlet log : 'a -> unit =\n  fun (x1 : 'a) ->\n    ignore\n      (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n         [|(Obj.magic x1)|])\nlet error : 'a -> unit =\n  fun (x2 : 'a) ->\n    ignore\n      (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"error\"\n         [|(Obj.magic x2)|])\nmodule T =\n  struct\n    let log : (module Ojs.T with type t = 'a) -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x3 : a) ->\n          ignore\n            (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n               [|(A.t_to_js x3)|])\n    let error : (module Ojs.T with type t = 'a) -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x4 : a) ->\n          ignore\n            (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"error\"\n               [|(A.t_to_js x4)|])\n  end\n"
  },
  {
    "path": "node-test/bindings/expected/errors.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule Error =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let create : string -> t =\n      fun (x3 : string) ->\n        t_of_js\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Error\")\n             [|(Ojs.string_to_js x3)|])\n    let stack_trace_limit : int =\n      Ojs.int_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Error\")\n           \"stackTraceLimit\")\n    let set_stack_trace_limit : int -> unit =\n      fun (x4 : int) ->\n        Ojs.set_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Error\")\n          \"stackTraceLimit\" (Ojs.int_to_js x4)\n    let code : t -> string =\n      fun (x5 : t) ->\n        Ojs.string_of_js (Ojs.get_prop_ascii (t_to_js x5) \"code\")\n    let message : t -> string =\n      fun (x6 : t) ->\n        Ojs.string_of_js (Ojs.get_prop_ascii (t_to_js x6) \"message\")\n    let stack : t -> string =\n      fun (x7 : t) ->\n        Ojs.string_of_js (Ojs.get_prop_ascii (t_to_js x7) \"stack\")\n  end\n"
  },
  {
    "path": "node-test/bindings/expected/fs.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule Dirent =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let name : t -> string =\n      fun (x3 : t) ->\n        Ojs.string_of_js (Ojs.get_prop_ascii (t_to_js x3) \"name\")\n    let is_file : t -> bool =\n      fun (x4 : t) -> Ojs.bool_of_js (Ojs.call (t_to_js x4) \"isFile\" [||])\n    let is_directory : t -> bool =\n      fun (x5 : t) ->\n        Ojs.bool_of_js (Ojs.call (t_to_js x5) \"isDirectory\" [||])\n  end\nmodule Dir =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x7 : Ojs.t) -> x7\n    and t_to_js : t -> Ojs.t = fun (x6 : Ojs.t) -> x6\n    let path : t -> string =\n      fun (x8 : t) ->\n        Ojs.string_of_js (Ojs.get_prop_ascii (t_to_js x8) \"path\")\n    let close : t -> unit Promise.t =\n      fun (x9 : t) ->\n        Promise.t_of_js Ojs.unit_of_js (Ojs.call (t_to_js x9) \"close\" [||])\n    let read : t -> Dirent.t option Promise.t =\n      fun (x11 : t) ->\n        Promise.t_of_js\n          (fun (x12 : Ojs.t) -> Ojs.option_of_js Dirent.t_of_js x12)\n          (Ojs.call (t_to_js x11) \"read\" [||])\n  end\nmodule FileHandle =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x15 : Ojs.t) -> x15\n    and t_to_js : t -> Ojs.t = fun (x14 : Ojs.t) -> x14\n    type read = {\n      bytes_read: int ;\n      buffer: Buffer.t }\n    let rec read_of_js : Ojs.t -> read =\n      fun (x17 : Ojs.t) ->\n        {\n          bytes_read = (Ojs.int_of_js (Ojs.get_prop_ascii x17 \"bytesRead\"));\n          buffer = (Buffer.t_of_js (Ojs.get_prop_ascii x17 \"buffer\"))\n        }\n    and read_to_js : read -> Ojs.t =\n      fun (x16 : read) ->\n        Ojs.obj\n          [|(\"bytesRead\", (Ojs.int_to_js x16.bytes_read));(\"buffer\",\n                                                            (Buffer.t_to_js\n                                                               x16.buffer))|]\n    let append_file : t -> Buffer.t -> unit Promise.t =\n      fun (x19 : t) (x18 : Buffer.t) ->\n        Promise.t_of_js Ojs.unit_of_js\n          (Ojs.call (t_to_js x19) \"appendFile\" [|(Buffer.t_to_js x18)|])\n    let read : t -> Buffer.t -> int -> int -> int -> read Promise.t =\n      fun (x25 : t) (x21 : Buffer.t) (x22 : int) (x23 : int) (x24 : int) ->\n        Promise.t_of_js read_of_js\n          (Ojs.call (t_to_js x25) \"read\"\n             [|(Buffer.t_to_js x21);(Ojs.int_to_js x22);(Ojs.int_to_js x23);(\n               Ojs.int_to_js x24)|])\n    let chmod : t -> int -> unit Promise.t =\n      fun (x28 : t) (x27 : int) ->\n        Promise.t_of_js Ojs.unit_of_js\n          (Ojs.call (t_to_js x28) \"chmod\" [|(Ojs.int_to_js x27)|])\n    let chmown : t -> uid:int -> gid:int -> unit Promise.t =\n      fun (x32 : t) ~uid:(x30 : int) ~gid:(x31 : int) ->\n        Promise.t_of_js Ojs.unit_of_js\n          (Ojs.call (t_to_js x32) \"chmown\"\n             [|(Ojs.int_to_js x30);(Ojs.int_to_js x31)|])\n    let close : t -> unit Promise.t =\n      fun (x34 : t) ->\n        Promise.t_of_js Ojs.unit_of_js (Ojs.call (t_to_js x34) \"close\" [||])\n    let datasync : t -> unit Promise.t =\n      fun (x36 : t) ->\n        Promise.t_of_js Ojs.unit_of_js\n          (Ojs.call (t_to_js x36) \"datasync\" [||])\n    let fd : t -> int =\n      fun (x38 : t) -> Ojs.int_of_js (Ojs.get_prop_ascii (t_to_js x38) \"fd\")\n  end\nlet readdir : string -> string list Promise.t =\n  fun (x39 : string) ->\n    Promise.t_of_js\n      (fun (x40 : Ojs.t) -> Ojs.list_of_js Ojs.string_of_js x40)\n      (Ojs.call\n         (Ojs.get_prop_ascii (Jsoo_runtime.Js.runtime_value \"node_fs\")\n            \"promises\") \"readdir\" [|(Ojs.string_to_js x39)|])\nlet open_ : string -> flag:string -> FileHandle.t Promise.t =\n  fun (x42 : string) ~flag:(x43 : string) ->\n    Promise.t_of_js FileHandle.t_of_js\n      (Ojs.call\n         (Ojs.get_prop_ascii (Jsoo_runtime.Js.runtime_value \"node_fs\")\n            \"promises\") \"open\"\n         [|(Ojs.string_to_js x42);(Ojs.string_to_js x43)|])\nlet rmdir : string -> unit Promise.t =\n  fun (x45 : string) ->\n    Promise.t_of_js Ojs.unit_of_js\n      (Ojs.call\n         (Ojs.get_prop_ascii (Jsoo_runtime.Js.runtime_value \"node_fs\")\n            \"promises\") \"rmdir\" [|(Ojs.string_to_js x45)|])\nlet rename : string -> string -> unit Promise.t =\n  fun (x47 : string) (x48 : string) ->\n    Promise.t_of_js Ojs.unit_of_js\n      (Ojs.call\n         (Ojs.get_prop_ascii (Jsoo_runtime.Js.runtime_value \"node_fs\")\n            \"promises\") \"rename\"\n         [|(Ojs.string_to_js x47);(Ojs.string_to_js x48)|])\nlet unlink : string -> unit Promise.t =\n  fun (x50 : string) ->\n    Promise.t_of_js Ojs.unit_of_js\n      (Ojs.call\n         (Ojs.get_prop_ascii (Jsoo_runtime.Js.runtime_value \"node_fs\")\n            \"promises\") \"unlink\" [|(Ojs.string_to_js x50)|])\n"
  },
  {
    "path": "node-test/bindings/expected/global.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\ntype timeout_id = Ojs.t\nlet rec timeout_id_of_js : Ojs.t -> timeout_id = fun (x2 : Ojs.t) -> x2\nand timeout_id_to_js : timeout_id -> Ojs.t = fun (x1 : Ojs.t) -> x1\ntype interval_id = Ojs.t\nlet rec interval_id_of_js : Ojs.t -> interval_id = fun (x4 : Ojs.t) -> x4\nand interval_id_to_js : interval_id -> Ojs.t = fun (x3 : Ojs.t) -> x3\nlet set_interval : (unit -> unit) -> int -> interval_id =\n  fun (x5 : unit -> unit) (x6 : int) ->\n    interval_id_of_js\n      (Ojs.call Ojs.global \"setInterval\"\n         [|(Ojs.fun_to_js 1 (fun _ -> x5 ()));(Ojs.int_to_js x6)|])\nlet set_timeout : (unit -> unit) -> int -> timeout_id =\n  fun (x7 : unit -> unit) (x8 : int) ->\n    timeout_id_of_js\n      (Ojs.call Ojs.global \"setTimeout\"\n         [|(Ojs.fun_to_js 1 (fun _ -> x7 ()));(Ojs.int_to_js x8)|])\nlet clear_timeout : timeout_id -> unit =\n  fun (x9 : timeout_id) ->\n    ignore (Ojs.call Ojs.global \"clearTimeout\" [|(timeout_id_to_js x9)|])\nlet clear_interval : interval_id -> unit =\n  fun (x10 : interval_id) ->\n    ignore (Ojs.call Ojs.global \"clearInterval\" [|(interval_id_to_js x10)|])\n"
  },
  {
    "path": "node-test/bindings/expected/imports.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nlet path : Ojs.t = Jsoo_runtime.Js.runtime_value \"node_path\"\n"
  },
  {
    "path": "node-test/bindings/expected/number.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\ntype t = Ojs.t\nlet rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\nand t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\nlet toString : t -> ?radix:int -> unit -> float =\n  fun (x6 : t) ?radix:(x3 : int option) () ->\n    Ojs.float_of_js\n      (let x7 = t_to_js x6 in\n       Ojs.call (Ojs.get_prop_ascii x7 \"toString\") \"apply\"\n         [|x7;((let x4 =\n                  Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                (match x3 with\n                 | Some x5 ->\n                     ignore (Ojs.call x4 \"push\" [|(Ojs.int_to_js x5)|])\n                 | None -> ());\n                x4))|])\nlet toFixed : t -> ?fractionDigits:int -> unit -> float =\n  fun (x11 : t) ?fractionDigits:(x8 : int option) () ->\n    Ojs.float_of_js\n      (let x12 = t_to_js x11 in\n       Ojs.call (Ojs.get_prop_ascii x12 \"toFixed\") \"apply\"\n         [|x12;((let x9 =\n                   Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                 (match x8 with\n                  | Some x10 ->\n                      ignore (Ojs.call x9 \"push\" [|(Ojs.int_to_js x10)|])\n                  | None -> ());\n                 x9))|])\nlet toExponential : t -> ?fractionDigits:int -> unit -> float =\n  fun (x16 : t) ?fractionDigits:(x13 : int option) () ->\n    Ojs.float_of_js\n      (let x17 = t_to_js x16 in\n       Ojs.call (Ojs.get_prop_ascii x17 \"toExponential\") \"apply\"\n         [|x17;((let x14 =\n                   Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                 (match x13 with\n                  | Some x15 ->\n                      ignore (Ojs.call x14 \"push\" [|(Ojs.int_to_js x15)|])\n                  | None -> ());\n                 x14))|])\nlet toPrecision : t -> ?precision:int -> unit -> float =\n  fun (x21 : t) ?precision:(x18 : int option) () ->\n    Ojs.float_of_js\n      (let x22 = t_to_js x21 in\n       Ojs.call (Ojs.get_prop_ascii x22 \"toPrecision\") \"apply\"\n         [|x22;((let x19 =\n                   Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                 (match x18 with\n                  | Some x20 ->\n                      ignore (Ojs.call x19 \"push\" [|(Ojs.int_to_js x20)|])\n                  | None -> ());\n                 x19))|])\nlet valueOf : t -> float =\n  fun (x23 : t) -> Ojs.float_of_js (Ojs.call (t_to_js x23) \"valueOf\" [||])\nmodule Scoped =\n  struct\n    let create : 'any -> t =\n      fun (x24 : 'any) ->\n        t_of_js\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Number\")\n             [|(Obj.magic x24)|])\n    let invoke : 'any -> float =\n      fun (x25 : 'any) ->\n        Ojs.float_of_js\n          (Ojs.apply (Ojs.get_prop_ascii Ojs.global \"Number\")\n             [|(Obj.magic x25)|])\n    let min_value : float =\n      Ojs.float_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Number\")\n           \"MIN_VALUE\")\n    let max_value : float =\n      Ojs.float_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Number\")\n           \"MAX_VALUE\")\n    let nan : float =\n      Ojs.float_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Number\") \"NaN\")\n    let negative_infinity : float =\n      Ojs.float_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Number\")\n           \"NEGATIVE_INFINITY\")\n    let positive_infinity : float =\n      Ojs.float_of_js\n        (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"Number\")\n           \"POSITIVE_INFINITY\")\n  end\nmodule Static =\n  struct\n    type number = t\n    let rec number_of_js : Ojs.t -> number = fun (x27 : Ojs.t) -> t_of_js x27\n    and number_to_js : number -> Ojs.t = fun (x26 : t) -> t_to_js x26\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x29 : Ojs.t) -> x29\n    and t_to_js : t -> Ojs.t = fun (x28 : Ojs.t) -> x28\n    let create : t -> 'any -> number =\n      fun (x31 : t) (x30 : 'any) ->\n        number_of_js (Ojs.new_obj (t_to_js x31) [|(Obj.magic x30)|])\n    let apply : t -> 'any -> float =\n      fun (x33 : t) (x32 : 'any) ->\n        Ojs.float_of_js (Ojs.apply (t_to_js x33) [|(Obj.magic x32)|])\n    let min_value : t -> float =\n      fun (x34 : t) ->\n        Ojs.float_of_js (Ojs.get_prop_ascii (t_to_js x34) \"MIN_VALUE\")\n    let max_value : t -> float =\n      fun (x35 : t) ->\n        Ojs.float_of_js (Ojs.get_prop_ascii (t_to_js x35) \"MAX_VALUE\")\n    let nan : t -> float =\n      fun (x36 : t) ->\n        Ojs.float_of_js (Ojs.get_prop_ascii (t_to_js x36) \"NaN\")\n    let negative_infinity : t -> float =\n      fun (x37 : t) ->\n        Ojs.float_of_js\n          (Ojs.get_prop_ascii (t_to_js x37) \"NEGATIVE_INFINITY\")\n    let positive_infinity : t -> float =\n      fun (x38 : t) ->\n        Ojs.float_of_js\n          (Ojs.get_prop_ascii (t_to_js x38) \"POSITIVE_INFINITY\")\n  end\nlet number : Static.t =\n  Static.t_of_js (Ojs.get_prop_ascii Ojs.global \"Number\")\n"
  },
  {
    "path": "node-test/bindings/expected/path.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nlet sep : string = Ojs.string_of_js (Ojs.get_prop_ascii Imports.path \"sep\")\nlet dirname : string -> string =\n  fun (x1 : string) ->\n    Ojs.string_of_js\n      (Ojs.call Imports.path \"dirname\" [|(Ojs.string_to_js x1)|])\nlet extname : string -> string =\n  fun (x2 : string) ->\n    Ojs.string_of_js\n      (Ojs.call Imports.path \"extname\" [|(Ojs.string_to_js x2)|])\nlet is_absolute : string -> bool =\n  fun (x3 : string) ->\n    Ojs.bool_of_js\n      (Ojs.call Imports.path \"isAbsolute\" [|(Ojs.string_to_js x3)|])\nlet join : string list -> string =\n  fun (x4 : string list) ->\n    Ojs.string_of_js\n      (let x7 = Imports.path in\n       Ojs.call (Ojs.get_prop_ascii x7 \"join\") \"apply\"\n         [|x7;((let x5 =\n                  Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                List.iter\n                  (fun (x6 : string) ->\n                     ignore (Ojs.call x5 \"push\" [|(Ojs.string_to_js x6)|]))\n                  x4;\n                x5))|])\nlet normalize : string -> string =\n  fun (x8 : string) ->\n    Ojs.string_of_js\n      (Ojs.call Imports.path \"normalize\" [|(Ojs.string_to_js x8)|])\ntype parse_result =\n  {\n  dir: string ;\n  root: string ;\n  base: string ;\n  name: string ;\n  ext: string }\nlet rec parse_result_of_js : Ojs.t -> parse_result =\n  fun (x10 : Ojs.t) ->\n    {\n      dir = (Ojs.string_of_js (Ojs.get_prop_ascii x10 \"dir\"));\n      root = (Ojs.string_of_js (Ojs.get_prop_ascii x10 \"root\"));\n      base = (Ojs.string_of_js (Ojs.get_prop_ascii x10 \"base\"));\n      name = (Ojs.string_of_js (Ojs.get_prop_ascii x10 \"name\"));\n      ext = (Ojs.string_of_js (Ojs.get_prop_ascii x10 \"ext\"))\n    }\nand parse_result_to_js : parse_result -> Ojs.t =\n  fun (x9 : parse_result) ->\n    Ojs.obj\n      [|(\"dir\", (Ojs.string_to_js x9.dir));(\"root\",\n                                             (Ojs.string_to_js x9.root));\n        (\"base\", (Ojs.string_to_js x9.base));(\"name\",\n                                               (Ojs.string_to_js x9.name));\n        (\"ext\", (Ojs.string_to_js x9.ext))|]\nlet parse : string -> parse_result =\n  fun (x11 : string) ->\n    parse_result_of_js\n      (Ojs.call Imports.path \"parse\" [|(Ojs.string_to_js x11)|])\n"
  },
  {
    "path": "node-test/bindings/expected/process.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nlet env : string Container.StringMap.t =\n  Container.StringMap.t_of_js Ojs.string_of_js\n    (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"process\") \"env\")\nlet version : string option =\n  Ojs.option_of_js Ojs.string_of_js\n    (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"process\") \"version\")\n"
  },
  {
    "path": "node-test/bindings/expected/promise.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule UntypedPromise =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let resolve : Ojs.t -> Ojs.t =\n      fun (x3 : Ojs.t) ->\n        Ojs.call (Ojs.get_prop_ascii Ojs.global \"Promise\") \"resolve\" [|x3|]\n    let reject : Ojs.t -> Ojs.t =\n      fun (x4 : Ojs.t) ->\n        Ojs.call (Ojs.get_prop_ascii Ojs.global \"Promise\") \"reject\" [|x4|]\n    let then_ :\n      Ojs.t -> success:(Ojs.t -> Ojs.t) -> error:(Ojs.t -> Ojs.t) -> Ojs.t =\n      fun (x9 : Ojs.t) ~success:(x5 : Ojs.t -> Ojs.t)\n        ~error:(x7 : Ojs.t -> Ojs.t) ->\n        Ojs.call x9 \"then\" [|(Ojs.fun_to_js 1 x5);(Ojs.fun_to_js 1 x7)|]\n    let all : Ojs.t list -> Ojs.t =\n      fun (x10 : Ojs.t list) ->\n        Ojs.call (Ojs.get_prop_ascii Ojs.global \"Promise\") \"all\"\n          [|(Ojs.list_to_js (fun (x11 : Ojs.t) -> x11) x10)|]\n    include\n      struct\n        type wrap = {\n          content: Ojs.t }\n        [@@@ocaml.warning \"-7-32-39\"]\n        let rec wrap_of_js : Ojs.t -> wrap =\n          fun (x13 : Ojs.t) ->\n            { content = (Ojs.get_prop_ascii x13 \"content\") }\n        and wrap_to_js : wrap -> Ojs.t =\n          fun (x12 : wrap) -> Ojs.obj [|(\"content\", (x12.content))|]\n      end\n    let is_promise o = (resolve o) == o\n    let wrap o = if is_promise o then wrap_to_js { content = o } else o\n    let unwrap o =\n      if Ojs.has_property o \"content\"\n      then Ojs.get_prop_ascii o \"content\"\n      else o\n    let return x = resolve (wrap x)\n    let fail err = reject (wrap err)\n    let bind ?(error= fail) p f =\n      then_ p ~success:(fun x -> f (unwrap x))\n        ~error:(fun x -> error (unwrap x))\n  end\ntype 'a t = UntypedPromise.t\ntype error = Ojs.t\nlet fail error = UntypedPromise.fail error\nlet return x = UntypedPromise.return (Obj.magic x)\nlet bind ?error p f = UntypedPromise.bind ?error p (fun x -> f (Obj.magic x))\nlet prod p1 p2 =\n  bind (UntypedPromise.all [p1; p2])\n    (fun ojs ->\n       match Ojs.list_of_js Ojs.t_of_js ojs with\n       | x1::x2::[] -> return (x1, x2)\n       | _ -> assert false)\nlet map f p = bind p (fun x -> return (f x))\nlet t_to_js f p = UntypedPromise.t_to_js (map f p)\nlet t_of_js f p = map f (UntypedPromise.t_of_js p)\nlet (let+) p f = map f p\nlet (and+) = prod\nlet ( let* ) p f = bind p f\nlet ( and* ) = prod\nlet catch p error = bind p ~error return\n"
  },
  {
    "path": "node-test/bindings/fs.mli",
    "content": "[@@@js.scope \"@node_fs.promises\"]\n\nmodule Dirent : sig\n  type t = Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n\n  val name: t -> string [@@js.get]\n  val is_file: t -> bool [@@js.call]\n  val is_directory: t -> bool [@@js.call]\nend\n\nmodule Dir : sig\n  type t = Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n\n\n  val path: t -> string [@@js.get]\n  val close: t -> unit Promise.t [@@js.call]\n  val read:t -> Dirent.t option Promise.t [@@js.call]\nend\n\nmodule FileHandle : sig\n  type t = Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n\n  type read = {\n    bytes_read: int;\n    buffer: Buffer.t;\n  }\n\n  val append_file: t -> Buffer.t -> unit Promise.t [@@js.call]\n  val read: t -> Buffer.t -> int -> int -> int -> read Promise.t [@@js.call]\n  val chmod: t -> int -> unit Promise.t [@@js.call]\n  val chmown: t -> uid:int -> gid:int -> unit Promise.t [@@js.call]\n  val close: t -> unit Promise.t [@@js.call]\n  val datasync: t -> unit Promise.t [@@js.call]\n  val fd: t -> int [@@js.get]\nend\n\nval readdir: string -> string list Promise.t [@@js.global]\nval open_: string -> flag:string -> FileHandle.t Promise.t [@@js.global]\nval rmdir: string -> unit Promise.t [@@js.global]\nval rename: string -> string -> unit Promise.t [@@js.global]\nval unlink: string -> unit Promise.t [@@js.global]\n"
  },
  {
    "path": "node-test/bindings/global.mli",
    "content": "type timeout_id\nval timeout_id_to_js: timeout_id -> Ojs.t\nval timeout_id_of_js: Ojs.t -> timeout_id\n\ntype interval_id\nval interval_id_to_js: interval_id -> Ojs.t\nval interval_id_of_js: Ojs.t -> interval_id\n\n\nval set_interval: (unit -> unit) -> int -> interval_id [@@js.global]\nval set_timeout: (unit -> unit) -> int -> timeout_id [@@js.global]\nval clear_timeout: timeout_id -> unit [@@js.global]\nval clear_interval: interval_id -> unit [@@js.global]\n"
  },
  {
    "path": "node-test/bindings/imports.js",
    "content": "//Provides: node_path\nvar node_path = require('path');\n\n//Provides: node_fs\nvar node_fs = require('fs');\n"
  },
  {
    "path": "node-test/bindings/imports.mli",
    "content": "val path: Ojs.t [@@js.global \"@node_path\"]\n"
  },
  {
    "path": "node-test/bindings/imports.wat",
    "content": "\n(global (export \"_node_path\") (import \"js\" \"node_path\") anyref)\n(global (export \"_node_fs\") (import \"js\" \"node_fs\") anyref)\n"
  },
  {
    "path": "node-test/bindings/number.mli",
    "content": "type t = private Ojs.t\n\nval toString: t -> ?radix:int -> unit -> float [@@js.call]\nval toFixed: t -> ?fractionDigits:int -> unit -> float [@@js.call]\nval toExponential: t -> ?fractionDigits:int -> unit -> float [@@js.call]\nval toPrecision: t -> ?precision:int -> unit -> float [@@js.call]\nval valueOf: t -> float [@@js.call]\n\n(* scoped *)\n\nmodule [@js.scope \"Number\"] Scoped : sig\n  val create: 'any -> t [@@js.create]\n  val invoke: 'any -> float [@@js.invoke]\n\n  val min_value: float [@@js.global \"MIN_VALUE\"]\n  val max_value: float [@@js.global \"MAX_VALUE\"]\n  val nan: float [@@js.global \"NaN\"]\n  val negative_infinity: float [@@js.global \"NEGATIVE_INFINITY\"]\n  val positive_infinity: float [@@js.global \"POSITIVE_INFINITY\"]\nend\n\n(* non-scoped *)\n\nmodule Static : sig\n  type number = t\n  type t = private Ojs.t\n\n  val create: t -> 'any -> number [@@js.apply_newable]\n  val apply: t -> 'any -> float [@@js.apply]\n\n  val min_value: t -> float [@@js.get \"MIN_VALUE\"]\n  val max_value: t -> float [@@js.get \"MAX_VALUE\"]\n  val nan: t -> float [@@js.get \"NaN\"]\n  val negative_infinity: t -> float [@@js.get \"NEGATIVE_INFINITY\"]\n  val positive_infinity: t -> float [@@js.get \"POSITIVE_INFINITY\"]\nend\nval number: Static.t [@@js.global \"Number\"]\n"
  },
  {
    "path": "node-test/bindings/path.mli",
    "content": "[@@@js.scope Imports.path]\n\nval sep: string [@@js.global]\nval dirname: string -> string [@@js.global]\nval extname: string -> string [@@js.global]\nval is_absolute: string -> bool [@@js.global]\nval join: (string list [@js.variadic]) -> string [@@js.global]\nval normalize: string -> string [@@js.global]\n\ntype parse_result =\n  {\n    dir: string;\n    root: string;\n    base: string;\n    name: string;\n    ext: string\n  }\n\nval parse: string -> parse_result [@@js.global]\n"
  },
  {
    "path": "node-test/bindings/process.mli",
    "content": "[@@@js.scope \"process\"]\n\nval env : string Container.StringMap.t [@@js.global]\nval version: string option [@@js.global]"
  },
  {
    "path": "node-test/bindings/promise.mli",
    "content": "module UntypedPromise : sig\n\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  [@@@js.stop]\n  val return: Ojs.t -> t\n  val fail: Ojs.t -> t\n  val bind: ?error:(Ojs.t -> t) -> t -> (Ojs.t -> t) -> t\n  val all: Ojs.t list -> t\n  [@@@js.start]\n\n  [@@@js.implem\n    val resolve: Ojs.t -> Ojs.t [@@js.global \"Promise.resolve\"]\n    val reject: Ojs.t -> Ojs.t [@@js.global \"Promise.reject\"]\n    val then_: Ojs.t -> success:(Ojs.t -> Ojs.t) -> error:(Ojs.t -> Ojs.t) -> Ojs.t [@@js.call \"then\"]\n    val all: Ojs.t list -> Ojs.t [@@js.global \"Promise.all\"]\n\n    type wrap = { content: Ojs.t }[@@js]\n\n    let is_promise o =\n      resolve o == o\n\n    let wrap o =\n      if is_promise o then\n        wrap_to_js { content = o }\n      else o\n\n    let unwrap o =\n      if Ojs.has_property o \"content\" then\n        Ojs.get_prop_ascii o \"content\"\n      else\n        o\n\n    let return x = resolve (wrap x)\n    let fail err = reject (wrap err)\n    let bind ?(error = fail) p f =\n      then_ p ~success:(fun x -> f (unwrap x))\n        ~error:(fun x -> error (unwrap x))\n\n  ]\nend\n\n[@@@js.stop]\ntype 'a t\nval t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\nval t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n\ntype error = Ojs.t\n\nval fail: error -> 'a t\nval return: 'a -> 'a t\nval bind: ?error:(error -> 'b t) -> 'a t -> ('a -> 'b t) -> 'b t\nval map: ('a -> 'b) -> 'a t -> 'b t\nval prod: 'a t -> 'b t -> ('a * 'b) t\n\nval ( let+ ): 'a t -> ('a -> 'b) -> 'b t\nval ( and+ ): 'a t -> 'b t -> ('a * 'b) t\nval ( let* ): 'a t -> ('a -> 'b t) -> 'b t\nval ( and* ): 'a t -> 'b t -> ('a * 'b) t\n\nval catch: 'a t -> (error -> 'a t) -> 'a t\n\n[@@@js.start]\n[@@@js.implem\n  type 'a t = UntypedPromise.t\n  type error = Ojs.t\n  let fail error = UntypedPromise.fail  error\n  let return x = UntypedPromise.return (Obj.magic x)\n  let bind ?error p f =\n    UntypedPromise.bind ?error p\n      (fun x -> f (Obj.magic x))\n\n  let prod p1 p2 =\n    bind (UntypedPromise.all [p1; p2])\n      (fun ojs ->\n         match Ojs.list_of_js Ojs.t_of_js ojs with\n         | [x1; x2] -> return (x1, x2)\n         | _ -> assert false\n      )\n  let map f p = bind p (fun x -> return (f x))\n  let t_to_js f p = UntypedPromise.t_to_js (map f p)\n  let t_of_js f p = map f (UntypedPromise.t_of_js p)\n\n  let (let+) p f = map f p\n  let (and+) = prod\n  let (let*) p f = bind p f\n  let (and*) = prod\n\n  let catch p error = bind p ~error return\n\n]\n"
  },
  {
    "path": "node-test/runtime_primitives/bindings.mli",
    "content": "module [@js.scope \"@node_fs\"] Fs : sig\n  val write_file_sync : string -> string -> unit [@@js.global \"writeFileSync\"]\n  val read_file_sync : string -> encoding:string -> string [@@js.global \"readFileSync\"]\n  val readdir_sync : string -> string array [@@js.global \"readdirSync\"]\n  val append_file_sync : string -> string -> unit [@@js.global \"appendFileSync\"]\nend\n\nmodule [@js.scope \"@node_path\"] Path : sig\n  val separator: string [@@js.global \"sep\"]\n  val join : (string list [@js.variadic]) -> string [@@js.global \"join\"]\nend\n\nval node_version : string [@@js.global \"@node_version\"]\nval log : string -> unit [@@js.global \"@node_console\"]\n"
  },
  {
    "path": "node-test/runtime_primitives/dune",
    "content": "(rule\n (targets bindings.ml)\n (deps bindings.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(executable\n (name example)\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes js wasm)\n (js_of_ocaml\n  (javascript_files imports.js))\n (wasm_of_ocaml\n  (javascript_files imports.js imports.wat)))\n\n(rule\n (alias runtest)\n (enabled_if %{bin-available:node})\n (action\n  (run node %{dep:./example.bc.js})))\n\n(rule\n (alias runtest-wasm)\n (enabled_if %{bin-available:node})\n (action\n  (run node %{dep:./example.bc.wasm.js})))\n"
  },
  {
    "path": "node-test/runtime_primitives/example.ml",
    "content": "open Bindings\n\nlet initial_content = \"Hello, Node.js!\"\nlet appended_line = \"\\nAppending a new line.\"\nlet encoding = \"utf-8\"\nlet filename = \"example.txt\"\n\nlet run () =\n  let file = Path.join [\".\"; filename] in\n\n  Fs.write_file_sync file initial_content;\n\n  let content = Fs.read_file_sync file ~encoding in\n  if content <> initial_content then\n    failwith \"Unexpected initial content\";\n  log (\"File content: \" ^ content);\n\n  let files = Fs.readdir_sync \".\" |> Array.to_list in\n  if not (List.mem filename files) then\n    failwith \"example.txt missing from directory listing\";\n  log (\"Files in current directory: \" ^ String.concat \", \" files);\n\n  Fs.append_file_sync file appended_line;\n\n  let updated = Fs.read_file_sync file ~encoding in\n  if updated <> initial_content ^ appended_line then\n    failwith \"Append failed\";\n  log (\"Updated content: \" ^ updated);\n  log (\"Path separator reported by Node: \" ^ Path.separator);\n  log (\"Node.js version: \" ^ node_version)\n\n\nlet () = run ()\n"
  },
  {
    "path": "node-test/runtime_primitives/imports.js",
    "content": "'use strict';\n\n//Provides: node_path\nvar node_path = require('path');\n\n//Provides: node_fs\nvar node_fs = require('fs');\n\n//Provides: node_version\nvar node_version = require('process').version;\n\n//Provides: node_console\nvar node_console = console.log;\n"
  },
  {
    "path": "node-test/runtime_primitives/imports.wat",
    "content": "(global (export \"_node_path\") (import \"js\" \"node_path\") anyref)\n(global (export \"_node_fs\") (import \"js\" \"node_fs\") anyref)\n(global (export \"_node_version\") (import \"js\" \"node_version\") anyref)\n(global (export \"_node_console\") (import \"js\" \"node_console\") anyref)\n"
  },
  {
    "path": "node-test/test1/dune",
    "content": "(executable\n (name test)\n (libraries ojs node)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes js wasm)\n (js_of_ocaml\n  (javascript_files recursive.js))\n (wasm_of_ocaml\n  (javascript_files recursive.js)))\n\n(rule\n (targets recursive.ml)\n (deps recursive.mli)\n (action\n  (run gen_js_api %{deps})))\n\n(rule\n (alias runtest)\n (enabled_if %{bin-available:node})\n (action\n  (run node %{dep:./test.bc.js})))\n\n(rule\n (alias runtest-wasm)\n (enabled_if %{bin-available:node})\n (action\n  (run node %{dep:./test.bc.wasm.js})))\n"
  },
  {
    "path": "node-test/test1/recursive.js",
    "content": "\nvar Foo = /*#__PURE__*/function () {\n  \"use strict\";\n\n  function Foo(name) {\n    this.name = name;\n  }\n\n  var _proto = Foo.prototype;\n\n  _proto.describe = function describe() {\n    return \"Foo:\".concat(this.name);\n  };\n\n  _proto.toBar = function toBar() {\n    return new Bar(this.name);\n  };\n\n  return Foo;\n}();\n\n\nvar Bar = /*#__PURE__*/function () {\n  \"use strict\";\n\n  function Bar(name) {\n    this.name = name;\n  }\n\n  var _proto2 = Bar.prototype;\n\n  _proto2.describe = function describe() {\n    return \"Bar:\".concat(this.name);\n  };\n\n  _proto2.toFoo = function toFoo() {\n    return new Foo(this.name);\n  };\n\n  return Bar;\n}();\n\nglobalThis.Foo = Foo\nglobalThis.Bar = Bar\n"
  },
  {
    "path": "node-test/test1/recursive.mli",
    "content": "module [@js.scope \"Foo\"] rec Foo : sig\n  type t = private Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n  val create: string -> t [@@js.create]\n  val describe: t -> string [@@js.call \"describe\"]\n  val to_bar: t -> Bar.t [@@js.call \"toBar\"]\nend\n\nand [@js.scope \"Bar\"] Bar : sig\n  type t = private Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n  val create: string -> t [@@js.create]\n  val describe: t -> string [@@js.call \"describe\"]\n  val to_foo: t -> Foo.t [@@js.call \"toFoo\"]\nend\n"
  },
  {
    "path": "node-test/test1/test.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n[@@@ocaml.warning \"-32-34\"]\n\nopen Node\n\nlet check_node_version version =\n  let major_version = function\n    | Some s when String.length s > 0 && s.[0] = 'v' ->\n        begin match\n          String.sub s 1 (String.length s - 1)\n          |> String.split_on_char '.'\n        with\n        | [] -> None\n        | hd :: _ -> int_of_string_opt hd\n        end\n    | _ -> None\n  in\n  if Option.value ~default:(-1) (major_version Process.version) < version then\n    begin\n      Printf.eprintf \"[WARNING] Ignoring test: it requires Node > %d; please upgrade (current version %s)\" version\n        (Option.value ~default:\"???\" Process.version);\n      exit 0\n    end\n\nlet () =\n  check_node_version 18\n\n(** Buffer **)\n\nlet caml_from_set s =\n  let len = String.length s in\n  let buf = Buffer.alloc len in\n  String.iteri (fun k x ->\n      Buffer.set buf k (Char.code x)\n    ) s;\n  buf\n\nlet caml_from_write s =\n  let len = String.length s in\n  let buf = Buffer.alloc len in\n  let written = Buffer.write buf s in\n  assert (written = len);\n  buf\n\nlet assert_equal_buffer b1 b2 =\n  let len1 = Buffer.length b1 in\n  let len2 = Buffer.length b2 in\n  assert (len1 = len2);\n  for k = 0 to len1 -1 do\n    assert (Buffer.get b1 k = Buffer.get b2 k)\n  done\n\nlet copy src =\n  let len = Buffer.length src in\n  let dst = Buffer.alloc len in\n  let written =\n    Buffer.copy src ~dst ~start:0 ~dst_start:0 ~dst_end:len\n  in\n  assert (len = written);\n  dst\n\nlet () =\n  let test = \"test\" in\n  let native = Buffer.from test in\n  let from_set = caml_from_set test in\n  let from_write = caml_from_write test in\n  let from_copy = copy native in\n  assert_equal_buffer native from_set;\n  assert_equal_buffer native from_write;\n  assert_equal_buffer native from_copy\n\n(** Process **)\n\nlet () =\n  Container.StringMap.iter\n    (fun key value ->\n       assert (Sys.getenv key = value)\n    )\n    Process.env\n\nlet uncaught_handler p =\n  let open Promise in\n  catch p (fun error ->\n      Printf.eprintf \"Uncaught exception: %s\\n\" (Printexc.to_string (Obj.magic error));\n      exit 1\n    )\n\n(** FileSystem **)\n\nlet root : unit Promise.t =\n  let open Promise in\n  uncaught_handler\n    begin\n      let* contents = Fs.readdir \".\"\n      and+ contents' = Fs.readdir \".\" in\n      List.iter2 (fun x y ->\n          assert (x = y)) contents contents';\n      return ()\n    end\n\n(*** Index signature **)\n\ninclude [%js:\n  module ArrayLike (K : Ojs.T) : sig\n    type t = private Ojs.t\n    val t_to_js: t -> Ojs.t\n    val t_of_js: Ojs.t -> t\n\n    val create: unit -> t [@@js.builder]\n    val get: t -> int -> K.t option [@@js.index_get]\n    val set: t -> int -> K.t -> unit [@@js.index_set]\n  end\n\n  module MapLike (K : Ojs.T) : sig\n    type t = private Ojs.t\n    val t_to_js: t -> Ojs.t\n    val t_of_js: Ojs.t -> t\n\n    val create: unit -> t [@@js.builder]\n    val get: t -> string -> K.t option [@@js.index_get]\n    val set: t -> string -> K.t -> unit [@@js.index_set]\n  end\n\n  module Symbol : sig\n    type t = private Ojs.t\n    val t_to_js: t -> Ojs.t\n    val t_of_js: Ojs.t -> t\n\n    val fresh: unit -> t [@@js.global \"Symbol\"]\n  end\n\n  module SymbolMap (K : Ojs.T) : sig\n    type t = private Ojs.t\n    val t_to_js: t -> Ojs.t\n    val t_of_js: Ojs.t -> t\n\n    val create: unit -> t [@@js.builder]\n    val get: t -> Symbol.t -> K.t option [@@js.index_get]\n    val set: t -> Symbol.t -> K.t -> unit [@@js.index_set]\n  end\n\n]\n\nlet () =\n  let module M = MapLike([%js: type t = string val t_to_js: t -> Ojs.t val t_of_js: Ojs.t -> t]) in\n  let map_str = M.create () in\n  M.set map_str \"foo\" \"bar\";\n  assert (M.get map_str \"foo\" = Some \"bar\");\n  M.set map_str \"baz\" \"boo\";\n  assert (M.get map_str \"baz\" = Some \"boo\");\n\n  let module A = ArrayLike([%js: type t = int val t_to_js: t -> Ojs.t val t_of_js: Ojs.t -> t]) in\n  let map_int = A.create () in\n  let len = 10 in\n  for k = 0 to len - 1 do\n    A.set map_int k k;\n    assert (A.get map_int k = Some k);\n    A.set map_int k (k * k);\n    assert (A.get map_int k = Some (k * k));\n  done;\n\n  let module M = SymbolMap([%js: type t = string val t_to_js: t -> Ojs.t val t_of_js: Ojs.t -> t]) in\n  let a = Symbol.fresh () in\n  let b = Symbol.fresh () in\n  let map_str = M.create () in\n  M.set map_str a \"bar\";\n  assert (M.get map_str a = Some \"bar\");\n  M.set map_str b \"boo\";\n  assert (M.get map_str b = Some \"boo\")\n\n\n(*** Function signature **)\n\ninclude [%js:\n  module Concat : sig\n    type t = private Ojs.t\n\n    val t_to_js: t -> Ojs.t\n    val t_of_js: Ojs.t -> t\n\n    val apply: t -> (string list [@js.variadic]) -> string [@@js.apply]\n  end\n\n  module [@js.scope Imports.path] Path2 : sig\n    val join: Concat.t [@@js.global \"join\"]\n  end\n]\n\nlet () =\n  let args = [\"foo\"; \"bar\"; \"baz\"] in\n  let res1 = Path.join args in\n  let res2 = Concat.apply Path2.join args in\n  assert (res1 = res2);\n  ()\n\n(*** Newable function *)\n\ninclude [%js:\n  module Date: sig\n    type t = private Ojs.t\n    val getUTCFullYear: t -> float [@@js.call \"getUTCFullYear\"]\n    val getUTCMonth: t -> float [@@js.call \"getUTCMonth\"]\n    val getUTCDate: t -> float [@@js.call \"getUTCDate\"]\n  end\n\n  module DateConstructor: sig\n    type t = private Ojs.t\n    val utc:\n      t ->\n      year:int -> month:int -> ?date:int ->\n      ?hours:int -> ?minutes:int -> ?seconds:int ->\n      ?ms:int -> unit -> float [@@js.call \"UTC\"]\n    val new_:\n      t -> float -> Date.t [@@js.apply_newable]\n  end\n\n  val date: DateConstructor.t [@@js.global \"Date\"]\n]\n\nlet () =\n  let d =\n    DateConstructor.new_ date\n      (DateConstructor.utc date ~year:1999 ~month:11 ~date:31 ())\n  in\n  assert (int_of_float (Date.getUTCFullYear d) == 1999);\n  assert (int_of_float (Date.getUTCMonth d) == 11);\n  assert (int_of_float (Date.getUTCDate d) == 31);\n  ()\n\n(** Arrays **)\nlet () =\n  let open Arrays.StringArray in\n  let a = create () in\n  for k = 0 to 10 do\n    push a (string_of_int k);\n  done;\n  let s = join a \",\" in\n  List.iteri (fun k x ->\n      assert (string_of_int k = x)\n    ) (String.split_on_char ',' s)\n\n(** Invoking a global object **)\n(** https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/Number **)\nlet () =\n  let check (a: Number.t) (b: float) =\n    assert (Ojs.instance_of (a :> Ojs.t) ~constr:(Number.number :> Ojs.t));\n    assert (not (Ojs.instance_of (Ojs.float_to_js b) ~constr:(Number.number :> Ojs.t)));\n    assert (Number.valueOf a = b);\n    ()\n  in\n  let s = Ojs.string_to_js \"123\" in\n  check (Number.Scoped.create s) (Number.Scoped.invoke s);\n  check (Number.Static.create Number.number s) (Number.Static.apply Number.number s);\n  assert (Number.Scoped.max_value = Number.Static.max_value Number.number);\n  ()\n\n(** Using recursive modules **)\nlet () =\n  let open Recursive in\n  let fooA = Foo.create \"A\" in\n  assert (Foo.describe fooA = \"Foo:A\");\n  let barA = Foo.to_bar fooA in\n  assert (Bar.describe barA = \"Bar:A\");\n  let fooA' = Bar.to_foo barA in\n  assert (Foo.describe fooA' = \"Foo:A\");\n  ()\n\n(** Using first class modules **)\ninclude [%js:\n  val to_string: (module[@js] Ojs.T with type t = 'a) -> 'a -> string [@@js.call \"toString\"]\n]\nlet () =\n  let check (type a) (module A : Ojs.T with type t = a) (value: a) (expected: string) =\n    let str = to_string (module A) value in\n    assert (str = expected)\n  in\n  check (module Ojs.Int) 42 \"42\";\n  check (module Ojs.Float) 4.2 \"4.2\";\n  check (module Ojs.String) \"hello\" \"hello\";\n  check (module Ojs.List(Ojs.Int)) [4;2] \"4,2\";\n  check (module Ojs.List(Ojs.String)) [\"hello\"; \"world\"] \"hello,world\";\n  ()\nlet () =\n  let open Arrays.JsArray2 in\n  let a = create () in\n  for k = 0 to 10 do\n    push (module Ojs.String) a (string_of_int k);\n  done;\n\n  let sa = join a \",\" in\n  List.iteri (fun k x ->\n      assert (string_of_int k = x)\n    ) (String.split_on_char ',' sa);\n\n  let b =\n    let orig = List.init 11 string_of_int in\n    create' (module Ojs.String) orig\n  in\n  let sb = join b \",\" in\n  assert (sa = sb);\n\n  assert (get (module Ojs.String) a 0 = Some \"0\");\n  set (module Ojs.String) a 1 \"foo\";\n  assert (get (module Ojs.String) a 1 = Some \"foo\");\n  ()\n"
  },
  {
    "path": "ojs.opam",
    "content": "# This file is generated by dune, edit dune-project instead\nopam-version: \"2.0\"\nversion: \"1.1.7\"\nsynopsis: \"Runtime Library for gen_js_api generated libraries\"\ndescription: \"To be used in conjunction with gen_js_api\"\nmaintainer: [\"Alain Frisch <alain.frisch@lexifi.com>\"]\nauthors: [\n  \"Alain Frisch <alain.frisch@lexifi.com>\"\n  \"Sebastien Briais <sebastien.briais@lexifi.com>\"\n]\nlicense: \"MIT\"\nhomepage: \"https://github.com/LexiFi/gen_js_api\"\nbug-reports: \"https://github.com/LexiFi/gen_js_api/issues\"\ndepends: [\n  \"dune\" {>= \"3.17\"}\n  \"ocaml\" {>= \"4.13\"}\n  \"js_of_ocaml-compiler\" {>= \"6.3.0\"}\n  \"odoc\" {with-doc}\n]\ndev-repo: \"git+https://github.com/LexiFi/gen_js_api.git\"\nbuild: [\n  [\"dune\" \"subst\"] {dev}\n  [\"dune\" \"build\" \"-p\" name \"-j\" jobs \"@install\" \"@doc\" {with-doc}]\n]\n"
  },
  {
    "path": "ojs.opam.template",
    "content": "build: [\n  [\"dune\" \"subst\"] {dev}\n  [\"dune\" \"build\" \"-p\" name \"-j\" jobs \"@install\" \"@doc\" {with-doc}]\n]\n"
  },
  {
    "path": "ppx-driver/dune",
    "content": "(library\n (name gen_js_api_ppx_driver)\n (public_name gen_js_api.ppx)\n (synopsis \"Syntactic support for gen_js_api\")\n (libraries gen_js_api.lib ppxlib.ast ppxlib)\n (kind ppx_rewriter)\n (ppx_runtime_libraries ojs)\n (preprocess no_preprocessing))\n"
  },
  {
    "path": "ppx-driver/gen_js_api_ppx_driver.ml",
    "content": "let check_attributes_with_ppxlib = false\nlet check_locations_with_ppxlib = false\n\nlet () =\n  if check_attributes_with_ppxlib\n  then (\n    Ppxlib.Driver.enable_checks ();\n    Gen_js_api_ppx.check_attribute := false\n  );\n  if check_locations_with_ppxlib\n  then (\n    Ppxlib.Driver.enable_location_check ()\n  );\n  let mapper_for_sig =\n    Gen_js_api_ppx.mark_attributes_as_used\n  in\n  let mapper_for_str =\n    Gen_js_api_ppx.mark_attributes_as_used\n  in\n  let module_expr_ext =\n    let rewriter ~loc ~path:_ si =\n      Gen_js_api_ppx.module_expr_rewriter ~loc ~attrs:[] si\n    in\n    Ppxlib.Extension.declare \"js\"\n      Ppxlib.Extension.Context.Module_expr\n      Ppxlib.(Ast_pattern.psig Ast_pattern.__)\n      rewriter\n    |> Ppxlib.Context_free.Rule.extension\n  in\n  let ext_to =\n    let rewriter ~loc ~path:_ core_type =\n      Gen_js_api_ppx.js_to_rewriter ~loc core_type\n    in\n    Ppxlib.Extension.declare \"js.to\"\n      Ppxlib.Extension.Context.Expression\n      Ppxlib.(Ast_pattern.ptyp Ast_pattern.__)\n      rewriter\n    |> Ppxlib.Context_free.Rule.extension\n  in\n  let ext_of =\n    let rewriter ~loc ~path:_ core_type =\n      Gen_js_api_ppx.js_of_rewriter ~loc core_type\n    in\n    Ppxlib.Extension.declare \"js.of\"\n      Ppxlib.Extension.Context.Expression\n      Ppxlib.(Ast_pattern.ptyp Ast_pattern.__)\n      rewriter\n    |> Ppxlib.Context_free.Rule.extension\n  in\n  let attr_typ =\n    let rewriter ~ctxt (rec_flag : Ppxlib.Asttypes.rec_flag) tdl _ =\n      Gen_js_api_ppx.type_decl_rewriter\n        ~loc:(Ppxlib.Expansion_context.Deriver.derived_item_loc ctxt)\n        rec_flag tdl\n    in\n    Ppxlib.Context_free.Rule.attr_str_type_decl\n      (Ppxlib.Attribute.declare \"js\"\n         Ppxlib.Attribute.Context.type_declaration\n         Ppxlib.(Ast_pattern.pstr Ast_pattern.nil) ())\n      rewriter\n  in\n  Ppxlib.Driver.register_transformation\n    \"gen_js_api\"\n    ~rules:[module_expr_ext; ext_of; ext_to; attr_typ ]\n    ~impl:(mapper_for_str # structure)\n    ~intf:(mapper_for_sig # signature)\n"
  },
  {
    "path": "ppx-lib/dune",
    "content": "(library\n (name gen_js_api_ppx)\n (public_name gen_js_api.lib)\n (libraries compiler-libs.common ppxlib)\n (ppx_runtime_libraries ojs)\n (preprocess no_preprocessing))\n"
  },
  {
    "path": "ppx-lib/gen_js_api_ppx.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\nopen Ppxlib\n\nopen Asttypes\nopen Parsetree\nopen Longident\nopen Ast_helper\nopen Location\n\nlet mkloc txt loc =\n  { txt; loc }\n\nlet mknoloc txt =\n  mkloc txt !Ast_helper.default_loc\n\n(** Errors *)\n\ntype error =\n  | Expression_expected\n  | Identifier_expected\n  | Structure_expected\n  | Invalid_expression\n  | Multiple_binding_declarations\n  | Binding_type_mismatch\n  | Cannot_parse_type\n  | Cannot_parse_sigitem\n  | Cannot_parse_classdecl\n  | Cannot_parse_classfield\n  | Implicit_name of string\n  | Not_supported_here of string\n  | Record_expected of string\n  | Record_constructor_in_union\n  | Unknown_union_method\n  | Non_constant_constructor_in_enum\n  | Multiple_default_case\n  | Duplicate_case_value of location * location\n  | Invalid_variadic_type_arg\n  | No_input\n  | Multiple_inputs\n  | Unlabelled_argument_in_builder\n  | Spurious_attribute of label\n  | Sum_kind_args\n  | Union_without_discriminator\n  | Contravariant_type_parameter of string\n  | Cannot_set_runtime_value of string\n\nexception Error of Location.t * error\n\nlet is_ascii s =\n  let exception Break in\n  try\n    String.iter (fun c -> if Char.code c > 127 then raise Break) s;\n    true\n  with Break -> false\n\nlet check_attribute = ref true\nlet used_attributes_tbl = Hashtbl.create 16\n\n(* [merlin_hide] tells merlin to not look at a node, or at any of its\n   descendants.  *)\nlet merlin_hide =\n  { attr_name = { txt = \"merlin.hide\"; loc = Location.none }\n  ; attr_payload = PStr []\n  ; attr_loc = Location.none\n  }\n\nlet register_loc attr =\n  Ppxlib.Attribute.mark_as_handled_manually attr;\n  Hashtbl.replace used_attributes_tbl attr.attr_name.loc ()\n\nlet is_registered_loc loc = Hashtbl.mem used_attributes_tbl loc\n\nlet error loc err = raise (Error (loc, err))\n\nlet filter_attr_name key attr =\n  if attr.attr_name.txt = key then begin\n    register_loc attr;\n    true\n  end else false\n\nlet filter_extension key name = name.txt = key\n\nlet has_attribute key attrs = List.exists (filter_attr_name key) attrs\n\nlet get_attribute key attrs =\n  match List.find (filter_attr_name key) attrs with\n  | exception Not_found -> None\n  | attr -> Some attr\n\nlet unoption = function\n  | Some x -> x\n  | None -> assert false\n\nlet expr_of_stritem = function\n  | {pstr_desc=Pstr_eval (e, _); _} -> e\n  | p -> error p.pstr_loc Expression_expected\n\nlet expr_of_payload {attr_loc; attr_payload; _} =\n  match attr_payload with\n  | PStr [x] -> expr_of_stritem x\n  | _ -> error attr_loc Expression_expected\n\nlet str_of_payload {attr_loc; attr_payload; _} =\n  match attr_payload with\n  | PStr x -> x\n  | _ -> error attr_loc Structure_expected\n\nlet id_of_expr = function\n  | {pexp_desc=Pexp_constant (Pconst_string (s, _, _)); _} -> s\n  | e -> error e.pexp_loc Identifier_expected\n\nlet get_expr_attribute key attrs =\n  match get_attribute key attrs with\n  | None -> None\n  | Some payload -> Some (expr_of_payload payload)\n\nlet get_string_attribute key attrs =\n  match get_attribute key attrs with\n  | None -> None\n  | Some payload -> Some (id_of_expr (expr_of_payload payload))\n\nlet get_string_attribute_default key default attrs =\n  match get_attribute key attrs with\n  | None -> default\n  | Some payload -> payload.attr_loc, id_of_expr (expr_of_payload payload)\n\nlet print_error ppf = function\n  | Expression_expected ->\n      Format.fprintf ppf \"Expression expected\"\n  | Structure_expected ->\n      Format.fprintf ppf \"Structure expected\"\n  | Identifier_expected ->\n      Format.fprintf ppf \"String literal expected\"\n  | Invalid_expression ->\n      Format.fprintf ppf \"Invalid expression\"\n  | Multiple_binding_declarations ->\n      Format.fprintf ppf \"Multiple binding declarations\"\n  | Binding_type_mismatch ->\n      Format.fprintf ppf \"Binding declaration and type are not compatible\"\n  | Cannot_parse_type ->\n      Format.fprintf ppf \"Cannot parse type\"\n  | Cannot_parse_sigitem ->\n      Format.fprintf ppf \"Cannot parse signature item\"\n  | Cannot_parse_classdecl ->\n      Format.fprintf ppf \"Cannot parse class declaration\"\n  | Cannot_parse_classfield ->\n      Format.fprintf ppf \"Cannot parse class field\"\n  | Implicit_name prefix ->\n      Format.fprintf ppf \"Implicit name must start with '%s' and cannot be empty\" prefix\n  | Not_supported_here msg ->\n      Format.fprintf ppf \"%s not supported in this context\" msg\n  | Non_constant_constructor_in_enum ->\n      Format.fprintf ppf \"Constructors in enums cannot take arguments\"\n  | Multiple_default_case ->\n      Format.fprintf ppf \"At most one default constructor is supported in variants\"\n  | Duplicate_case_value (loc1, loc2)  ->\n      let line1, line2 = loc1.loc_start.pos_lnum, loc2.loc_start.pos_lnum in\n      let line1, line2 = if line1 < line2 then line1, line2 else line2, line1 in\n      Format.fprintf ppf \"This case value is used twice at lines %d and %d\" line1 line2\n  | Invalid_variadic_type_arg ->\n      Format.fprintf ppf \"A variadic function argument must be of type list\"\n  | No_input ->\n      Format.fprintf ppf \"An input file must be provided\"\n  | Multiple_inputs ->\n      Format.fprintf ppf \"A single input file must be provided\"\n  | Unlabelled_argument_in_builder ->\n      Format.fprintf ppf \"Arguments of builder must be named\"\n  | Spurious_attribute label ->\n      Format.fprintf ppf \"Spurious %s attribute\" label\n  | Sum_kind_args ->\n      Format.fprintf ppf \"Incompatible label name for 'kind' and constructor arguments.\"\n  | Record_constructor_in_union ->\n      Format.fprintf ppf \"Constructors in unions must not be an inline record.\"\n  | Unknown_union_method ->\n      Format.fprintf ppf \"Unknown method to discriminate unions.\"\n  | Union_without_discriminator ->\n      Format.fprintf ppf \"js.union without way to discriminate values.\"\n  | Contravariant_type_parameter label ->\n      Format.fprintf ppf \"Contravariant type parameter '%s is not allowed.\" label\n  | Record_expected shape ->\n      Format.fprintf ppf \"Record %s expected.\" shape\n  | Cannot_set_runtime_value name ->\n      Format.fprintf ppf \"Cannot set runtime value '%s'.\" name\n\nlet () =\n  Location.Error.register_error_of_exn\n    (function\n      | Error (loc, err) ->\n          let createf ~loc fmt =\n            Format.kasprintf\n              (fun str -> Location.Error.make ~loc ~sub:[] str) fmt\n          in\n          Some (createf ~loc \"%a\" print_error err)\n      | _ -> None\n    )\n\n(*\nlet show_attrs attrs =\n  prerr_endline \"===========\";\n  prerr_endline \"attributes:\";\n  List.iter (fun ({txt; loc = _}, _) -> prerr_endline txt) attrs\n*)\n\nlet js_name ~global_attrs ?(capitalize = false) name =\n  if has_attribute \"js.verbatim_names\" global_attrs then\n    if capitalize then String.capitalize_ascii name\n    else name\n  else\n    let n = String.length name in\n    let buf = Buffer.create n in\n    let capitalize = ref capitalize in\n    for i = 0 to n-1 do\n      let c = name.[i] in\n      if c = '_' then capitalize := true\n      else if !capitalize then begin\n        Buffer.add_char buf (Char.uppercase_ascii c);\n        capitalize := false\n      end else Buffer.add_char buf c\n    done;\n    Buffer.contents buf\n\nlet get_js_constr ~global_attrs name attributes =\n  match get_attribute \"js\" attributes with\n  | None -> `String (js_name ~global_attrs name)\n  | Some payload ->\n      begin match (expr_of_payload payload).pexp_desc with\n      | Pexp_constant (Pconst_string (s, _, _)) -> `String s\n      | Pexp_constant (Pconst_integer (n, _)) -> `Int n\n      | Pexp_constant (Pconst_float (f, _)) -> `Float f\n      | Pexp_construct (ident_loc, _) ->\n          begin match ident_loc.txt with\n          | Lident \"true\"  -> `Bool true\n          | Lident \"false\" -> `Bool false\n          | _ -> error ident_loc.loc Invalid_expression\n          end\n      | _ -> error payload.attr_loc Invalid_expression\n      end\n\n(** AST *)\n\ntype typ =\n  | Arrow of arrow_params\n  | Unit of Location.t\n  | Js\n  | Name of string * typ list\n  | Variant of { location: Location.t;\n                 global_attrs:attributes;\n                 attributes:attributes;\n                 constrs:constructor list }\n  | Tuple of typ list\n  | Typ_var of string\n  | Packaged_type of { local_name:  string; (* `a` specified by `(type a)`*)\n                       module_name: string  (* `A` as in `(module A : Ojs.T with type t = a)` *) }\n\nand lab =\n  | Arg\n  | Lab of {ml: string}\n  | Opt of {ml: string; def: Parsetree.expression option}\n\nand arg =\n  {\n    lab: lab;\n    att: attributes;\n    typ: typ;\n  }\n\nand arrow_params =\n  {\n    ty_args: arg list;\n    ty_vararg: arg option;\n    unit_arg: bool;\n    ty_res: typ;\n  }\n\nand constructor_arg =\n  | Constant\n  | Unary of typ\n  | Nary of typ list\n  | Record of (Location.t * lid * string * typ) list\n\nand constructor =\n  {\n    mlconstr: string;\n    arg: constructor_arg;\n    attributes: attributes;\n    location: Location.t;\n  }\n\nlet arg_label = function\n  | Arg -> Nolabel\n  | Lab {ml; _} -> Labelled ml\n  | Opt {ml; _} -> Optional ml\n\ntype apply_type =\n  | Function    (* f(..) *)\n  | NewableFunction (* new f(..) *)\n\ntype valdef =\n  | Cast\n  | Ignore\n  | PropGet of string\n  | PropSet of string\n  | IndexGet\n  | IndexSet\n  | MethCall of string\n  | Apply of apply_type\n  | Invoke\n  | Global of string\n  | New of string option\n  | Builder of attributes\n  | Auto of valdef\n\nlet rec string_of_valdef = function\n  | Cast -> \"js.cast\"\n  | Ignore -> \"js.ignore\"\n  | PropGet _ -> \"js.get\"\n  | PropSet _ -> \"js.set\"\n  | IndexGet -> \"js.index_get\"\n  | IndexSet -> \"js.index_set\"\n  | MethCall _ -> \"js.call\"\n  | Apply Function -> \"js.apply\"\n  | Apply NewableFunction -> \"js.apply_newable\"\n  | Invoke -> \"js.invoke\"\n  | Global _ -> \"js.global\"\n  | New None -> \"js.create\"\n  | New (Some _) -> \"js.new\"\n  | Builder _ -> \"js.builder\"\n  | Auto valdef -> string_of_valdef valdef\n\nlet auto_deprecation_attribute loc valdef =\n  let message =\n    Printf.sprintf\n      \"Heuristic for automatic binding is deprecated; please add the '@%s' attribute.\"\n      (string_of_valdef valdef)\n  in\n  attribute_of_warning loc message\n\ntype methoddef =\n  | Getter of string\n  | Setter of string\n  | IndexGetter\n  | IndexSetter\n  | MethodCall of string\n  | ApplyAsFunction of apply_type\n\ntype method_decl =\n  {\n    method_name: string;\n    method_typ: typ;\n    method_def: methoddef;\n    method_loc: Location.t;\n    method_attrs: attributes\n  }\n\ntype class_field =\n  | Method of method_decl\n  | Inherit of Longident.t Location.loc\n\ntype classdecl =\n  | Declaration of { class_name: string; class_fields: class_field list }\n  | Constructor of { class_name: string; js_class_name: string; class_arrow: arrow_params }\n\ntype decl =\n  | Module of functor_parameter list * string * decl list\n  | RecModule of (module_type * functor_parameter list * string * decl list) list\n  | ModuleAlias of string * Longident.t Location.loc\n  | Type of rec_flag * Parsetree.type_declaration list * attributes\n  | Val of { name:string;\n             ty: typ;\n             decl: valdef;\n             loc: Location.t;\n             packages: (string * string) list; (** reversed order, (local_name, module_name) *)\n             global_attrs: attributes }\n  | Class of classdecl list\n  | Implem of Parsetree.structure\n  | Open of Parsetree.open_description\n  | Include of Parsetree.module_expr Parsetree.include_infos\n\n(** Parsing *)\n\nlet local_type_of_type_var label =\n  \"__\"^label\n\n\nlet neg_variance = function\n  | -1 -> 1\n  | 0 | 1 -> -1\n  | _ -> invalid_arg \"neg_variance\"\n\nlet no_attributes attributes =\n  List.iter (fun attr ->\n      ignore (filter_attr_name \"js.dummy\" attr)\n    ) attributes;\n  attributes = []\n\ntype type_context =\n  {\n    type_params: string list;\n    packages: (string * string) list; (** reversed order, (local_name, module_name) *)\n  }\n\nlet empty_type_context = { type_params = []; packages = [] }\n\nlet rec parse_arg ~variance (ctx: type_context) lab ~global_attrs ty =\n  let lab =\n    match lab with\n    | Nolabel -> Arg\n    | Labelled ml -> Lab {ml}\n    | Optional ml ->\n        Opt {ml; def=get_expr_attribute \"js.default\" ty.ptyp_attributes}\n  in\n  {\n    lab;\n    att=ty.ptyp_attributes;\n    typ = parse_typ ~variance:(neg_variance variance) ctx ~global_attrs ty;\n  }\n\nand parse_typ ~variance ctx ~global_attrs ty =\n  match ty.ptyp_desc with\n  | Ptyp_arrow (lab, t1, t2) when has_attribute \"js.variadic\" t1.ptyp_attributes ->\n      begin match parse_arg ~variance ctx lab ~global_attrs t1 with\n      | {lab; att; typ=Name (\"list\", [typ])} ->\n          let ty_vararg = Some {lab; att; typ} in\n          begin match parse_typ ~variance ctx ~global_attrs t2 with\n          | Arrow ({ty_args = []; ty_vararg = None; unit_arg = _; ty_res = _} as params) when no_attributes t2.ptyp_attributes ->\n              Arrow {params with ty_vararg}\n          | Arrow _ when t2.ptyp_attributes = [] -> error ty.ptyp_loc Cannot_parse_type\n          | tres -> Arrow {ty_args = []; ty_vararg; unit_arg = false; ty_res = tres}\n          end\n      | _ -> error t1.ptyp_loc Invalid_variadic_type_arg\n      end\n  | Ptyp_arrow (lab, t1, t2) ->\n      let t1 = parse_arg ~variance ctx lab ~global_attrs t1 in\n      begin match parse_typ ~variance ctx ~global_attrs t2 with\n      | Arrow ({ty_args; ty_vararg = _; unit_arg = _; ty_res = _} as params) when no_attributes t2.ptyp_attributes -> Arrow {params with ty_args = t1 :: ty_args}\n      | tres ->\n          begin match t1 with\n          | {lab=Arg; att=[]; typ=Unit _} -> Arrow {ty_args = []; ty_vararg = None; unit_arg = true; ty_res = tres}\n          | _ -> Arrow {ty_args = [t1]; ty_vararg = None; unit_arg = false; ty_res = tres}\n          end\n      end\n  | Ptyp_constr ({txt = lid; loc = _}, tl) ->\n      begin match String.concat \".\" (Longident.flatten_exn lid), tl with\n      | \"unit\", [] -> Unit ty.ptyp_loc\n      | \"Ojs.t\", [] -> Js\n      | s, tl -> Name (s, List.map (parse_typ ~variance ctx ~global_attrs) tl)\n      end\n  | Ptyp_variant (rows, Closed, None) ->\n      let location = ty.ptyp_loc in\n      let prepare_row = function\n        | {prf_desc = Rtag ({txt = mlconstr; _}, true, []); prf_attributes = attributes; prf_loc = location} ->\n            { mlconstr; arg = Constant; attributes; location }\n        | {prf_desc = Rtag ({txt = mlconstr; _}, false, [typ]); prf_attributes = attributes; prf_loc = location} ->\n            begin match parse_typ ~variance ctx ~global_attrs typ with\n            | Tuple typs -> { mlconstr; arg = Nary typs; attributes; location }\n            | typ -> { mlconstr; arg = Unary typ; attributes; location }\n            end\n        | _ -> error location Cannot_parse_type\n      in\n      Variant {location; global_attrs; attributes = ty.ptyp_attributes; constrs = List.map prepare_row rows}\n\n  | Ptyp_tuple typs ->\n      let typs = List.map (parse_typ ~variance ctx ~global_attrs) typs in\n      Tuple typs\n\n  | Ptyp_var label ->\n      if List.mem label ctx.type_params then\n        if variance < 0 then\n          error ty.ptyp_loc (Contravariant_type_parameter label)\n        else\n          Name (local_type_of_type_var label, [])\n      else\n        begin match List.assoc_opt label ctx.packages with\n        | Some module_name -> Packaged_type { local_name = label; module_name }\n        | None -> Typ_var label\n        end\n\n  | _ ->\n      error ty.ptyp_loc Cannot_parse_type\n\nlet parse_typ = parse_typ ~variance:0\n\nlet check_prefix ~prefix s =\n  let l = String.length prefix in\n  if l <= String.length s && String.sub s 0 l = prefix\n  then\n    Some (String.sub s l (String.length s - l))\n  else\n    None\n\nlet has_prefix ~prefix s = check_prefix ~prefix s <> None\n\nlet drop_prefix ~prefix s =\n  match check_prefix ~prefix s with\n  | Some x -> x\n  | None -> assert false\n\n\nlet check_suffix ~suffix s =\n  let l = String.length suffix in\n  if l <= String.length s && String.sub s (String.length s - l) l = suffix\n  then\n    Some (String.sub s 0 (String.length s - l))\n  else\n    None\n\nlet rec choose f = function\n  | [] -> []\n  | x :: xs ->\n      begin match f x with\n      | None -> choose f xs\n      | Some y -> y :: choose f xs\n      end\n\nlet derived_from_type s ty =\n  match ty with\n  | Arrow {ty_args; ty_vararg = None; unit_arg = false; ty_res = Js} ->\n      begin match List.rev ty_args with\n      | {lab=Arg; att=_; typ=Name (t, _);} :: _ -> check_suffix ~suffix:\"_to_js\" s = Some t\n      | _ -> false\n      end\n  | Arrow {ty_res = Name (t, _); ty_vararg = None; unit_arg = false; ty_args } ->\n      begin match List.rev ty_args with\n      | {lab=Arg; att=_; typ= Js;} :: _ -> check_suffix ~suffix:\"_of_js\" s = Some t\n      | _ -> false\n      end\n  | _ -> false\n\nlet auto ~global_attrs s ty =\n  if derived_from_type s ty then\n    Ignore\n  else\n    Auto begin match ty with\n      | Arrow {ty_args = _; ty_vararg = None; unit_arg = _; ty_res = Name _} when s = \"create\" -> New None\n      | Arrow {ty_args = _; ty_vararg = None; unit_arg = _; ty_res = Name _} when has_prefix ~prefix:\"new_\" s -> New (Some (js_name ~capitalize:true ~global_attrs (drop_prefix ~prefix:\"new_\" s)))\n      | Arrow {ty_args = [_]; ty_vararg = None; unit_arg = false; ty_res = Unit _} when has_prefix ~prefix:\"set_\" s -> PropSet (js_name ~global_attrs (drop_prefix ~prefix:\"set_\" s))\n      | Arrow {ty_args = [{lab=Arg; att=_; typ=Name _}; _; _]; ty_vararg = None; unit_arg = false; ty_res = Unit _} when s = \"set\" -> IndexSet\n      | Arrow {ty_args = [{lab=Arg; att=_; typ=Name _}; _]; ty_vararg = None; unit_arg = false; ty_res = Unit _} when has_prefix ~prefix:\"set_\" s -> PropSet (js_name ~global_attrs (drop_prefix ~prefix:\"set_\" s))\n      | Arrow {ty_args = [{lab=Arg; att=_; typ=Name _}]; ty_vararg = None; unit_arg = false; ty_res = Unit _} -> MethCall (js_name ~global_attrs s)\n      | Arrow {ty_args = [{lab=Arg; att=_; typ=Name _}; _]; ty_vararg = None; unit_arg = false; ty_res = _} when s = \"get\" -> IndexGet\n      | Arrow {ty_args = [{lab=Arg; att=_; typ=Name _}]; ty_vararg = None; unit_arg = false; ty_res = _} -> PropGet (js_name ~global_attrs s)\n      | Arrow {ty_args = []; ty_vararg = None; unit_arg = true; ty_res = _} -> PropGet (js_name ~global_attrs s)\n      | Arrow {ty_args = {lab=Arg; att=_; typ=Name _} :: _; ty_vararg = _; unit_arg = _; ty_res = _} when s = \"apply\" -> Apply Function\n      | Arrow {ty_args = {lab=Arg; att=_; typ=Name _} :: _; ty_vararg = _; unit_arg = _; ty_res = _} -> MethCall (js_name ~global_attrs s)\n      | _ -> Global (js_name ~global_attrs s)\n    end\n\nlet auto_in_object ~global_attrs s typ =\n  Auto begin match typ with\n    | Arrow {ty_args = [{lab=Arg; att=_; typ=_}]; ty_vararg = None; unit_arg = false; ty_res = Unit _} when has_prefix ~prefix:\"set_\" s -> PropSet (js_name ~global_attrs (drop_prefix ~prefix:\"set_\" s))\n    | Arrow {ty_args = [_]; ty_vararg = None; unit_arg = _; ty_res = _} when s = \"get\" -> IndexGet\n    | Arrow {ty_args = [_; _]; ty_vararg = None; unit_arg = false; ty_res = Unit _} when s = \"set\" -> IndexSet\n    | Arrow _ when s = \"apply\" -> Apply Function\n    | Arrow _ -> MethCall (js_name ~global_attrs s)\n    | Unit _ -> MethCall (js_name ~global_attrs s)\n    | _ -> PropGet (js_name ~global_attrs s)\n  end\n\nlet parse_attr ~global_attrs (s, loc, auto) attribute =\n  let opt_name ?(prefix = \"\") ?(capitalize = false) () =\n    match attribute.attr_payload with\n    | PStr [] ->\n        begin match check_prefix ~prefix s with\n        | None | Some \"\" -> error loc (Implicit_name prefix)\n        | Some s ->\n            js_name ~global_attrs ~capitalize s\n        end\n    | _ -> id_of_expr (expr_of_payload attribute)\n  in\n  let actions =\n    [ \"js.cast\", (fun () -> Cast);\n      \"js.get\", (fun () -> PropGet (opt_name ()));\n      \"js.set\", (fun () -> PropSet (opt_name ~prefix:\"set_\" ()));\n      \"js.index_get\", (fun () -> IndexGet);\n      \"js.index_set\", (fun () -> IndexSet);\n      \"js.call\", (fun () -> MethCall (opt_name ()));\n      \"js.apply\", (fun () -> Apply Function);\n      \"js.apply_newable\", (fun () -> Apply NewableFunction);\n      \"js.invoke\", (fun () -> Invoke);\n      \"js.global\", (fun () -> Global (opt_name ()));\n      \"js\", (fun () -> auto ());\n      \"js.create\", (fun () -> New None);\n      \"js.new\", (fun () -> New (Some (opt_name ~prefix:\"new_\" ~capitalize:true ())));\n      \"js.builder\", (fun () -> Builder global_attrs);\n    ]\n  in\n  match List.find (fun (name, _) -> filter_attr_name name attribute) actions with\n  | exception Not_found -> None\n  | _, f -> Some (f ())\n\nlet extract_packages_for_valdecl ty =\n  let is_ojs_T (ojs_T: Longident.t) (t: Longident.t) =\n    match Longident.flatten_exn ojs_T, Longident.flatten_exn t with\n    | [\"Ojs\"; \"T\"], [\"t\"] -> true\n    | _ -> false\n  in\n  let rec go acc ty =\n    match ty.ptyp_desc with\n    | Ptyp_arrow (Nolabel, { ptyp_desc = Ptyp_package ({ txt = ojs_T; _ }, [{ txt = t; _}, { ptyp_desc = Ptyp_var tyvar; _ }]); ptyp_attributes; _ }, rest)\n      when is_ojs_T ojs_T t && has_attribute \"js\" ptyp_attributes ->\n        let module_name =\n          String.mapi (fun i c -> if i = 0 then Char.uppercase_ascii c else c) tyvar\n        in\n        go ((tyvar, module_name) :: acc) rest\n    | _ -> ty, acc\n  in\n  go [] ty\n\nlet parse_valdecl ~global_attrs ~in_sig vd =\n  let attributes = vd.pval_attributes in\n  let global_attrs = attributes @ global_attrs in\n  let s = vd.pval_name.txt in\n  let loc = vd.pval_loc in\n  let ty, packages = extract_packages_for_valdecl vd.pval_type in\n  let ty = parse_typ { empty_type_context with packages } ~global_attrs ty in\n  let auto () = auto ~global_attrs s ty in\n  let defs = choose (parse_attr ~global_attrs (s, loc, auto)) attributes in\n  let r =\n    match defs with\n    | [x] -> x\n    | [] when in_sig -> auto ()\n    | [] -> raise Exit\n    | _ -> error loc Multiple_binding_declarations\n  in\n  Val { name = s; ty; decl = r; packages; loc; global_attrs }\n\nlet rec functor_of_module_type = function\n  | {pmty_desc = Pmty_signature si; pmty_attributes; _} -> Some ([], si, pmty_attributes)\n  | {pmty_desc = Pmty_functor (params, body); _} ->\n      begin match functor_of_module_type body with\n      | Some (parameters, si, attrs) ->\n          Some (params :: parameters, si, attrs)\n      | None -> None\n      end\n  | _ -> None\n\nlet rec parse_sig_item ~global_attrs rest s =\n  let parse_module_declaration = function\n    | {pmd_name = { txt = Some name; _}; pmd_type; pmd_loc = _; pmd_attributes} ->\n        begin match functor_of_module_type pmd_type with\n        | None -> error s.psig_loc Cannot_parse_sigitem\n        | Some (functor_parameters, si, attrs) ->\n            let global_attrs =\n              push_module_attributes name attrs\n                (push_module_attributes name pmd_attributes global_attrs)\n            in\n            (functor_parameters, name, parse_sig ~global_attrs si)\n        end\n    | _ ->\n        error s.psig_loc Cannot_parse_sigitem\n  in\n  match s.psig_desc with\n  | Psig_value vd when vd.pval_prim = [] ->\n      parse_valdecl ~global_attrs ~in_sig:true vd :: rest ~global_attrs\n  | Psig_type (rec_flag, decls) ->\n      Type (rec_flag, decls, global_attrs) :: rest ~global_attrs\n  | Psig_module {pmd_name = {txt = Some name; _}; pmd_type = {pmty_desc = Pmty_alias lid; _}; _} ->\n      ModuleAlias (name, lid) :: rest ~global_attrs\n  | Psig_module md ->\n      let functor_parameters, name, decls = parse_module_declaration md in\n      Module (functor_parameters, name, decls) :: rest ~global_attrs\n  | Psig_recmodule mds ->\n      let mapper md =\n        let functor_parameters, name, decls = parse_module_declaration md in\n        let module_type = md.pmd_type in\n        (module_type, functor_parameters, name, decls)\n      in\n      RecModule (List.map mapper mds) :: rest ~global_attrs\n  | Psig_class cs -> Class (List.map (parse_class_decl ~global_attrs) cs) :: rest ~global_attrs\n  | Psig_attribute ({attr_payload = PStr str; _} as attribute) when filter_attr_name \"js.implem\" attribute -> Implem str :: rest ~global_attrs\n  | Psig_attribute attribute ->\n      let global_attrs = attribute :: global_attrs in\n      rest ~global_attrs\n  | Psig_open descr -> Open descr :: rest ~global_attrs\n  | Psig_include ({pincl_mod; _} as info) ->\n      let rec module_expr mod_typ =\n        match mod_typ.pmty_desc with\n        | Pmty_typeof module_expr -> module_expr\n        | Pmty_with (t, _) -> module_expr t\n        | _ -> error s.psig_loc Cannot_parse_sigitem\n      in\n      Include {info with pincl_mod = module_expr pincl_mod} :: rest ~global_attrs\n  | _ ->\n      error s.psig_loc Cannot_parse_sigitem\n\nand push_module_attributes module_name module_attributes global_attrs =\n  let rec rev_append acc = function\n    | ({attr_name = {txt = \"js.scope\"; _}; attr_payload = PStr [];  _}) as attribute :: tl ->\n        rev_append ({ attribute with attr_payload = PStr [Str.eval (Exp.constant (Pconst_string (module_name, Location.none, None)))] } :: acc) tl\n    |  hd :: tl -> rev_append (hd :: acc) tl\n    | [] -> acc\n  in\n  rev_append global_attrs (List.rev module_attributes)\n\nand parse_sig ~global_attrs = function\n  | [] -> []\n  | {psig_desc = Psig_attribute attribute; _} :: rest when filter_attr_name \"js.stop\" attribute ->\n      parse_sig_verbatim ~global_attrs rest\n  | {psig_desc = Psig_value vd; _} :: rest when\n      has_attribute \"js.custom\" vd.pval_attributes ->\n      let attribute = unoption (get_attribute \"js.custom\" vd.pval_attributes) in\n      let str = str_of_payload attribute in\n      Implem str :: parse_sig ~global_attrs rest\n  | s :: rest ->\n      parse_sig_item ~global_attrs (parse_sig rest) s\n\nand parse_sig_verbatim ~global_attrs = function\n  | [] -> []\n  | {psig_desc = Psig_attribute attribute; _} :: rest when filter_attr_name \"js.start\" attribute -> parse_sig ~global_attrs rest\n  | _ :: rest -> parse_sig_verbatim ~global_attrs rest\n\nand parse_class_decl ~global_attrs = function\n  | {pci_virt = Concrete; pci_params = []; pci_name; pci_expr = {pcty_desc = Pcty_arrow (Nolabel, {ptyp_desc = Ptyp_constr ({txt = Longident.Ldot (Lident \"Ojs\", \"t\"); loc = _}, []); ptyp_loc = _; ptyp_attributes = _; ptyp_loc_stack = _}, {pcty_desc = Pcty_signature {pcsig_self = {ptyp_desc = Ptyp_any; _}; pcsig_fields}; pcty_loc = _; pcty_attributes = _}); _}; pci_attributes; pci_loc = _} ->\n      let global_attrs = pci_attributes @ global_attrs in\n      let class_name = pci_name.txt in\n      Declaration { class_name; class_fields = List.map (parse_class_field ~global_attrs) pcsig_fields }\n  | {pci_virt = Concrete; pci_params = []; pci_name; pci_expr; pci_attributes; pci_loc} ->\n      let global_attrs = pci_attributes @ global_attrs in\n      let rec convert_typ = function\n        | { pcty_desc = Pcty_constr (id, typs); pcty_attributes; pcty_loc } ->\n            Typ.constr ~loc:pcty_loc ~attrs:pcty_attributes id typs\n        | { pcty_desc = Pcty_arrow (label, typ, ct); pcty_attributes; pcty_loc } ->\n            Typ.arrow ~loc:pcty_loc ~attrs:pcty_attributes label typ (convert_typ ct)\n        | _ -> error pci_loc Cannot_parse_classdecl\n      in\n      let class_arrow =\n        match parse_typ empty_type_context ~global_attrs (convert_typ pci_expr) with\n        | Arrow ({ty_args = _; ty_vararg = _; unit_arg = _; ty_res = Name (_, [])} as params) -> params\n        | (Name (_, []) as ty_res) -> {ty_args = []; ty_vararg = None; unit_arg = false; ty_res}\n        | _ -> error pci_loc Cannot_parse_classdecl\n      in\n      let class_name = pci_name.txt in\n      let js_class_name =\n        match get_string_attribute \"js.new\" pci_attributes with\n        | None -> js_name ~global_attrs ~capitalize:true class_name\n        | Some s -> s\n      in\n      Constructor {class_name; js_class_name; class_arrow}\n  | {pci_loc; _} -> error pci_loc Cannot_parse_classdecl\n\nand parse_class_field ~global_attrs = function\n  | {pctf_desc = Pctf_method ({txt = method_name; _}, Public, Concrete, typ); pctf_loc; pctf_attributes} ->\n      let ty = parse_typ empty_type_context ~global_attrs typ in\n      let auto () = auto_in_object ~global_attrs method_name ty in\n      let defs = choose (parse_attr ~global_attrs (method_name, pctf_loc, auto)) pctf_attributes in\n      let kind =\n        match defs with\n        | [x] -> x\n        | [] -> auto ()\n        | _ -> error pctf_loc Multiple_binding_declarations\n      in\n      let rec method_def = function\n        | Auto def -> method_def def\n        | PropGet s -> Getter s\n        | PropSet s -> Setter s\n        | IndexGet -> IndexGetter\n        | IndexSet -> IndexSetter\n        | MethCall s -> MethodCall s\n        | Apply t -> ApplyAsFunction t\n        | _ -> error pctf_loc Cannot_parse_classfield\n      in\n      let method_attrs =\n        match kind with\n        | Auto _ ->\n            [ auto_deprecation_attribute pctf_loc kind ]\n        | _ -> []\n      in\n      Method\n        {\n          method_name;\n          method_typ = ty;\n          method_def = method_def kind;\n          method_loc = pctf_loc;\n          method_attrs;\n        }\n  | {pctf_desc = Pctf_inherit {pcty_desc = Pcty_constr (id, []); _}; _} ->\n      Inherit id\n  | {pctf_loc; _} -> error pctf_loc Cannot_parse_classfield\n\n(** Code generation *)\n\nlet longident_parse x = Longident.parse x [@@ocaml.alert \"-deprecated\"]\n\nlet var x = Exp.ident (mknoloc (longident_parse x))\nlet str s = Exp.constant (Pconst_string (s, Location.none, None))\nlet int_of_repr n = Exp.constant (Pconst_integer (n, None))\nlet int n = int_of_repr (string_of_int n)\nlet float_of_repr f = Exp.constant (Pconst_float (f, None))\nlet bool b = Exp.construct (mknoloc (longident_parse (if b then \"true\" else \"false\"))) None\nlet pat_int n = Pat.constant (Pconst_integer (n, None))\nlet pat_float f = Pat.constant (Pconst_float (f, None))\nlet pat_str s = Pat.constant (Pconst_string (s, Location.none, None))\nlet pat_bool b = Pat.construct (mknoloc (longident_parse (if b then \"true\" else \"false\"))) None\n\nlet attr s e = (Attr.mk (mknoloc s) (PStr [Str.eval e]))\n\nlet disable_warnings = Str.attribute (attr \"ocaml.warning\" (str \"-7-32-39\"))\n(*  7: method overridden.\n    32: unused value declarations (when *_of_js, *_to_js are not needed)\n    39: unused rec flag (for *_of_js, *_to_js functions, when the\n       type is not actually recursive) *)\n\n\nlet incl = function\n  | [x] -> x\n  | str -> Str.include_ (Incl.mk (Mod.structure str))\n\nlet nolabel args = List.map (function x -> Nolabel, x) args\n\nlet ojs_typ = Typ.constr (mknoloc (longident_parse \"Ojs.t\")) []\n\nlet ojs_var s = Exp.ident (mknoloc (Ldot (Lident \"Ojs\", s)))\n\nlet ojs s args = Exp.apply (ojs_var s) (nolabel args)\n\nlet ojs_null = ojs_var \"null\"\n\nlet list_iter f x =\n  Exp.apply (Exp.ident (mknoloc (longident_parse \"List.iter\"))) (nolabel [f; x])\n\nlet fun_ ?(eta = true) (label, s, typ) e =\n  match e.pexp_desc with\n  | Pexp_apply (f, [Nolabel, {pexp_desc = Pexp_ident {txt = Lident x; loc = _}; _}])\n    when x = s && eta -> f\n  | _ ->\n      Ast_builder.Default.pexp_fun ~loc:Location.none label None (Pat.constraint_ (Pat.var (mknoloc s)) typ) e\n\nlet fun_unit e =\n  match e.pexp_desc with\n  | Pexp_apply (f, [Nolabel, {pexp_desc = Pexp_construct ({txt = Lident \"()\"; loc = _}, None); _}]) ->\n      f\n  | _ ->\n      Ast_builder.Default.pexp_fun ~loc:Location.none Nolabel None (Pat.construct (mknoloc (Lident \"()\")) None) e\n\nlet func args unit_arg body =\n  let body = if unit_arg then fun_unit body else body in\n  List.fold_right (fun s rest -> fun_ s rest) args body\n\nlet uid = ref 0\n\nlet fresh () =\n  incr uid;\n  Printf.sprintf \"x%i\" !uid\n\nlet apply f args = Exp.apply f args\n\nlet unit_lid = mknoloc (Lident \"()\")\nlet unit_expr = Exp.construct unit_lid None\nlet unit_pat = Pat.construct unit_lid None\n\nlet some_pat arg =\n  Pat.construct (mknoloc (longident_parse \"Some\")) (Some arg)\n\nlet none_pat () =\n  Pat.construct (mknoloc (longident_parse \"None\")) None\n\nlet match_some_none ~some ~none exp =\n  let s = fresh () in\n  Exp.match_ exp\n    [\n      Exp.case (some_pat (Pat.var (mknoloc s))) (some (var s));\n      Exp.case (none_pat ()) none;\n    ]\n\nlet app f args unit_arg =\n  let args = if unit_arg then args @ [Nolabel, unit_expr] else args in\n  apply f args\n\nlet exp_ignore res =\n  apply (var \"ignore\") [ Nolabel, res ]\nlet split sep s =\n  let n = String.length s in\n  let rec aux start i =\n    if i < n then\n      if s.[i] = sep then String.sub s start (i - start) :: aux (i+1) (i+1)\n      else aux start (i+1)\n    else [String.sub s start (i - start)]\n  in\n  aux 0 0\n\nlet ojs_global = ojs_var \"global\"\n\nlet ojs_get o s =\n  if is_ascii s then\n    ojs \"get_prop_ascii\" [o; str s]\n  else\n    ojs \"get_prop\" [o; ojs \"string_to_js\" [str s]]\n\nlet ojs_set o s v =\n  if is_ascii s then\n    ojs \"set_prop_ascii\" [o; str s; v]\n  else\n    ojs \"set_prop\" [o; ojs \"string_to_js\" [str s]; v]\n\nlet split_at s =\n  if String.length s > 0 && s.[0] = '@' then\n    Some (String.sub s 1 (String.length s - 1))\n  else None\n\nlet runtime s =\n  let runtime_value = Exp.ident (mknoloc (longident_parse \"Jsoo_runtime.Js.runtime_value\")) in\n  Exp.apply runtime_value (nolabel [Exp.constant (Pconst_string (s, Location.none, None))])\n\nlet rec select_split_path o = function\n  | [] -> assert false\n  | (hd :: tl) as l ->\n      let o, l =\n        match split_at hd with\n        | Some s -> runtime s, tl\n        | None -> o, l\n      in\n      match l with\n      | [] -> o, None\n      | [x] -> o, Some x\n      | hd :: tl -> select_split_path (ojs_get o hd) tl\n\nlet select_path o s =\n  select_split_path o (split '.' s)\n\nlet get_path global_object s =\n  let o, x = select_path global_object s in\n  match x with\n  | None -> o\n  | Some x -> ojs_get o x\n\nlet ojs_variable s =\n  get_path ojs_global s\n\nlet set_path ~loc global_object s v =\n  let o, x = select_path global_object s in\n  match x with\n  | None -> error loc (Cannot_set_runtime_value s)\n  | Some x ->\n      ojs_set o x v\n\nlet def ?packages s ty body =\n  let ty, body =\n    match packages with\n    | None | Some [] -> ty, body\n    | Some packages ->\n        (* append module arguments *)\n        let folder1 (ty, body) (local_name, module_name) =\n          let package is_local =\n            let t =\n              if is_local then Typ.constr (mknoloc (Lident local_name)) []\n              else Typ.var local_name\n            in\n            Typ.package (mknoloc (Ldot (Lident \"Ojs\", \"T\"))) [mknoloc (Lident \"t\"), t] in\n          let ty = Typ.arrow Nolabel (package false) ty in\n          let body =\n            let arg =\n              Pat.constraint_\n                (Pat.unpack (mknoloc (Some module_name)))\n                (package true)\n            in\n            Ast_builder.Default.pexp_fun ~loc:Location.none Nolabel None arg body\n          in\n          ty, body\n        in\n        (* append locally abstract types *)\n        let folder2 (ty, body) (local_name, _) =\n          ty, Exp.newtype (mknoloc local_name) body\n        in\n        List.fold_left folder2 (List.fold_left folder1 (ty, body) packages) packages\n  in\n  Str.value Nonrecursive [ Vb.mk ~value_constraint:(Pvc_constraint { locally_abstract_univars = []; typ = ty}) (Pat.var (mknoloc s)) body ]\n\nlet builtin_type = function\n  | \"int\" | \"string\" | \"bool\" | \"float\"\n  | \"array\" | \"list\" | \"option\" -> true\n  | _ -> false\n\nlet let_exp_in exp f =\n  let x = fresh () in\n  let pat = Pat.var (mknoloc x) in\n  Exp.let_ Nonrecursive [Vb.mk pat exp] (f (var x))\n\nlet ojs_apply_arr o = function\n  | `Simple arr -> ojs \"apply\" [o; arr]\n  | `Push arr ->\n      ojs \"call\" [o; str \"apply\"; Exp.array [ ojs_null; arr ]]\n\nlet ojs_call_arr o s meth =\n  match s, meth with\n  | None, `Simple arr -> ojs \"apply\" [o; arr]\n  | Some s, `Simple arr -> ojs \"call\" [o; str s; arr]\n  | None, `Push arr ->\n      let_exp_in o\n        (fun o ->\n           ojs \"call\" [o; str \"apply\"; Exp.array [ ojs_null ; arr ]]\n        )\n  | Some s, `Push arr ->\n      let_exp_in o\n        (fun o ->\n           ojs \"call\" [ojs_get o s; str \"apply\"; Exp.array [ o; arr ]]\n        )\n\nlet ojs_new_obj_arr cl = function\n  | `Simple arr -> ojs \"new_obj\" [cl; arr]\n  | `Push arr -> ojs \"new_obj_arr\" [cl; arr]\n\nlet assert_false = Exp.assert_ (Exp.construct (mknoloc (longident_parse \"false\")) None)\n\nlet clear_attr_mapper =\n  object\n    inherit Ast_traverse.map\n\n    method! attributes attrs =\n      let f {attr_name = {txt = _; loc}; _} = not (is_registered_loc loc) in\n      List.filter f attrs\n  end\n\nlet rewrite_typ_decl t =\n  let t = clear_attr_mapper # type_declaration {t with ptype_private = Public} in\n  match t.ptype_manifest, t.ptype_kind with\n  | None, Ptype_abstract -> {t with ptype_manifest = Some ojs_typ}\n  | _ -> t\n\nlet string_typ = Name (\"string\", [])\nlet int_typ = Name (\"int\", [])\nlet bool_typ = Name (\"bool\", [])\nlet float_typ = Name (\"float\", [])\n\nlet is_discriminator_type = function\n  | Name ((\"string\"|\"int\"|\"float\"|\"bool\"), []) -> true\n  | _ -> false\n\nlet is_simple_enum params =\n  let p {mlconstr = _; arg; attributes; location = _} =\n    match arg with\n    | Constant -> true\n    | Unary arg_typ when is_discriminator_type arg_typ -> has_attribute \"js.default\" attributes\n    | Unary _\n    | Nary _\n    | Record _ -> false\n  in\n  List.for_all p params\n\ntype union_discriminator =\n  | No_discriminator\n  | On_field of string\n\nlet get_variant_kind loc attrs =\n  if has_attribute \"js.enum\" attrs then `Enum\n  else if has_attribute \"js.union\" attrs then begin\n    match get_attribute \"js.union\" attrs with\n    | None -> assert false\n    | Some attribute ->\n        begin match attribute.attr_payload with\n        | PStr [] -> `Union No_discriminator\n        | _ ->\n            begin match expr_of_payload attribute with\n            | {pexp_desc = Pexp_apply ({pexp_desc = Pexp_ident {txt = Lident \"on_field\";_}; _}, [Nolabel, {pexp_desc = Pexp_constant (Pconst_string (s, _, _)); _}]); _} -> `Union (On_field s)\n            | _ -> error attribute.attr_loc Unknown_union_method\n            end\n        end\n  end else if has_attribute \"js.sum\" attrs then begin\n    match get_attribute \"js.sum\" attrs with\n    | None -> assert false\n    | Some attribute ->\n        begin match attribute.attr_payload with\n        | PStr [] -> `Sum \"kind\"\n        | _ -> `Sum (id_of_expr (expr_of_payload attribute))\n        end\n  end else error loc (Not_supported_here \"Sum types without js.* attribute\")\n\ntype variant_cases =\n  {\n    int_default: case option;\n    int_cases: float case_value list;\n    float_default: case option;\n    float_cases: float case_value list;\n    string_default: case option;\n    string_cases: string case_value list;\n    bool_default: case option;\n    bool_cases: bool case_value list;\n  }\n\nand 'a case_value = {\n  value: 'a;\n  case: case;\n  loc: location;\n}\n\nlet case_value ~loc ~value pat x =\n  let case = Exp.case pat x in\n  { value; case; loc }\n\nlet empty_variant_cases =\n  {\n    int_default = None; int_cases = [];\n    float_default = None; float_cases = [];\n    string_default = None; string_cases = [];\n    bool_default = None; bool_cases = []\n  }\n\nlet rec js2ml ty exp =\n  match ty with\n  | Js ->\n      exp\n  | Name (s, tl) ->\n      let s = if builtin_type s then \"Ojs.\" ^ s else s in\n      let args = List.map (js2ml_fun ~eta:true) tl in\n      app (var (s ^ \"_of_js\")) (nolabel (args @ [exp])) false\n  | Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let res = ojs_apply_arr exp concrete_args in\n      func formal_args unit_arg (js2ml_unit ty_res res)\n  | Unit _ ->\n      app (var \"Ojs.unit_of_js\") (nolabel [exp]) false\n  | Variant {location; global_attrs; attributes; constrs} ->\n      js2ml_of_variant ~variant:true location ~global_attrs attributes constrs exp\n  | Tuple typs ->\n      let f x =\n        Exp.tuple (List.mapi (fun i typ -> js2ml typ (ojs \"array_get\" [x; int i])) typs)\n      in\n      let_exp_in exp f\n  | Typ_var _ ->\n      app (var (\"Obj.magic\")) (nolabel ([exp])) false\n  | Packaged_type { module_name; _ } ->\n      app (var (module_name ^ \".t_of_js\")) (nolabel [exp]) false\n\nand js2ml_of_variant ~variant loc ~global_attrs attrs constrs exp =\n  let variant_kind = get_variant_kind loc attrs in\n  let check_label =\n    match variant_kind with\n    | `Sum kind -> (fun loc label -> if label = kind then error loc Sum_kind_args)\n    | _ -> (fun _ _ -> ())\n  in\n  let mkval =\n    if variant then fun x arg -> Exp.variant x arg\n    else fun x arg -> Exp.construct (mknoloc (Longident.Lident x)) arg\n  in\n  let f exp =\n    let gen_cases (cases: variant_cases) {mlconstr; arg; attributes; location} =\n      let case x =\n        let loc = location in\n        match get_js_constr ~global_attrs mlconstr attributes with\n        | `String s -> { cases with string_cases = case_value ~loc ~value:s (pat_str s) x :: cases.string_cases }\n        | `Int n -> { cases with int_cases = case_value ~loc ~value:(float_of_string n) (pat_int n) x :: cases.int_cases }\n        | `Float f -> { cases with float_cases = case_value ~loc ~value:(float_of_string f) (pat_float f) x :: cases.float_cases }\n        | `Bool b -> { cases with bool_cases = case_value ~loc ~value:b (pat_bool b) x :: cases.bool_cases }\n      in\n      let get_arg key typ = js2ml typ (ojs_get exp key) in\n      match arg with\n      | Constant -> case (mkval mlconstr None)\n      | Unary arg_typ ->\n          let otherwise() =\n            match variant_kind with\n            | `Enum -> error location Non_constant_constructor_in_enum\n            | `Sum _ ->\n                let loc, arg_field = get_string_attribute_default \"js.arg\" (location, \"arg\") attributes in\n                check_label loc arg_field;\n                case (mkval mlconstr (Some (get_arg arg_field arg_typ)))\n            | `Union _ -> case (mkval mlconstr (Some (js2ml arg_typ exp)))\n          in\n          let process_default defs cont =\n            match get_attribute \"js.default\" attributes with\n            | None -> otherwise()\n            | Some attribute ->\n                if List.for_all ((=) None) defs then begin\n                  match variant_kind with\n                  | `Enum ->\n                      let x = fresh() in\n                      cont (Some (Exp.case (Pat.var (mknoloc x)) (mkval mlconstr (Some (var x)))))\n                  | `Sum _ | `Union _ ->\n                      cont (Some (Exp.case (Pat.any ()) (mkval mlconstr (Some (js2ml arg_typ exp)))))\n                end else error attribute.attr_loc Multiple_default_case\n          in\n          begin match variant_kind with\n          | `Enum when arg_typ = int_typ ->\n              process_default [cases.int_default] (fun int_default -> { cases with int_default })\n          | `Enum when arg_typ = string_typ ->\n              process_default [cases.string_default] (fun string_default -> { cases with string_default })\n          | `Enum when arg_typ = bool_typ ->\n              process_default [cases.bool_default] (fun bool_default -> { cases with bool_default })\n          | `Enum when arg_typ = float_typ ->\n              process_default [cases.float_default] (fun float_default -> { cases with float_default })\n          | `Sum _ | `Union _ when arg_typ = Js ->\n              process_default [cases.int_default; cases.float_default; cases.string_default; cases.bool_default] (fun default -> { cases with int_default = default; float_default = default; string_default = default; bool_default = default })\n          | _ -> otherwise()\n          end\n      | Nary args_typ ->\n          begin match variant_kind with\n          | `Enum -> error location Non_constant_constructor_in_enum\n          | `Sum _ ->\n              let loc, args_field = get_string_attribute_default \"js.arg\" (location, \"arg\") attributes in\n              check_label loc args_field;\n              let get_args key i typ = js2ml typ (ojs \"array_get\" [ojs_get exp key; int i]) in\n              case (mkval mlconstr (Some (Exp.tuple (List.mapi (get_args args_field) args_typ))))\n          | `Union _ -> case (mkval mlconstr (Some (js2ml (Tuple args_typ) exp))) (* treat it as a tuple of the constructor arguments *)\n          end\n      | Record args ->\n          begin match variant_kind with\n          | `Enum -> error location Non_constant_constructor_in_enum\n          | `Sum _ ->\n              case (mkval mlconstr (Some (Exp.record (List.map (fun (loc, mlname, jsname, typ) -> check_label loc jsname; mlname, get_arg jsname typ) args) None)))\n          | `Union _ -> error location Record_constructor_in_union\n          end\n    in\n\n    let { int_default; int_cases; float_default; float_cases; string_default; string_cases; bool_default; bool_cases; _ } =\n      let cases = List.fold_left gen_cases empty_variant_cases constrs in\n\n      (* check if there are any duplicate cases of number *)\n      let _ =\n        let {\n          string_cases; float_cases; int_cases; bool_cases;\n          int_default = _; float_default = _; bool_default = _; string_default = _\n        } = cases in\n        let check_duplicates l =\n          let compare_values x y = Stdlib.compare x.value y.value in\n          let l = List.sort compare_values l in\n          let rec has_dup = function\n            | [] | [ _ ] -> ()\n            | x :: ((y :: _) as l) ->\n                if compare_values x y = 0 then\n                  error loc (Duplicate_case_value (x.loc, y.loc))\n                else\n                  has_dup l\n          in\n          has_dup l\n        in\n        check_duplicates string_cases;\n        check_duplicates bool_cases;\n        check_duplicates (float_cases @ int_cases);\n      in\n      cases\n    in\n\n    (* if both `true` and `false` are present, there is no need to generate the default cases for bool values *)\n    let bool_default, generate_fail_pattern_for_bool =\n      if List.exists (fun {value; _} -> value) bool_cases && List.exists (fun {value; _} -> not value) bool_cases then None, false\n      else bool_default, true\n    in\n\n    let gen_match ~fail_pattern e default other_cases =\n      let other_cases = List.map (fun {case;_} -> case) other_cases in\n      match default, other_cases with\n      | None, [] -> None\n      | Some default, [] when default.pc_lhs.ppat_desc = Ppat_any ->\n          Some default.pc_rhs\n      | Some default, _ ->\n          let cases = List.rev (default :: other_cases) in\n          Some (Exp.match_ e cases)\n      | None, _ :: _ ->\n          let cases =\n            if fail_pattern then (Exp.case (Pat.any ()) assert_false) :: other_cases\n            else other_cases\n          in\n          Some (Exp.match_ e (List.rev cases))\n    in\n    let discriminator =\n      match variant_kind with\n      | `Enum -> exp\n      | `Sum kind -> ojs_get exp kind\n      | `Union No_discriminator -> error loc Union_without_discriminator\n      | `Union (On_field kind) -> ojs_get exp kind\n    in\n    let number_match =\n      let default_expr exprOpt = Option.map (fun expr -> Exp.case (Pat.any ()) expr) exprOpt in\n      let get_int_match int_default = gen_match ~fail_pattern:true (js2ml int_typ discriminator) int_default int_cases in\n      let get_float_match float_default = gen_match ~fail_pattern:true (js2ml float_typ discriminator) float_default float_cases in\n      let int_match = get_int_match int_default in\n      let float_match = get_float_match float_default in\n      match int_match, float_match with\n      | Some m, None | None, Some m -> Some m\n      | None, None -> None\n      | Some _, Some _ ->\n          match int_default, float_default with\n          | _, None -> get_float_match (default_expr int_match)\n          | None, Some d ->\n              let case =\n                match get_int_match (default_expr (Some d.pc_rhs)) with\n                | None -> d\n                | Some int_match -> { d with pc_rhs = int_match }\n              in\n              get_float_match (Some case)\n          | Some d1, Some d2 ->\n              if d1 = d2 then get_float_match (default_expr int_match)\n              else error loc Multiple_default_case\n    in\n    let string_match = gen_match ~fail_pattern:true (js2ml string_typ discriminator) string_default string_cases in\n    let bool_match = gen_match ~fail_pattern:generate_fail_pattern_for_bool (js2ml bool_typ discriminator) bool_default bool_cases in\n    match number_match, string_match, bool_match with\n    | None, None, None -> assert false\n    | Some number_match, None, None -> number_match\n    | None, Some string_match, None -> string_match\n    | None, None, Some bool_match -> bool_match\n    | _ ->\n        let case_number = Option.map (Exp.case (pat_str \"number\")) number_match in\n        let case_string = Option.map (Exp.case (pat_str \"string\")) string_match in\n        let case_bool = Option.map (Exp.case (pat_str \"boolean\")) bool_match in\n        let case_default =\n          match variant_kind, int_default, float_default, string_default, bool_default with\n          | `Enum, _, _, _, _\n          | _, None, None, None, None -> Exp.case (Pat.any ()) assert_false\n          | (`Sum _ | `Union _), _, _, _, _ ->\n              let defaults = List.filter_map Fun.id [int_default; float_default; string_default; bool_default] in\n              match defaults with\n              | def :: rest when List.for_all ((=) def) rest -> def\n              | _ -> assert false\n        in\n        let cases =\n          List.fold_left\n            (fun state -> function Some x -> x :: state | None -> state)\n            [case_default]\n            [case_bool; case_string; case_number]\n        in\n        Exp.match_ (ojs \"type_of\" [discriminator]) cases\n  in\n  let_exp_in exp f\n\nand ml2js ty exp =\n  match ty with\n  | Js -> exp\n  | Name (s, tl) ->\n      let s = if builtin_type s then \"Ojs.\" ^ s else s in\n      let args = List.map (ml2js_fun ~eta:true) tl in\n      app (var (s ^ \"_to_js\")) (nolabel (args @ [exp])) false\n  | Arrow {ty_args; ty_vararg = None; unit_arg; ty_res} ->\n      let args =\n        let f _i {lab; att=_; typ} =\n          let s = fresh() in\n          let typ =\n            match lab with\n            | Arg | Lab _ -> typ\n            | Opt _ -> Name (\"option\", [typ])\n          in\n          (s, gen_typ typ), (arg_label lab, js2ml typ (var s))\n        in\n        List.mapi f ty_args\n      in\n      let formal_args, concrete_args = List.map fst args, List.map snd args in\n      let res = ml2js_unit ty_res (app exp concrete_args unit_arg) in\n      let body = if formal_args = [] then Ast_builder.Default.pexp_fun ~loc:Location.none Nolabel None (Pat.any ()) res else res in\n      let f = List.fold_right (fun (s, _) -> fun_ (Nolabel, s, ojs_typ)) formal_args body in\n      ojs \"fun_to_js\" [int (max 1 (List.length formal_args)); f]\n  | Arrow {ty_args; ty_vararg = Some {lab=label_variadic; att=_; typ=ty_variadic};\n           unit_arg; ty_res} ->\n      let arguments = fresh() in\n      let n_args = List.length ty_args in\n      let concrete_args =\n        List.mapi\n          (fun i {lab; att=_; typ} -> arg_label lab, js2ml typ (ojs \"array_get\" [var arguments; int i])) ty_args\n      in\n      let extra_arg = ojs \"list_of_js_from\" [ js2ml_fun ty_variadic; var arguments; int n_args ] in\n      let extra_arg =\n        match label_variadic with\n        | Arg | Lab _ -> extra_arg\n        | Opt _ -> Exp.construct (mknoloc (longident_parse \"Some\")) (Some extra_arg)\n      in\n      let concrete_args = concrete_args @ [arg_label label_variadic, extra_arg] in\n      let res = app exp concrete_args unit_arg in\n      let f = func [Nolabel, arguments, Typ.any ()] false (ml2js_unit ty_res res) in\n      ojs \"fun_to_js_args\" [f]\n  | Unit _ -> app (var \"Ojs.unit_to_js\") (nolabel [exp]) false\n  | Variant {location; global_attrs; attributes; constrs} ->\n      ml2js_of_variant ~variant:true location ~global_attrs attributes constrs exp\n  | Tuple typs ->\n      let typed_vars = List.mapi (fun i typ -> i, typ, fresh ()) typs in\n      let pat = Pat.tuple (List.map (function (_, _, x) -> Pat.var (mknoloc x)) typed_vars) in\n      Exp.let_ Nonrecursive [Vb.mk pat exp] begin\n        let n = List.length typs in\n        let a = fresh () in\n        let new_array = ojs \"array_make\" [int n] in\n        Exp.let_ Nonrecursive [Vb.mk (Pat.var (mknoloc a)) new_array] begin\n          let f e (i, typ, x) =\n            Exp.sequence (ojs \"array_set\" [var a; int i; ml2js typ (var x)]) e\n          in\n          List.fold_left f (var a) (List.rev typed_vars)\n        end\n      end\n  | Typ_var _ ->\n      app (var (\"Obj.magic\")) (nolabel ([exp])) false\n  | Packaged_type { module_name; _ } ->\n      app (var (module_name ^ \".t_to_js\")) (nolabel [exp]) false\n\nand ml2js_discriminator ~global_attrs mlconstr attributes =\n  match get_js_constr ~global_attrs mlconstr attributes with\n  | `Int n -> ml2js int_typ (int_of_repr n)\n  | `Float f -> ml2js float_typ (float_of_repr f)\n  | `String s -> ml2js string_typ (str s)\n  | `Bool b -> ml2js bool_typ (bool b)\n\nand ml2js_of_variant ~variant loc ~global_attrs attrs constrs exp =\n  let variant_kind = get_variant_kind loc attrs in\n  let check_label =\n    match variant_kind with\n    | `Sum kind -> (fun loc label -> if label = kind then error loc Sum_kind_args)\n    | _ -> (fun _ _ -> ())\n  in\n  let mkpat =\n    if variant then fun x arg -> Pat.variant x arg\n    else fun x arg -> Pat.construct (mknoloc (Longident.Lident x)) arg\n  in\n  let pair key typ value = Exp.tuple [str key; ml2js typ value] in\n  let case {mlconstr; arg; attributes; location} =\n    let mkobj args =\n      let discriminator = ml2js_discriminator ~global_attrs mlconstr attributes in\n      match variant_kind, args with\n      | `Enum, [] -> discriminator\n      | `Enum, _ :: _ -> error location Non_constant_constructor_in_enum\n      | `Sum kind, _ -> ojs \"obj\" [Exp.array ((Exp.tuple [str kind; discriminator]) :: args)]\n      | `Union _, [] -> ojs_null\n      | `Union _, _ :: _ -> error location Record_constructor_in_union\n    in\n    match arg with\n    | Constant -> Exp.case (mkpat mlconstr None) (mkobj [])\n    | Unary arg_typ ->\n        let x = fresh() in\n        let value =\n          match variant_kind with\n          | `Enum when\n              is_discriminator_type arg_typ &&\n              has_attribute \"js.default\" attributes -> ml2js arg_typ (var x)\n          | `Enum | `Sum _ ->\n              let loc, arg_field = get_string_attribute_default \"js.arg\" (location, \"arg\") attributes in\n              check_label loc arg_field;\n              mkobj [pair arg_field arg_typ (var x)]\n          | `Union _ -> ml2js arg_typ (var x)\n        in\n        Exp.case (mkpat mlconstr (Some (Pat.var (mknoloc x)))) value\n    | Nary args_typ ->\n        begin match variant_kind with\n        | `Enum | `Sum _ ->\n            let loc, args_field = get_string_attribute_default \"js.arg\" (location, \"arg\") attributes in\n            check_label loc args_field;\n            let xis = List.mapi (fun i typ -> i, typ, fresh()) args_typ in\n            let n_args = List.length xis in\n            Exp.case\n              (mkpat mlconstr (Some (Pat.tuple (List.map (fun (_, _, xi) -> Pat.var (mknoloc xi)) xis))))\n              (let args = fresh() in\n               Exp.let_ Nonrecursive\n                 [Vb.mk (Pat.var (mknoloc args)) (ojs \"array_make\" [int n_args])]\n                 (List.fold_left\n                    (fun e (i, typi, xi) ->\n                       Exp.sequence\n                         (ojs \"array_set\" [var args; int i; ml2js typi (var xi)]) e)\n                    (mkobj [pair args_field Js (var args)])\n                    xis))\n        | `Union _ -> (* treat it as a tuple of the constructor arguments *)\n            let x = fresh() in\n            Exp.case (mkpat mlconstr (Some (Pat.var (mknoloc x)))) (ml2js (Tuple args_typ) (var x))\n        end\n    | Record args ->\n        let x = fresh() in\n        Exp.case\n          (mkpat mlconstr (Some (Pat.var (mknoloc x))))\n          (mkobj (List.map (fun (loc, mlname, jsname, typ) -> check_label loc jsname; pair jsname typ (Exp.field (var x) mlname)) args))\n  in\n  Exp.match_ exp (List.map case constrs)\n\nand js2ml_fun ?eta ty = mkfun ?eta ~typ:Js (js2ml ty)\nand ml2js_fun ?eta ty = mkfun ?eta ~typ:ty (ml2js ty)\n\nand prepare_args ty_args ty_vararg : (arg_label * label * _) list * [ `Push of expression | `Simple of expression ] =\n  if ty_vararg = None &&\n     List.for_all\n       (function\n         | {lab = Opt {def = None; _}; _} -> false\n         | {typ = Variant {location = _; global_attrs = _; attributes; constrs}; _} when has_attribute \"js.enum\" attributes -> is_simple_enum constrs\n         | {lab = Arg | Lab _ | Opt {def = Some _; _}; _} -> true\n       )\n       ty_args\n  then\n    let x,y = prepare_args_simple ty_args in\n    x, `Simple y\n  else\n    let x, y = prepare_args_push ty_args ty_vararg in\n    x, `Push y\n\nand prepare_args_simple ty_args =\n  let f {lab; att=_; typ} =\n    let s = fresh () in\n    let e, typ =\n      match lab with\n      | Arg | Lab _ -> ml2js typ (var s), typ\n      | Opt {def; _} ->\n          begin match def with\n          | None -> assert false\n          | Some none ->\n              ml2js typ (match_some_none ~none ~some:(fun v -> v) (var s)), Name (\"option\", [typ])\n          end\n    in\n    (arg_label lab, s, gen_typ typ), e\n  in\n  let formal_args, concrete = List.split (List.map f ty_args) in\n  let concrete_args = Exp.array concrete in\n  formal_args, concrete_args\n\nand prepare_args_push ty_args ty_vararg =\n  let push arr typ x =\n    match typ with\n    | Variant {location = _; global_attrs; attributes; constrs} when\n        (has_attribute \"js.enum\" attributes && not (is_simple_enum constrs)) ->\n        let f {mlconstr; arg; attributes; location = _} =\n          let gen_tuple typs =\n            let xis = List.map (fun typ -> typ, fresh ()) typs in\n            let cargs =\n              match xis with\n              | [] -> None\n              | [_, x] -> Some (Pat.var (mknoloc x))\n              | _ :: _ :: _ -> Some (Pat.tuple (List.map (fun (_, xi) -> Pat.var (mknoloc xi)) xis))\n            in\n            let args =\n              ml2js_discriminator ~global_attrs mlconstr attributes ::\n              List.map (fun (typi, xi) -> ml2js typi (var xi)) xis\n            in\n            let e = exp_ignore (ojs \"call\" [arr; str \"push\"; Exp.array args]) in\n            Exp.case (Pat.variant mlconstr cargs) e\n          in\n          match arg with\n          | Constant -> gen_tuple []\n          | Unary typ -> gen_tuple [typ]\n          | Nary typs -> gen_tuple typs\n          | Record _ -> assert false\n        in\n        let cases = List.map f constrs in\n        Exp.match_ (Exp.constraint_ x (gen_typ typ)) cases\n    | typ -> exp_ignore (ojs \"call\" [arr; str \"push\"; Exp.array [ml2js typ x]])\n  in\n  let f {lab; att=_; typ} =\n    let s = fresh () in\n    let arg_typ =\n      match lab with\n      | Arg | Lab _ -> typ\n      | Opt _ -> Name (\"option\", [typ])\n    in\n    (arg_label lab, s, gen_typ arg_typ),\n    fun arr ->\n      let s = var s in\n      match lab with\n      | Arg | Lab _ -> push arr typ s\n      | Opt {def; _} ->\n          begin match def with\n          | None ->\n              match_some_none ~none:unit_expr ~some:(fun s -> push arr typ s) s\n          | Some none ->\n              push arr typ (match_some_none ~none ~some:(fun v -> v) s)\n          end\n  in\n  let formal_args, concrete_args = List.split (List.map f ty_args) in\n  let formal_args, concrete_args =\n    match ty_vararg with\n    | None -> formal_args, concrete_args\n    | Some {lab; att=_; typ} ->\n        let arg = fresh () in\n        formal_args @ [arg_label lab, arg, gen_typ (Name (\"list\", [typ]))],\n        concrete_args @ [fun arr ->\n            let extra_args = list_iter (mkfun ~typ (fun x -> push arr typ x)) in\n            match lab with\n            | Arg | Lab _ -> extra_args (var arg)\n            | Opt _ -> match_some_none ~none:unit_expr ~some:extra_args (var arg)\n          ]\n  in\n  let body arr = List.fold_right (fun code -> Exp.sequence (code arr)) concrete_args arr in\n  formal_args, let_exp_in (ojs \"new_obj\" [ojs_variable \"Array\"; Exp.array []]) body\n\nand ml2js_unit ty_res res =\n  match ty_res with\n  | Unit _ -> res\n  | _ -> ml2js ty_res res\n\nand js2ml_unit ty_res res =\n  match ty_res with\n  | Unit _ -> exp_ignore res\n  | _ -> js2ml ty_res res\n\nand gen_typ ?(packaged_type_as_type_var = false) = function\n  | Name (s, tyl) ->\n      Typ.constr (mknoloc (longident_parse s)) (List.map (gen_typ ~packaged_type_as_type_var) tyl)\n  | Js -> ojs_typ\n  | Unit _ ->\n      Typ.constr (mknoloc (Lident \"unit\")) []\n  | Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n      let tl =\n        match ty_vararg with\n        | None -> ty_args\n        | Some {lab; att; typ} -> ty_args @ [{lab; att; typ=Name (\"list\", [typ])}]\n      in\n      let tl = if unit_arg then tl @ [{lab=Arg;att=[];typ=Unit none}] else tl in\n      List.fold_right (fun {lab; att=_; typ} t2 ->\n          Typ.arrow (arg_label lab) (gen_typ ~packaged_type_as_type_var typ) t2) tl (gen_typ ~packaged_type_as_type_var ty_res)\n  | Variant {location = _; global_attrs = _; attributes = _; constrs} ->\n      let f {mlconstr; arg; attributes = _; location = _} =\n        let mlconstr = mknoloc mlconstr in\n        match arg with\n        | Constant -> Rf.mk (Rtag (mlconstr, true, []))\n        | Unary typ -> Rf.mk (Rtag (mlconstr, false, [gen_typ ~packaged_type_as_type_var typ]))\n        | Nary typs -> Rf.mk (Rtag (mlconstr, false, [gen_typ ~packaged_type_as_type_var (Tuple typs)]))\n        | Record _ -> assert false\n      in\n      let rows = List.map f constrs in\n      Typ.variant rows Closed None\n  | Tuple typs ->\n      Typ.tuple (List.map (gen_typ ~packaged_type_as_type_var) typs)\n  | Typ_var label -> Typ.var label\n  | Packaged_type { local_name; _ } ->\n      if packaged_type_as_type_var then Typ.var local_name\n      else Typ.constr (mknoloc (Lident local_name)) []\n\nand mkfun ?typ ?eta f =\n  let s = fresh () in\n  let typ =\n    match typ with\n    | None -> Typ.any ()\n    | Some typ -> gen_typ typ\n  in\n  fun_ ?eta (Nolabel, s, typ) (f (var s))\n\nlet process_fields ctx ~global_attrs l =\n  let loc = l.pld_name.loc in\n  let mlname = l.pld_name.txt in\n  let attrs = l.pld_attributes in\n  let typ = l.pld_type in\n  let jsname =\n    match get_string_attribute \"js\" attrs with\n    | None -> js_name ~global_attrs mlname\n    | Some s -> s\n  in\n  loc,\n  mknoloc (Lident mlname), (* OCaml label *)\n  jsname, (* JS name *)\n  parse_typ ctx ~global_attrs typ\n\n\nlet global_object ~global_attrs =\n  let rec traverse = function\n    | [] -> ojs_global\n    | hd :: tl ->\n        begin match get_expr_attribute \"js.scope\" [hd] with\n        | None -> traverse tl\n        | Some {pexp_desc=Pexp_constant (Pconst_string (prop, _, _)); _} ->\n            get_path (traverse tl) prop\n\n        | Some {pexp_desc=Pexp_tuple path; _} ->\n            let init = traverse tl in\n            let folder state pexp =\n              match pexp.pexp_desc with\n              | Pexp_constant (Pconst_string (prop, _, _)) -> get_path state prop\n              | _ -> pexp (* global object *)\n            in\n            List.fold_left folder init path\n        | Some global_object -> global_object\n        end\n  in\n  traverse global_attrs\n\nlet rec gen_decls si =\n  List.concat (List.map gen_decl si)\n\nand gen_funs ~global_attrs p =\n  let name = p.ptype_name.txt in\n  let decl_attrs = p.ptype_attributes in\n  let global_attrs = global_attrs in\n  let ctx_withloc =\n    List.map (function\n        | {ptyp_desc = Ptyp_any; ptyp_loc = loc; ptyp_attributes = _; ptyp_loc_stack = _}, (NoVariance, _) ->\n            { loc = loc; txt = fresh () }\n        | {ptyp_desc = Ptyp_var label; ptyp_loc = loc; ptyp_attributes = _; ptyp_loc_stack = _}, (NoVariance, _) ->\n            { loc = loc; txt = label }\n        | _ -> error p.ptype_loc Cannot_parse_type\n      ) p.ptype_params\n  in\n  let poly ty =\n    match ctx_withloc with\n    | [] -> ty\n    | l -> Typ.poly l ty\n  in\n  let ctx = List.map (fun lwl -> lwl.txt) ctx_withloc in\n  let full_ctx = { empty_type_context with type_params = ctx } in\n  let loc = p.ptype_loc in\n  let exception Skip_mapping_generation in\n  let local_type = Name (name, List.map (fun txt -> Name (local_type_of_type_var txt, [])) ctx) in\n  let of_js, to_js, custom_funs =\n    match p.ptype_kind with\n    | _ when has_attribute \"js.custom\" decl_attrs ->\n        begin match get_attribute \"js.custom\" decl_attrs with\n        | None -> assert false\n        | Some attribute ->\n            match expr_of_payload attribute with\n            | { pexp_desc = Pexp_record (\n                ( [ { txt = Lident \"of_js\"; loc = loc_of}, of_js;\n                    { txt = Lident \"to_js\"; loc = loc_to}, to_js ]\n                | [ { txt = Lident \"to_js\"; loc = loc_to}, to_js;\n                    { txt = Lident \"of_js\"; loc = loc_of}, of_js ] ), None); _} ->\n                let value_binding suffix loc (body: expression) (ty: core_type) =\n                  let name = { txt = Printf.sprintf \"%s_%s\" name suffix; loc} in\n                  Vb.mk ~loc ~value_constraint:(Pvc_constraint { locally_abstract_univars = []; typ = ty}) (Pat.var name) body\n                in\n                let ty = gen_typ (Name (name, List.map (fun x -> Typ_var x) ctx)) in\n                let fold_types f base =\n                  let ty =\n                    List.fold_right (fun tv acc -> Typ.arrow Nolabel (f tv) acc) ctx base\n                  in\n                  poly ty\n                in\n                let of_js_ty =\n                  fold_types (fun tv -> Typ.arrow Nolabel ojs_typ (Typ.var tv)) (Typ.arrow Nolabel ojs_typ ty)\n                in\n                let to_js_ty =\n                  fold_types (fun tv -> Typ.arrow Nolabel (Typ.var tv) ojs_typ) (Typ.arrow Nolabel ty ojs_typ)\n                in\n                let vbs =\n                  [\n                    value_binding \"of_js\" loc_of of_js of_js_ty;\n                    value_binding \"to_js\" loc_to to_js to_js_ty;\n                  ]\n                in\n                lazy (raise Skip_mapping_generation),\n                lazy (raise Skip_mapping_generation),\n                vbs\n            | { pexp_loc; _ } -> error pexp_loc (Record_expected \"{ to_js = ...; of_js = ... }\")\n        end\n    | Ptype_abstract ->\n        let ty, eta =\n          match p.ptype_manifest with\n          | None -> Js, true\n          | Some ty -> parse_typ full_ctx ~global_attrs { ty with ptyp_attributes = decl_attrs @ ty.ptyp_attributes }, false\n        in\n        lazy (js2ml_fun ~eta ty),\n        lazy (ml2js_fun ~eta ty),\n        []\n    | Ptype_variant cstrs ->\n        let prepare_constructor c =\n          let mlconstr = c.pcd_name.txt in\n          let arg =\n            match c.pcd_args with\n            | Pcstr_tuple args ->\n                begin match args with\n                | [] -> Constant\n                | [x] -> Unary (parse_typ full_ctx ~global_attrs x)\n                | _ :: _ :: _ -> Nary (List.map (parse_typ full_ctx ~global_attrs) args)\n                end\n            | Pcstr_record args ->\n                let global_attrs = c.pcd_attributes @ global_attrs in\n                Record (List.map (process_fields full_ctx ~global_attrs) args)\n          in\n          { mlconstr; arg; attributes = c.pcd_attributes; location = c.pcd_loc }\n        in\n        let params = List.map prepare_constructor cstrs in\n        lazy (mkfun ~typ:Js (js2ml_of_variant ~variant:false loc ~global_attrs decl_attrs params)),\n        lazy (mkfun ~typ:local_type (ml2js_of_variant ~variant:false loc ~global_attrs decl_attrs params)),\n        []\n    | Ptype_record lbls ->\n        let global_attrs = decl_attrs @ global_attrs in\n        let lbls = List.map (process_fields full_ctx ~global_attrs) lbls in\n        let of_js x (_loc, ml, js, ty) = ml, js2ml ty (ojs_get x js) in\n        let to_js x (_loc, ml, js, ty) = Exp.tuple [str js; ml2js ty (Exp.field x ml)] in\n        lazy (mkfun ~typ:Js (fun x -> Exp.record (List.map (of_js x) lbls) None)),\n        lazy (mkfun ~typ:local_type (fun x -> ojs \"obj\" [Exp.array (List.map (to_js x) lbls)])),\n        []\n    | _ ->\n        error p.ptype_loc Cannot_parse_type\n  in\n  let force_opt x = try (Some (Lazy.force x)) with Error (_, Union_without_discriminator) | Skip_mapping_generation -> None in\n  let of_js, to_js = force_opt of_js, force_opt to_js in\n  let alpha_of_js typ =\n    Arrow {ty_args = [{lab=Arg; att=[]; typ = Js}]; ty_vararg = None; unit_arg = false; ty_res = typ}\n  in\n  let alpha_to_js typ =\n    Arrow {ty_args = [{lab=Arg; att=[]; typ}]; ty_vararg = None; unit_arg = false; ty_res = Js}\n  in\n  let push_typ f l =\n    List.map (fun label -> f (Typ_var label)) ctx @ l\n  in\n  let push_fun suffix typ body =\n    match body with\n    | None -> None\n    | Some body ->\n        let params =\n          List.concat [\n            List.map\n              (fun label ->\n                 { pparam_loc = loc;\n                   pparam_desc = Pparam_newtype\n                       ({ label with txt = local_type_of_type_var label.txt})}\n              ) ctx_withloc;\n            List.map\n              (fun label ->\n                 let name = (local_type_of_type_var label)^suffix in\n                 let label = Name (local_type_of_type_var label, []) in\n                 { pparam_loc = loc;\n                   pparam_desc = Pparam_val (Nolabel, None, (Pat.constraint_ (Pat.var (mknoloc name)) (gen_typ (typ label))))}\n              ) ctx\n          ]\n        in\n        match params with\n        | [] -> Some body\n        | params ->\n            Some\n              (\n                Ast_builder.Default.pexp_function ~loc\n                  params\n                  None (Pfunction_body body))\n  in\n  let f (name, input_typs, ret_typ, code) =\n    match code with\n    | None -> None\n    | Some code ->\n        Some\n          (Vb.mk ~loc:p.ptype_loc\n             ~value_constraint:(\n               Pvc_constraint {\n                 locally_abstract_univars = [];\n                 typ =\n                   (poly\n                      (gen_typ (Arrow\n                                  {\n                                    ty_args = (List.map (fun typ -> {lab=Arg; att=[]; typ}) input_typs);\n                                    ty_vararg = None; unit_arg = false; ty_res = ret_typ\n                                  })))})\n             (Pat.var (mknoloc name))\n             code)\n  in\n  let funs =\n    choose f [ name ^ \"_of_js\", push_typ alpha_of_js [Js], Name (name, List.map (fun x -> Typ_var x) ctx), push_fun \"_of_js\" alpha_of_js of_js;\n               name ^ \"_to_js\", push_typ alpha_to_js [Name (name, List.map (fun x -> Typ_var x) ctx)], Js, push_fun \"_to_js\" alpha_to_js to_js ]\n  in\n  funs @ custom_funs\n\nand gen_decl = function\n  | Type (rec_flag, decls, global_attrs) ->\n      let funs = List.concat (List.map (gen_funs ~global_attrs) decls) in\n      let decls = List.map rewrite_typ_decl decls in\n      [ Str.type_ rec_flag decls; Str.value rec_flag funs ]\n\n  | Module (functor_parameters, s, decls) ->\n      [ Str.module_ (gen_module functor_parameters s decls) ]\n\n  | RecModule modules ->\n      [ Str.rec_module (List.map (fun (module_type, functor_parameters, s, decls) -> gen_module ~module_type functor_parameters s decls) modules) ]\n\n  | ModuleAlias (s, lid) ->\n      [ Str.module_ (Mb.mk (mknoloc (Some s)) (Mod.ident lid)) ]\n\n  | Val { decl = Ignore; _ } -> []\n\n  | Val { name = s; ty; decl; packages; loc; global_attrs } ->\n      let global_object = global_object ~global_attrs in\n      let d = gen_def ~global_object loc decl ty in\n      [ def ~packages s (gen_typ ~packaged_type_as_type_var:true ty) d ]\n\n  | Class decls ->\n      let cast_funcs = List.concat (List.map gen_class_cast decls) in\n      let classes = List.map (gen_classdecl cast_funcs) decls in\n      [Str.class_ classes; Str.value Nonrecursive cast_funcs]\n\n  | Implem str ->\n      (Lazy.force mapper) # structure str\n\n  | Open descr ->\n      let descr = {descr with popen_expr = Mod.ident descr.popen_expr} in\n      [ Str.open_ descr ]\n\n  | Include descr ->\n      [ Str.include_ descr ]\n\nand gen_module ?module_type functor_parameters s decls : module_binding =\n  let structure = Mod.structure (gen_decls decls) in\n  let functors =\n    List.fold_left (fun acc param ->\n        Mod.functor_ param acc\n      ) structure (List.rev functor_parameters)\n  in\n  let body =\n    match module_type with\n    | None -> functors\n    | Some mty -> Mod.constraint_ functors mty\n  in\n  Mb.mk (mknoloc (Some s)) body\n\nand gen_classdecl cast_funcs = function\n  | Declaration { class_name; class_fields } ->\n      let x = fresh() in\n      let obj =\n        Cl.structure\n          (Cstr.mk (Pat.any()) (List.map (gen_class_field x) class_fields))\n      in\n      (* generate \"let _ = t_to_js in\" to avoid unused decl warnings *)\n      let ign = function\n        | {pvb_pat = {ppat_desc = Ppat_var {txt; loc = _}; _}; _} -> Vb.mk (Pat.any ()) (var txt)\n        | _ -> assert false\n      in\n      let obj = Cl.let_ Nonrecursive (List.map ign cast_funcs) obj in\n      let obj = Cl.let_ Nonrecursive cast_funcs obj in\n      Ci.mk\n        (mknoloc class_name)\n        (Cl.fun_ Nolabel None (Pat.constraint_ (Pat.var (mknoloc x)) ojs_typ) obj)\n  | Constructor {class_name; js_class_name; class_arrow = {ty_args; ty_vararg; unit_arg; ty_res}} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let obj = ojs_new_obj_arr (ojs_variable js_class_name) concrete_args in\n      let super_class =\n        match ty_res with\n        | Name (super_class, []) -> super_class\n        | _ -> assert false\n      in\n      let e = Cl.apply (Cl.constr (mknoloc (longident_parse super_class)) []) [Nolabel, obj] in\n      let e = if unit_arg then Cl.fun_ Nolabel None unit_pat e else e in\n      let f e (label, x, _) = Cl.fun_ label None (Pat.var (mknoloc x)) e in\n      Ci.mk (mknoloc class_name) (List.fold_left f e (List.rev formal_args))\n\nand gen_class_field x = function\n  | Method {method_name; method_typ; method_def; method_loc; method_attrs} ->\n      let body =\n        match method_def, method_typ with\n        | Getter s, ty_res -> js2ml ty_res (ojs_get (var x) s)\n        | Setter s, Arrow {ty_args = [{lab=Arg; att=_; typ}]; ty_vararg = None; unit_arg = false; ty_res = Unit _} ->\n            mkfun (fun arg -> ojs_set (var x) s (ml2js typ arg))\n        | MethodCall s, Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n            let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n            let res = ojs_call_arr (var x) (Some s) concrete_args in\n            func formal_args unit_arg (js2ml_unit ty_res res)\n        | MethodCall s, ty_res ->\n            js2ml_unit ty_res (ojs \"call\" [var x; str s; Exp.array []])\n        | IndexGetter, Arrow {ty_args = [{lab=Arg; att=_; typ=ty_index}]; ty_vararg = None; unit_arg = false; ty_res } ->\n            gen_index_get ty_index (var x) ty_res\n        | IndexSetter, Arrow {ty_args = [{lab=Arg; att=_; typ=ty_index}; {lab=Arg; att=_; typ=ty_value}]; ty_vararg = None; unit_arg = false; ty_res = Unit _ } ->\n            gen_index_set ty_index (var x) ty_value\n        | ApplyAsFunction t, Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n            let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n            let res =\n              match t with\n              | Function -> ojs_apply_arr (var x) concrete_args\n              | NewableFunction -> ojs_new_obj_arr (var x) concrete_args\n            in\n            func formal_args unit_arg (js2ml_unit ty_res res)\n        | _ -> error method_loc Binding_type_mismatch\n      in\n      Cf.method_ ~attrs:method_attrs (mknoloc method_name) Public (Cf.concrete Fresh (Exp.constraint_ body (gen_typ method_typ)))\n  | Inherit super ->\n      let e = Cl.apply (Cl.constr super []) [Nolabel, var x] in\n      Cf.inherit_ Fresh e None\n\nand gen_class_cast = function\n  | Declaration { class_name; class_fields = _ } ->\n      let class_typ = Typ.constr (mknoloc (longident_parse class_name)) [] in\n      let to_js =\n        let arg = fresh() in\n        Vb.mk (Pat.var (mknoloc (class_name ^ \"_to_js\")))\n          (Ast_builder.Default.pexp_fun ~loc:Location.none Nolabel None\n             (Pat.constraint_ (Pat.var (mknoloc arg)) class_typ)\n             (Exp.constraint_ (Exp.send (var arg) (mknoloc \"to_js\")) ojs_typ))\n      in\n      let of_js =\n        let arg = fresh() in\n        Vb.mk (Pat.var (mknoloc (class_name ^ \"_of_js\")))\n          (Ast_builder.Default.pexp_fun ~loc:Location.none Nolabel None\n             (Pat.constraint_ (Pat.var (mknoloc arg)) ojs_typ)\n             (Exp.constraint_ (Exp.apply (Exp.new_ (mknoloc (Longident.Lident class_name))) [Nolabel, var arg]) class_typ))\n      in\n      [to_js; of_js]\n  | Constructor {class_name = _; js_class_name = _; class_arrow = _} -> []\n\nand gen_def ~global_object loc decl ty =\n  match decl, ty with\n  | Cast, Arrow {ty_args = [{lab=Arg; att=_; typ}]; ty_vararg = None; unit_arg = false; ty_res} ->\n      mkfun ~typ (fun this -> js2ml ty_res (ml2js typ this))\n\n  | PropGet s, Arrow {ty_args = [{lab=Arg; att=_; typ}]; ty_vararg = None; unit_arg = false; ty_res} ->\n      mkfun ~typ (fun this -> js2ml ty_res (ojs_get (ml2js typ this) s))\n\n  | PropGet s, Arrow {ty_args = []; ty_vararg = None; unit_arg = true; ty_res} ->\n      fun_unit (gen_def ~global_object loc (Global s) ty_res)\n\n  | Global s, ty_res ->\n      begin match ty_res with\n      | Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n          let this, s = select_path global_object s in\n          let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n          let res this = ojs_call_arr (ml2js Js this) s concrete_args in\n          func formal_args unit_arg (js2ml_unit ty_res (res this))\n      | _ -> js2ml ty_res (get_path global_object s)\n      end\n\n  | PropSet s,\n    Arrow {ty_args = [{lab=Arg; att=_; typ=(Name _ as ty_this)};\n                      {lab=Arg; att=_; typ=ty_arg}];\n           ty_vararg = None; unit_arg = false; ty_res = Unit _} ->\n      let res this arg =\n        ojs_set (ml2js ty_this this) s (ml2js ty_arg arg)\n      in\n      mkfun ~typ:ty_this (fun this -> mkfun ~typ:ty_arg (fun arg -> res this arg))\n\n  | PropSet s, Arrow {ty_args = [{lab = Arg; att = _; typ = ty_arg}]; ty_vararg = None; unit_arg = false; ty_res = Unit _} ->\n      mkfun ~typ:ty_arg (fun arg -> set_path ~loc:arg.pexp_loc global_object s (ml2js ty_arg arg))\n\n  | MethCall s,\n    Arrow {ty_args = {lab=Arg; att=_; typ} :: ty_args; ty_vararg; unit_arg; ty_res} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let res this = ojs_call_arr (ml2js typ this) (Some s) concrete_args in\n      mkfun ~typ (fun this -> func formal_args unit_arg (js2ml_unit ty_res (res this)))\n\n  | New name, Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let res =\n        let constructor =\n          match name with\n          | None -> global_object\n          | Some name -> get_path global_object name\n        in\n        ojs_new_obj_arr constructor concrete_args\n      in\n      func formal_args unit_arg (js2ml ty_res res)\n\n  | Builder global_attrs, Arrow {ty_args; ty_vararg = None; unit_arg; ty_res} ->\n      let gen_arg {lab; att; typ} =\n        let s = fresh () in\n        let arg_typ =\n          match lab with\n          | Arg | Lab _ -> typ\n          | Opt _ -> Name (\"option\", [typ])\n        in\n        (arg_label lab, s, gen_typ arg_typ),\n        fun x ->\n          let js =\n            match get_string_attribute \"js\" att, lab with\n            | Some s, _ -> s\n            | None, Arg -> error loc Unlabelled_argument_in_builder\n            | None, (Lab {ml; _} | Opt {ml; _}) -> js_name ~global_attrs ml\n          in\n          let code exp = ojs_set x js (ml2js typ exp) in\n          (* special logic to avoid setting optional argument to 'undefined' *)\n          match lab with\n          | Arg | Lab _ -> code (var s)\n          | Opt {def; _} ->\n              begin match def with\n              | None ->\n                  match_some_none (var s) ~none:unit_expr ~some:code\n              | Some none ->\n                  code (match_some_none ~none ~some:(fun v -> v) (var s))\n              end\n      in\n\n      let args = List.map gen_arg ty_args in\n      let formal_args = List.map fst args in\n      let concrete_args = List.map snd args in\n      let f x init code = Exp.sequence (code x) init in\n      let init x = List.fold_left (f x) (js2ml_unit ty_res x) (List.rev concrete_args) in\n      let body = let_exp_in (ojs \"empty_obj\" [unit_expr]) init in\n      func formal_args unit_arg body\n\n  | Apply t,\n    Arrow {ty_args = {lab=Arg; att=_; typ} :: ty_args; ty_vararg; unit_arg; ty_res} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let res this =\n        match t with\n        | Function -> ojs_apply_arr (ml2js typ this) concrete_args\n        | NewableFunction -> ojs_new_obj_arr (ml2js typ this) concrete_args\n      in\n      mkfun ~typ (fun this -> func formal_args unit_arg (js2ml_unit ty_res (res this)))\n\n  | Invoke, Arrow {ty_args; ty_vararg; unit_arg; ty_res} ->\n      let formal_args, concrete_args = prepare_args ty_args ty_vararg in\n      let res = ojs_apply_arr global_object concrete_args in\n      func formal_args unit_arg (js2ml ty_res res)\n\n  | IndexGet,\n    Arrow {ty_args = [{lab=Arg; att=_; typ=(Name _ as ty_this)}; {lab=Arg; att=_; typ=ty_index}];\n           ty_vararg = None; unit_arg = false; ty_res} ->\n      mkfun ~typ:ty_this (fun this -> gen_index_get ty_index (ml2js ty_this this) ty_res)\n\n  | IndexSet,\n    Arrow {ty_args = [{lab=Arg; att=_; typ=(Name _ as ty_this)};\n                      {lab=Arg; att=_; typ=ty_index};\n                      {lab=Arg; att=_; typ=ty_value}];\n           ty_vararg = None; unit_arg = false; ty_res = Unit _} ->\n      mkfun ~typ:ty_this (fun this -> gen_index_set ty_index (ml2js ty_this this) ty_value)\n\n  | Auto valdef, _ ->\n      Ast_helper.Exp.attr\n        (gen_def ~global_object loc valdef ty)\n        (auto_deprecation_attribute loc valdef)\n  | _ ->\n      error loc Binding_type_mismatch\n\nand gen_index_get ty_index this ty_res =\n  let res index =\n    match ty_index with\n    | Name (\"int\", []) -> ojs \"array_get\" [this; index]\n    | _ -> ojs \"get_prop\" [this; ml2js ty_index index]\n  in\n  mkfun ~typ:ty_index (fun index -> js2ml ty_res (res index))\n\nand gen_index_set ty_index this ty_value =\n  let res index value =\n    let value_js = ml2js ty_value value in\n    match ty_index with\n    | Name (\"int\", []) -> ojs \"array_set\" [this; index; value_js]\n    | _ -> ojs \"set_prop\" [this; ml2js ty_index index; value_js]\n  in\n  mkfun ~typ:ty_index (fun index -> mkfun ~typ:ty_value (fun value -> res index value))\n\n\n(** ppx mapper *)\n\nand str_of_sg ~global_attrs sg =\n  let decls = parse_sig ~global_attrs sg in\n  let attr =\n    attr \"js.dummy\" (str \"!! This code has been generated by gen_js_api !!\")\n  in\n  register_loc attr;\n  Str.attribute attr ::\n  disable_warnings ::\n  gen_decls decls\n\nand module_expr_rewriter ~loc ~attrs sg =\n  let str = str_of_sg ~global_attrs:attrs sg in\n  Mod.constraint_\n    (Mod.structure ~attrs:[ merlin_hide ] str)\n    (Mty.signature ~loc ~attrs (clear_attr_mapper # signature sg))\n\nand js_to_rewriter ~loc ty =\n  let e' = with_default_loc {loc with loc_ghost = true }\n      (fun () -> js2ml_fun (parse_typ empty_type_context ~global_attrs:[] ty))\n  in\n  { e' with pexp_loc = loc }\n\nand js_of_rewriter ~loc ty =\n  let e' = with_default_loc {loc with loc_ghost = true}\n      (fun () -> ml2js_fun (parse_typ empty_type_context ~global_attrs:[] ty))\n  in\n  { e' with pexp_loc = loc  }\n\nand type_decl_rewriter ~loc rec_flag l =\n  let itm = with_default_loc {loc with loc_ghost = true}\n      (fun () ->\n         let funs = List.concat (List.map (gen_funs ~global_attrs:[]) l) in\n         [\n           disable_warnings;\n           Str.value ~loc:loc rec_flag funs\n         ]\n      )\n  in\n  itm\n\nand mapper =\n  lazy (object\n    inherit Ast_traverse.map as super\n\n    method! module_expr mexp =\n      let mexp = super # module_expr mexp in\n      match mexp.pmod_desc with\n      | Pmod_extension ({txt = \"js\"; _}, PSig sg) ->\n          module_expr_rewriter ~loc:mexp.pmod_loc ~attrs:mexp.pmod_attributes sg\n      | _ -> mexp\n\n    method! structure_item str =\n      let str = super # structure_item str in\n      let global_attrs = [] in\n      match str.pstr_desc with\n      | Pstr_primitive vd when vd.pval_prim = [] ->\n          begin match parse_valdecl ~global_attrs ~in_sig:false vd with\n          | exception Exit -> str\n          | d -> incl (gen_decls [d])\n          end\n      | Pstr_type (rec_flag, decls) ->\n          let js_decls = List.filter (fun d -> has_attribute \"js\" d.ptype_attributes) decls in\n          begin match js_decls with\n          | [] -> str\n          | l ->\n              incl (\n                {str with pstr_desc = Pstr_type (rec_flag, List.map (fun d -> if has_attribute \"js\" d.ptype_attributes then rewrite_typ_decl d else d) decls)}\n                ::\n                type_decl_rewriter ~loc:str.pstr_loc rec_flag l\n              )\n          end\n      | _ ->\n          str\n\n    method! expression e =\n      let e = super # expression e in\n      match e.pexp_desc with\n      | Pexp_extension (attr, PTyp ty) when filter_extension \"js.to\" attr ->\n          js_to_rewriter ~loc:e.pexp_loc ty\n      | Pexp_extension (attr, PTyp ty) when filter_extension \"js.of\" attr ->\n          js_of_rewriter ~loc:e.pexp_loc ty\n      | _ ->\n          e\n\n    method! attribute a =\n      ignore (filter_attr_name \"js.dummy\" a : bool);\n      super # attribute a\n\n  end)\n\nlet is_js_attribute txt = txt = \"js\" || has_prefix ~prefix:\"js.\" txt\n\nlet check_loc_mapper =\n  object\n    inherit Ast_traverse.map\n\n    method! attribute ({attr_name = {txt; loc}; _} as attr) =\n      if is_js_attribute txt then begin\n        if is_registered_loc loc || not !check_attribute || txt = \"js.dummy\" then ()\n        else error loc (Spurious_attribute txt)\n      end;\n      attr\n\n  end\n\n(** Main *)\n\nlet out = ref \"\"\n\nlet specs =\n  [\n    \"-o\", Arg.Set_string out, \"  Specify output .ml file (- for stdout).\";\n  ]\n\nlet usage = \"gen_js_api [-o mymodule.ml] mymodule.mli\"\n\nlet standalone () =\n  let files = ref [] in\n  Arg.parse specs (fun s -> files := s :: !files) usage;\n  let src =\n    match !files with\n    | [src] -> src\n    | [] -> error Location.none No_input\n    | _ -> error Location.none Multiple_inputs\n  in\n  if !out = \"\" then out := Filename.chop_extension src ^ \".ml\";\n  let oc = if !out = \"-\" then stdout else open_out !out in\n  let sg =\n    Ocaml_common.Pparse.parse_interface\n      ~tool_name:\"gen_js_iface\"\n      src |> Selected_ast.Of_ocaml.copy_signature\n  in\n  let str = str_of_sg ~global_attrs:[] sg in\n  ignore (check_loc_mapper # signature sg);\n  let str = clear_attr_mapper # structure str in\n  Format.fprintf (Format.formatter_of_out_channel oc) \"%a@.\" Pprintast.structure str;\n  if !out <> \"-\" then close_out oc\n\nlet mapper =\n  object\n    inherit Ast_traverse.map as super\n\n    method! structure str =\n      check_loc_mapper # structure (super#structure str)\n  end\n\n\nlet mark_attributes_as_used =\n  (* mark `js.***` attributes as used in mli. *)\n  object\n    inherit Ast_traverse.map as super\n    method! attribute ({attr_name = {txt; _}; _} as attr) =\n      if is_js_attribute txt then\n        ignore (filter_attr_name txt attr : bool);\n\n      super # attribute attr\n  end\n"
  },
  {
    "path": "ppx-lib/gen_js_api_ppx.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\nopen Ppxlib\n\nval check_attribute : bool ref\n\nval mapper : Ast_traverse.map\n\nval module_expr_rewriter: loc:Location.t -> attrs:Ppxlib.Parsetree.attributes -> Ppxlib.Parsetree.signature -> Ppxlib.module_expr\n\nval js_of_rewriter: loc:Location.t -> core_type -> expression\n\nval js_to_rewriter: loc:Location.t -> core_type -> expression\n\nval type_decl_rewriter: loc:Location.t -> rec_flag -> type_declaration list -> structure\n\nval mark_attributes_as_used: Ast_traverse.map\n\nval standalone : unit -> unit\n"
  },
  {
    "path": "ppx-standalone/dune",
    "content": "(executables\n (names gen_js_api)\n (public_names gen_js_api)\n (package gen_js_api)\n (libraries compiler-libs.common ppxlib gen_js_api.lib))\n\n(install\n (section libexec)\n (package gen_js_api)\n (files\n  (gen_js_api.exe as gen_js_api)))\n"
  },
  {
    "path": "ppx-standalone/gen_js_api.ml",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\nopen Ppxlib\n\nlet () =\n  try\n    Gen_js_api_ppx.standalone ()\n  with exn ->\n    Format.eprintf \"%a@.\" Location.report_exception exn;\n    exit 2\n"
  },
  {
    "path": "ppx-standalone/gen_js_api.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n\n(* Empty interface, to enable unused-declaration warnings. *)\n"
  },
  {
    "path": "ppx-test/binding.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\nmodule M : sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val cast: t -> string [@@js.cast]\n\n  val prop_get_arg: t -> int [@@js.get \"getter\"]\n  val prop_get: unit -> int [@@js.get \"getter\"]\n\n  val global: t [@@js.global \"global\"]\n  val global_arrow: int -> int [@@js.global \"global\"]\n\n  val prop_set: t -> int -> unit [@@js.set \"setter\"]\n  val prop_set_global: t -> unit [@@js.set \"setter\"]\n\n  val method_call_global: t -> int [@@js.call \"method\"]\n  val method_call_global_unit: t -> unit [@@js.call \"method\"]\n  val method_call_unit: t -> unit -> int [@@js.call \"method\"]\n  val method_call_args: t -> int -> int [@@js.call \"method\"]\n  val method_call_unit_unit: t -> unit -> unit [@@js.call \"method\"]\n  val method_call_args_unit: t -> int -> unit [@@js.call \"method\"]\n\n  val new_thing: int -> t [@@js.new]\n\n  val builder: ?x:int -> (int [@js \"y\"]) -> z:int -> t [@@js.builder]\n\n  val index_get_int: t -> int -> string option [@@js.index_get]\n  val index_get_string: t -> string -> string option [@@js.index_get]\n  val index_get_generic: t -> Ojs.t -> string option [@@js.index_get]\n\n  val index_set_int: t -> int -> string -> unit [@@js.index_set]\n  val index_set_string: t -> string -> string -> unit [@@js.index_set]\n  val index_set_generic: t -> Ojs.t -> string -> unit [@@js.index_set]\nend"
  },
  {
    "path": "ppx-test/binding_automatic.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n[@@@js.implem [@@@warning \"-22\"]]\n\nmodule M : sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val prop_get_arg: t -> int\n  val prop_get: unit -> int\n  val set_prop: t -> int -> unit\n  val set_global: int -> unit\n  val new_thing_unit: unit -> t\n  val new_thing_args: int -> t\n  val method_call_global: t -> unit\n  val method_call_unit: t -> unit -> int\n  val method_call_args: t -> int -> int\n  val method_call_unit_unit: t -> unit -> unit\n  val method_call_args_unit: t -> int -> unit\n  val global: t\n\n  [@@@warning \"-32\"]\n  val get: t -> int -> string option\n  val set: t -> int -> string -> unit\n  val get: t -> string -> string option\n  val set: t -> string -> string -> unit\n  [@@@warning \"+32\"]\n  val get: t -> Ojs.t -> string option\n  val set: t -> Ojs.t -> string -> unit\nend\n"
  },
  {
    "path": "ppx-test/binding_explicitly_automatic.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n[@@@js.implem [@@@warning \"-22\"]]\n\nmodule M : sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val prop_get_arg: t -> int [@@js]\n  val prop_get: unit -> int [@@js]\n  val set_prop: t -> int -> unit [@@js]\n  val set_global: int -> unit [@@js]\n  val new_thing_unit: unit -> t [@@js]\n  val new_thing_args: int -> t [@@js]\n  val method_call_global: t -> unit [@@js]\n  val method_call_unit: t -> unit -> int [@@js]\n  val method_call_args: t -> int -> int [@@js]\n  val method_call_unit_unit: t -> unit -> unit [@@js]\n  val method_call_args_unit: t -> int -> unit [@@js]\n  val global: t [@@js]\n\n  [@@@warning \"-32\"]\n  val get: t -> int -> string option [@@js]\n  val set: t -> int -> string -> unit [@@js]\n  val get: t -> string -> string option [@@js]\n  val set: t -> string -> string -> unit [@@js]\n  [@@@warning \"+32\"]\n  val get: t -> Ojs.t -> string option [@@js]\n  val set: t -> Ojs.t -> string -> unit [@@js]\nend"
  },
  {
    "path": "ppx-test/binding_manual.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\nmodule M : sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val prop_get_arg: t -> int [@@js.get \"propGetArg\"]\n  val prop_get: unit -> int [@@js.get \"propGet\"]\n  val set_prop: t -> int -> unit [@@js.set \"prop\"]\n  val set_global: int -> unit [@@js.set \"global\"]\n  val new_thing_unit: unit -> t [@@js.new \"ThingUnit\"]\n  val new_thing_args: int -> t [@@js.new \"ThingArgs\"]\n  val method_call_global: t -> unit [@@js.call \"methodCallGlobal\"]\n  val method_call_unit: t -> unit -> int [@@js.call \"methodCallUnit\"]\n  val method_call_args: t -> int -> int[@@js.call \"methodCallArgs\"]\n  val method_call_unit_unit: t -> unit -> unit[@@js.call \"methodCallUnitUnit\"]\n  val method_call_args_unit: t -> int -> unit[@@js.call \"methodCallArgsUnit\"]\n  val global: t[@@js.global \"global\"]\n\n  [@@@warning \"-32\"]\n  val get: t -> int -> string option [@@js.index_get]\n  val set: t -> int -> string -> unit [@@js.index_set]\n  val get: t -> string -> string option [@@js.index_get]\n  val set: t -> string -> string -> unit [@@js.index_set]\n  [@@@warning \"+32\"]\n  val get: t -> Ojs.t -> string option [@@js.index_get]\n  val set: t -> Ojs.t -> string -> unit [@@js.index_set]\nend"
  },
  {
    "path": "ppx-test/dune",
    "content": "(rule\n (targets extension.ml.result)\n (deps extension.ml)\n (action\n  (run ppx/main.exe --impl %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/extension.ml extension.ml.result)))\n\n(rule\n (targets issues.ml.result)\n (deps issues.ml)\n (action\n  (run ppx/main.exe --impl %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (enabled_if\n  (>= %{ocaml_version} 4.09))\n (action\n  (diff expected/issues.ml issues.ml.result)))\n\n(rule\n (targets types.ml.result)\n (deps types.ml)\n (action\n  (run ppx/main.exe --impl %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (enabled_if\n  (>= %{ocaml_version} 4.09))\n (action\n  (diff expected/types.ml types.ml.result)))\n\n(rule\n (targets binding_automatic.ml)\n (deps binding_automatic.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/binding_automatic.ml binding_automatic.ml)))\n\n(rule\n (targets binding_explicitly_automatic.ml)\n (deps binding_explicitly_automatic.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff binding_automatic.ml binding_explicitly_automatic.ml)))\n\n(rule\n (targets binding_manual.ml)\n (deps binding_manual.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (targets binding.ml)\n (deps binding.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/binding.ml binding.ml)))\n\n(rule\n (targets scoped.ml)\n (deps scoped.mli)\n (action\n  (run %{bin:gen_js_api} %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/scoped.ml scoped.ml)))\n\n(rule\n (targets union_and_enum.ml)\n (deps union_and_enum.mli)\n (action\n  (run %{bin:gen_js_api} %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (action\n  (diff expected/union_and_enum.ml union_and_enum.ml)))\n\n(rule\n (targets issues_mli.ml)\n (deps issues_mli.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/issues_mli.ml issues_mli.ml)))\n\n(rule\n (targets recursive_modules.ml)\n (deps recursive_modules.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/recursive_modules.ml recursive_modules.ml)))\n\n(rule\n (targets first_class_modules.ml)\n (deps first_class_modules.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/first_class_modules.ml first_class_modules.ml)))\n\n(library\n (name test_library)\n (libraries ojs)\n (preprocess\n  (pps gen_js_api.ppx))\n (modes byte)\n (modules\n  binding_automatic binding_explicitly_automatic binding_manual binding\n  extension first_class_modules issues_mli issues\n  recursive_modules scoped types union_and_enum))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (deps test_library.cma)\n (action\n  (echo \"Successfully compile test_library\")))\n\n(rule\n (targets modules.ml)\n (deps modules.mli)\n (action\n  (run gen_js_api %{deps} -o %{targets})))\n\n(rule\n (alias runtest)\n (package gen_js_api)\n (action\n  (diff expected/modules.ml modules.ml)))\n"
  },
  {
    "path": "ppx-test/expected/binding.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule M =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let cast : t -> string = fun (x3 : t) -> Ojs.string_of_js (t_to_js x3)\n    let prop_get_arg : t -> int =\n      fun (x4 : t) ->\n        Ojs.int_of_js (Ojs.get_prop_ascii (t_to_js x4) \"getter\")\n    let prop_get : unit -> int =\n      fun () -> Ojs.int_of_js (Ojs.get_prop_ascii Ojs.global \"getter\")\n    let global : t = t_of_js (Ojs.get_prop_ascii Ojs.global \"global\")\n    let global_arrow : int -> int =\n      fun (x5 : int) ->\n        Ojs.int_of_js (Ojs.call Ojs.global \"global\" [|(Ojs.int_to_js x5)|])\n    let prop_set : t -> int -> unit =\n      fun (x6 : t) (x7 : int) ->\n        Ojs.set_prop_ascii (t_to_js x6) \"setter\" (Ojs.int_to_js x7)\n    let prop_set_global : t -> unit =\n      fun (x8 : t) -> Ojs.set_prop_ascii Ojs.global \"setter\" (t_to_js x8)\n    let method_call_global : t -> int =\n      fun (x9 : t) -> Ojs.int_of_js (Ojs.call (t_to_js x9) \"method\" [||])\n    let method_call_global_unit : t -> unit =\n      fun (x10 : t) -> ignore (Ojs.call (t_to_js x10) \"method\" [||])\n    let method_call_unit : t -> unit -> int =\n      fun (x11 : t) () ->\n        Ojs.int_of_js (Ojs.call (t_to_js x11) \"method\" [||])\n    let method_call_args : t -> int -> int =\n      fun (x13 : t) (x12 : int) ->\n        Ojs.int_of_js\n          (Ojs.call (t_to_js x13) \"method\" [|(Ojs.int_to_js x12)|])\n    let method_call_unit_unit : t -> unit -> unit =\n      fun (x14 : t) () -> ignore (Ojs.call (t_to_js x14) \"method\" [||])\n    let method_call_args_unit : t -> int -> unit =\n      fun (x16 : t) (x15 : int) ->\n        ignore (Ojs.call (t_to_js x16) \"method\" [|(Ojs.int_to_js x15)|])\n    let new_thing : int -> t =\n      fun (x17 : int) ->\n        t_of_js\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Thing\")\n             [|(Ojs.int_to_js x17)|])\n    let builder : ?x:int -> int -> z:int -> t =\n      fun ?x:(x18 : int option) (x19 : int) ~z:(x20 : int) ->\n        let x21 = Ojs.empty_obj () in\n        (match x18 with\n         | Some x22 -> Ojs.set_prop_ascii x21 \"x\" (Ojs.int_to_js x22)\n         | None -> ());\n        Ojs.set_prop_ascii x21 \"y\" (Ojs.int_to_js x19);\n        Ojs.set_prop_ascii x21 \"z\" (Ojs.int_to_js x20);\n        t_of_js x21\n    let index_get_int : t -> int -> string option =\n      fun (x23 : t) (x24 : int) ->\n        Ojs.option_of_js Ojs.string_of_js (Ojs.array_get (t_to_js x23) x24)\n    let index_get_string : t -> string -> string option =\n      fun (x26 : t) (x27 : string) ->\n        Ojs.option_of_js Ojs.string_of_js\n          (Ojs.get_prop (t_to_js x26) (Ojs.string_to_js x27))\n    let index_get_generic : t -> Ojs.t -> string option =\n      fun (x29 : t) (x30 : Ojs.t) ->\n        Ojs.option_of_js Ojs.string_of_js (Ojs.get_prop (t_to_js x29) x30)\n    let index_set_int : t -> int -> string -> unit =\n      fun (x32 : t) (x33 : int) (x34 : string) ->\n        Ojs.array_set (t_to_js x32) x33 (Ojs.string_to_js x34)\n    let index_set_string : t -> string -> string -> unit =\n      fun (x35 : t) (x36 : string) (x37 : string) ->\n        Ojs.set_prop (t_to_js x35) (Ojs.string_to_js x36)\n          (Ojs.string_to_js x37)\n    let index_set_generic : t -> Ojs.t -> string -> unit =\n      fun (x38 : t) (x39 : Ojs.t) (x40 : string) ->\n        Ojs.set_prop (t_to_js x38) x39 (Ojs.string_to_js x40)\n  end\n"
  },
  {
    "path": "ppx-test/expected/binding_automatic.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\n[@@@warning \"-22\"]\nmodule M =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let prop_get_arg : t -> int =\n      ((fun (x3 : t) ->\n          Ojs.int_of_js (Ojs.get_prop_ascii (t_to_js x3) \"propGetArg\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.get' attribute.\"])\n    let prop_get : unit -> int =\n      ((fun () -> Ojs.int_of_js (Ojs.get_prop_ascii Ojs.global \"propGet\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.get' attribute.\"])\n    let set_prop : t -> int -> unit =\n      ((fun (x4 : t) (x5 : int) ->\n          Ojs.set_prop_ascii (t_to_js x4) \"prop\" (Ojs.int_to_js x5))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.set' attribute.\"])\n    let set_global : int -> unit =\n      ((fun (x6 : int) ->\n          Ojs.set_prop_ascii Ojs.global \"global\" (Ojs.int_to_js x6))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.set' attribute.\"])\n    let new_thing_unit : unit -> t =\n      ((fun () ->\n          t_of_js\n            (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"ThingUnit\") [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.new' attribute.\"])\n    let new_thing_args : int -> t =\n      ((fun (x7 : int) ->\n          t_of_js\n            (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"ThingArgs\")\n               [|(Ojs.int_to_js x7)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.new' attribute.\"])\n    let method_call_global : t -> unit =\n      ((fun (x8 : t) ->\n          ignore (Ojs.call (t_to_js x8) \"methodCallGlobal\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_unit : t -> unit -> int =\n      ((fun (x9 : t) () ->\n          Ojs.int_of_js (Ojs.call (t_to_js x9) \"methodCallUnit\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_args : t -> int -> int =\n      ((fun (x11 : t) (x10 : int) ->\n          Ojs.int_of_js\n            (Ojs.call (t_to_js x11) \"methodCallArgs\" [|(Ojs.int_to_js x10)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_unit_unit : t -> unit -> unit =\n      ((fun (x12 : t) () ->\n          ignore (Ojs.call (t_to_js x12) \"methodCallUnitUnit\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_args_unit : t -> int -> unit =\n      ((fun (x14 : t) (x13 : int) ->\n          ignore\n            (Ojs.call (t_to_js x14) \"methodCallArgsUnit\"\n               [|(Ojs.int_to_js x13)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let global : t = ((t_of_js (Ojs.get_prop_ascii Ojs.global \"global\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.global' attribute.\"])\n    let get : t -> int -> string option =\n      ((fun (x15 : t) (x16 : int) ->\n          Ojs.option_of_js Ojs.string_of_js (Ojs.array_get (t_to_js x15) x16))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_get' attribute.\"])\n    let set : t -> int -> string -> unit =\n      ((fun (x18 : t) (x19 : int) (x20 : string) ->\n          Ojs.array_set (t_to_js x18) x19 (Ojs.string_to_js x20))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_set' attribute.\"])\n    let get : t -> string -> string option =\n      ((fun (x21 : t) (x22 : string) ->\n          Ojs.option_of_js Ojs.string_of_js\n            (Ojs.get_prop (t_to_js x21) (Ojs.string_to_js x22)))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_get' attribute.\"])\n    let set : t -> string -> string -> unit =\n      ((fun (x24 : t) (x25 : string) (x26 : string) ->\n          Ojs.set_prop (t_to_js x24) (Ojs.string_to_js x25)\n            (Ojs.string_to_js x26))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_set' attribute.\"])\n    let get : t -> Ojs.t -> string option =\n      ((fun (x27 : t) (x28 : Ojs.t) ->\n          Ojs.option_of_js Ojs.string_of_js (Ojs.get_prop (t_to_js x27) x28))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_get' attribute.\"])\n    let set : t -> Ojs.t -> string -> unit =\n      ((fun (x30 : t) (x31 : Ojs.t) (x32 : string) ->\n          Ojs.set_prop (t_to_js x30) x31 (Ojs.string_to_js x32))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.index_set' attribute.\"])\n  end\n"
  },
  {
    "path": "ppx-test/expected/extension.ml",
    "content": "let _ = Ojs.int_to_js\nlet _ =\n  fun (x2 : int -> int) ->\n    Ojs.fun_to_js 1\n      (fun (x3 : Ojs.t) -> Ojs.int_to_js (x2 (Ojs.int_of_js x3)))\n"
  },
  {
    "path": "ppx-test/expected/first_class_modules.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule Console =\n  struct\n    let log : (module Ojs.T with type t = 'a) -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x1 : a) ->\n          ignore\n            (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n               [|(A.t_to_js x1)|])\n    let log2 :\n      (module Ojs.T with type t = 'a) ->\n        (module Ojs.T with type t = 'b) -> 'a -> 'b -> unit\n      =\n      fun (type a) ->\n        fun (type b) ->\n          fun ((module A)  : (module Ojs.T with type t = a))\n            ((module B)  : (module Ojs.T with type t = b)) (x2 : a) (x3 : b)\n            ->\n            ignore\n              (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n                 [|(A.t_to_js x2);(B.t_to_js x3)|])\n    let log3 :\n      (module Ojs.T with type t = 'a) ->\n        (module Ojs.T with type t = 'b) ->\n          (module Ojs.T with type t = 'c) -> 'a -> 'b -> 'c -> unit\n      =\n      fun (type a) ->\n        fun (type b) ->\n          fun (type c) ->\n            fun ((module A)  : (module Ojs.T with type t = a))\n              ((module B)  : (module Ojs.T with type t = b))\n              ((module C)  : (module Ojs.T with type t = c)) (x4 : a)\n              (x5 : b) (x6 : c) ->\n              ignore\n                (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n                   [|(A.t_to_js x4);(B.t_to_js x5);(C.t_to_js x6)|])\n  end\nmodule Console2 =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x8 : Ojs.t) -> x8\n    and t_to_js : t -> Ojs.t = fun (x7 : Ojs.t) -> x7\n    let log : (module Ojs.T with type t = 'a) -> t -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x10 : t) \n          (x9 : a) ->\n          ignore (Ojs.call (t_to_js x10) \"log\" [|(A.t_to_js x9)|])\n    let log2 :\n      (module Ojs.T with type t = 'a) ->\n        (module Ojs.T with type t = 'b) -> t -> 'a -> 'b -> unit\n      =\n      fun (type a) ->\n        fun (type b) ->\n          fun ((module A)  : (module Ojs.T with type t = a))\n            ((module B)  : (module Ojs.T with type t = b)) (x13 : t)\n            (x11 : a) (x12 : b) ->\n            ignore\n              (Ojs.call (t_to_js x13) \"log\"\n                 [|(A.t_to_js x11);(B.t_to_js x12)|])\n    let log3 :\n      (module Ojs.T with type t = 'a) ->\n        (module Ojs.T with type t = 'b) ->\n          (module Ojs.T with type t = 'c) -> t -> 'a -> 'b -> 'c -> unit\n      =\n      fun (type a) ->\n        fun (type b) ->\n          fun (type c) ->\n            fun ((module A)  : (module Ojs.T with type t = a))\n              ((module B)  : (module Ojs.T with type t = b))\n              ((module C)  : (module Ojs.T with type t = c)) (x17 : t)\n              (x14 : a) (x15 : b) (x16 : c) ->\n              ignore\n                (Ojs.call (t_to_js x17) \"log\"\n                   [|(A.t_to_js x14);(B.t_to_js x15);(C.t_to_js x16)|])\n  end\nmodule Console3 =\n  struct\n    module Log =\n      struct\n        let _1 : (module Ojs.T with type t = 'a) -> 'a -> unit =\n          fun (type a) ->\n            fun ((module A)  : (module Ojs.T with type t = a)) (x18 : a) ->\n              Ojs.unit_of_js\n                (Ojs.apply\n                   (Ojs.get_prop_ascii\n                      (Ojs.get_prop_ascii Ojs.global \"console\") \"log\")\n                   [|(A.t_to_js x18)|])\n        let _2 :\n          (module Ojs.T with type t = 'a) ->\n            (module Ojs.T with type t = 'b) -> 'a -> 'b -> unit\n          =\n          fun (type a) ->\n            fun (type b) ->\n              fun ((module A)  : (module Ojs.T with type t = a))\n                ((module B)  : (module Ojs.T with type t = b)) (x19 : a)\n                (x20 : b) ->\n                Ojs.unit_of_js\n                  (Ojs.apply\n                     (Ojs.get_prop_ascii\n                        (Ojs.get_prop_ascii Ojs.global \"console\") \"log\")\n                     [|(A.t_to_js x19);(B.t_to_js x20)|])\n        let _3 :\n          (module Ojs.T with type t = 'a) ->\n            (module Ojs.T with type t = 'b) ->\n              (module Ojs.T with type t = 'c) -> 'a -> 'b -> 'c -> unit\n          =\n          fun (type a) ->\n            fun (type b) ->\n              fun (type c) ->\n                fun ((module A)  : (module Ojs.T with type t = a))\n                  ((module B)  : (module Ojs.T with type t = b))\n                  ((module C)  : (module Ojs.T with type t = c)) (x21 : a)\n                  (x22 : b) (x23 : c) ->\n                  Ojs.unit_of_js\n                    (Ojs.apply\n                       (Ojs.get_prop_ascii\n                          (Ojs.get_prop_ascii Ojs.global \"console\") \"log\")\n                       [|(A.t_to_js x21);(B.t_to_js x22);(C.t_to_js x23)|])\n      end\n  end\nmodule Array =\n  struct\n    type 'a t = Ojs.t\n    let rec t_of_js : 'a . (Ojs.t -> 'a) -> Ojs.t -> 'a t =\n      fun (type __a) (__a_of_js : Ojs.t -> __a) -> fun (x25 : Ojs.t) -> x25\n    and t_to_js : 'a . ('a -> Ojs.t) -> 'a t -> Ojs.t =\n      fun (type __a) (__a_to_js : __a -> Ojs.t) -> fun (x24 : Ojs.t) -> x24\n    let create : (module Ojs.T with type t = 'a) -> 'a list -> 'a t =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x26 : a list) ->\n          t_of_js A.t_of_js\n            (Ojs.new_obj_arr (Ojs.get_prop_ascii Ojs.global \"Array\")\n               (let x27 =\n                  Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\") [||] in\n                List.iter\n                  (fun (x28 : a) ->\n                     ignore (Ojs.call x27 \"push\" [|(A.t_to_js x28)|])) x26;\n                x27))\n    let create' : (module Ojs.T with type t = 'a) -> 'a list -> 'a t =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x30 : a list) ->\n          t_of_js A.t_of_js\n            (Ojs.call (Ojs.get_prop_ascii Ojs.global \"Array\") \"apply\"\n               [|Ojs.null;((let x31 =\n                              Ojs.new_obj\n                                (Ojs.get_prop_ascii Ojs.global \"Array\") \n                                [||] in\n                            List.iter\n                              (fun (x32 : a) ->\n                                 ignore\n                                   (Ojs.call x31 \"push\" [|(A.t_to_js x32)|]))\n                              x30;\n                            x31))|])\n    let push : (module Ojs.T with type t = 'a) -> 'a t -> 'a -> unit =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x35 : a t)\n          (x34 : a) ->\n          ignore\n            (Ojs.call (t_to_js A.t_to_js x35) \"push\" [|(A.t_to_js x34)|])\n    let pop : (module Ojs.T with type t = 'a) -> 'a t -> 'a option =\n      fun (type a) ->\n        fun ((module A)  : (module Ojs.T with type t = a)) (x37 : a t) ->\n          Ojs.option_of_js A.t_of_js\n            (Ojs.call (t_to_js A.t_to_js x37) \"pop\" [||])\n  end\n"
  },
  {
    "path": "ppx-test/expected/issues.ml",
    "content": "module Issue116 : sig type t end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type t = Ojs.t\n      let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n      and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    end)[@merlin.hide ]) \nmodule Issue117 :\n  sig module T : sig val log : 'a -> unit val log2 : 'a -> 'b -> unit end end\n  =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      module T =\n        struct\n          let log : 'a -> unit =\n            fun (x3 : 'a) ->\n              ignore\n                (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"log\"\n                   [|(Obj.magic x3)|])\n          let log2 : 'a -> 'b -> unit =\n            fun (x4 : 'a) (x5 : 'b) ->\n              ignore\n                (Ojs.call (Ojs.get_prop_ascii Ojs.global \"console\") \"jsLog2\"\n                   [|(Obj.magic x4);(Obj.magic x5)|])\n        end\n    end)[@merlin.hide ]) \nmodule Issue124 :\n  sig\n    type a\n    and b = {\n      a: a }\n    type 'a dummy\n    type 'a wrapped =\n      | Wrapped of 'a \n    type u =\n      | Unknown of Ojs.t \n      | T of t \n      | WrappedT of t wrapped \n    and t = [ `U of u ] dummy\n    type ('a, 'b) base = [ `BaseA of 'a  | `BaseB of 'b ] dummy\n    and base1 = (int, string) base\n    and base2 = (string, int) base\n  end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type a = Ojs.t\n      and b = {\n        a: a }\n      let rec a_of_js : Ojs.t -> a = fun (x7 : Ojs.t) -> x7\n      and a_to_js : a -> Ojs.t = fun (x6 : Ojs.t) -> x6\n      and b_of_js : Ojs.t -> b = fun js -> { a = (a_of_js js) }\n      and b_to_js : b -> Ojs.t = fun { a } -> a_to_js a\n      type 'a dummy = Ojs.t\n      let rec dummy_of_js : 'a . (Ojs.t -> 'a) -> Ojs.t -> 'a dummy =\n        fun (type __a) (__a_of_js : Ojs.t -> __a) -> fun (x9 : Ojs.t) -> x9\n      and dummy_to_js : 'a . ('a -> Ojs.t) -> 'a dummy -> Ojs.t =\n        fun (type __a) (__a_to_js : __a -> Ojs.t) -> fun (x8 : Ojs.t) -> x8\n      type 'a wrapped =\n        | Wrapped of 'a \n      let rec wrapped_of_js : 'a . (Ojs.t -> 'a) -> Ojs.t -> 'a wrapped =\n        let f a_of_js x = Wrapped (a_of_js x) in f\n      and wrapped_to_js : 'a . ('a -> Ojs.t) -> 'a wrapped -> Ojs.t =\n        let f a_to_js = function | Wrapped a -> a_to_js a in f\n      type u =\n        | Unknown of Ojs.t \n        | T of t \n        | WrappedT of t wrapped \n      and t = [ `U of u ] dummy\n      let rec u_of_js : Ojs.t -> u =\n        fun (x15 : Ojs.t) ->\n          let x16 = x15 in\n          match Ojs.type_of (Ojs.get_prop_ascii x16 \"type\") with\n          | \"number\" -> Unknown x16\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x16 \"type\") with\n               | \"t\" -> T (t_of_js x16)\n               | \"wrapped_t\" -> WrappedT (wrapped_of_js t_of_js x16)\n               | _ -> Unknown x16)\n          | \"boolean\" -> Unknown x16\n          | _ -> Unknown x16\n      and u_to_js : u -> Ojs.t =\n        fun (x10 : u) ->\n          match x10 with\n          | Unknown x11 -> x11\n          | T x12 -> t_to_js x12\n          | WrappedT x13 -> wrapped_to_js t_to_js x13\n      and t_of_js : Ojs.t -> t = Obj.magic\n      and t_to_js : t -> Ojs.t = Obj.magic\n      type ('a, 'b) base = [ `BaseA of 'a  | `BaseB of 'b ] dummy\n      and base1 = (int, string) base\n      and base2 = (string, int) base\n      let rec base_of_js :\n        'a 'b . (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> Ojs.t -> ('a, 'b) base =\n        fun _ _ -> Obj.magic\n      and base_to_js :\n        'a 'b . ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('a, 'b) base -> Ojs.t =\n        fun _ _ -> Obj.magic\n      and base1_of_js : Ojs.t -> base1 =\n        fun (x21 : Ojs.t) -> base_of_js Ojs.int_of_js Ojs.string_of_js x21\n      and base1_to_js : base1 -> Ojs.t =\n        fun (x18 : (int, string) base) ->\n          base_to_js Ojs.int_to_js Ojs.string_to_js x18\n      and base2_of_js : Ojs.t -> base2 =\n        fun (x27 : Ojs.t) -> base_of_js Ojs.string_of_js Ojs.int_of_js x27\n      and base2_to_js : base2 -> Ojs.t =\n        fun (x24 : (string, int) base) ->\n          base_to_js Ojs.string_to_js Ojs.int_to_js x24\n    end)[@merlin.hide ]) \nmodule Issue109 : sig type t = [ `S of string  | `I of int ] end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type t = [ `S of string  | `I of int ]\n      let rec t_of_js : Ojs.t -> t =\n        fun (x35 : Ojs.t) ->\n          let x36 = x35 in\n          match Ojs.type_of x36 with\n          | \"number\" -> (match Ojs.int_of_js x36 with | x38 -> `I x38)\n          | \"string\" -> (match Ojs.string_of_js x36 with | x37 -> `S x37)\n          | _ -> assert false\n      and t_to_js : t -> Ojs.t =\n        fun (x32 : [ `S of string  | `I of int ]) ->\n          match x32 with\n          | `S x33 -> Ojs.string_to_js x33\n          | `I x34 -> Ojs.int_to_js x34\n    end)[@merlin.hide ]) \nmodule Issue142 : sig type t = [ `Foo ]\n                      and u = t end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type t = [ `Foo ]\n      and u = t\n      let rec t_of_js : Ojs.t -> t =\n        fun (x40 : Ojs.t) ->\n          let x41 = x40 in\n          match Ojs.int_of_js x41 with | 42 -> `Foo | _ -> assert false\n      and t_to_js : t -> Ojs.t =\n        fun (x39 : [ `Foo ]) -> match x39 with | `Foo -> Ojs.int_to_js 42\n      and u_of_js : Ojs.t -> u = fun (x43 : Ojs.t) -> t_of_js x43\n      and u_to_js : u -> Ojs.t = fun (x42 : t) -> t_to_js x42\n    end)[@merlin.hide ]) \nmodule Issue144 : sig type t val f : t -> args:int -> int end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type t = Ojs.t\n      let rec t_of_js : Ojs.t -> t = fun (x45 : Ojs.t) -> x45\n      and t_to_js : t -> Ojs.t = fun (x44 : Ojs.t) -> x44\n      let f : t -> args:int -> int =\n        fun (x46 : t) ~args:(x47 : int) ->\n          Ojs.int_of_js\n            (Ojs.apply (Ojs.call (t_to_js x46) \"f\" [||])\n               [|(Ojs.int_to_js x47)|])\n    end)[@merlin.hide ]) \nmodule Issue146 : sig val f : ?arg:[ `Foo ] -> unit -> int end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      let f : ?arg:[ `Foo ] -> unit -> int =\n        fun ?arg:(x48 : [ `Foo ] option) () ->\n          Ojs.int_of_js\n            (let x51 = Ojs.global in\n             Ojs.call (Ojs.get_prop_ascii x51 \"f\") \"apply\"\n               [|x51;((let x49 =\n                         Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                           [||] in\n                       (match x48 with\n                        | Some x50 ->\n                            ignore\n                              (Ojs.call x49 \"push\"\n                                 [|((match x50 with\n                                     | `Foo -> Ojs.int_to_js 42))|])\n                        | None -> ());\n                       x49))|])\n    end)[@merlin.hide ]) \nmodule PR165 :\n  sig\n    module Markdown : sig type t end\n    module ParameterInformation :\n    sig\n      type t\n      val create :\n        label:[ `String of string  | `Tuple of (int * int) ] ->\n          ?documentation:[ `String of string  | `Markdown of Markdown.t ] ->\n            unit -> t\n    end\n  end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      module Markdown =\n        struct\n          type t = Ojs.t\n          let rec t_of_js : Ojs.t -> t = fun (x53 : Ojs.t) -> x53\n          and t_to_js : t -> Ojs.t = fun (x52 : Ojs.t) -> x52\n        end\n      module ParameterInformation =\n        struct\n          type t = Ojs.t\n          let rec t_of_js : Ojs.t -> t = fun (x55 : Ojs.t) -> x55\n          and t_to_js : t -> Ojs.t = fun (x54 : Ojs.t) -> x54\n          let create :\n            label:[ `String of string  | `Tuple of (int * int) ] ->\n              ?documentation:[ `String of string  | `Markdown of Markdown.t ]\n                -> unit -> t\n            =\n            fun ~label:(x56 : [ `String of string  | `Tuple of (int * int) ])\n              ?documentation:(x57 :\n                               [ `String of string \n                               | `Markdown of Markdown.t ] option)\n              () ->\n              t_of_js\n                (Ojs.new_obj_arr\n                   (Ojs.get_prop_ascii Ojs.global \"ParameterInformation\")\n                   (let x58 =\n                      Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                        [||] in\n                    ignore\n                      (Ojs.call x58 \"push\"\n                         [|((match x56 with\n                             | `String x62 -> Ojs.string_to_js x62\n                             | `Tuple x63 ->\n                                 let (x64, x65) = x63 in\n                                 let x66 = Ojs.array_make 2 in\n                                 (Ojs.array_set x66 0 (Ojs.int_to_js x64);\n                                  Ojs.array_set x66 1 (Ojs.int_to_js x65);\n                                  x66)))|]);\n                    (match x57 with\n                     | Some x59 ->\n                         ignore\n                           (Ojs.call x58 \"push\"\n                              [|((match x59 with\n                                  | `String x60 -> Ojs.string_to_js x60\n                                  | `Markdown x61 -> Markdown.t_to_js x61))|])\n                     | None -> ());\n                    x58))\n        end\n    end)[@merlin.hide ]) \n"
  },
  {
    "path": "ppx-test/expected/issues_mli.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule Issue144 =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let f : t -> args:int -> int =\n      fun (x3 : t) ~args:(x4 : int) ->\n        Ojs.int_of_js\n          (Ojs.apply (Ojs.call (t_to_js x3) \"f\" [||]) [|(Ojs.int_to_js x4)|])\n  end\n"
  },
  {
    "path": "ppx-test/expected/modules.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule Event =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n  end\nmodule Foo =\n  struct\n    module E = Event\n    let foo : E.t -> string -> unit =\n      fun (x4 : E.t) (x3 : string) ->\n        ignore (Ojs.call (E.t_to_js x4) \"foo\" [|(Ojs.string_to_js x3)|])\n  end\nmodule Bar =\n  struct\n    include Event\n    let bar : t -> string -> unit =\n      fun (x6 : t) (x5 : string) ->\n        ignore (Ojs.call (t_to_js x6) \"bar\" [|(Ojs.string_to_js x5)|])\n  end\n"
  },
  {
    "path": "ppx-test/expected/recursive_modules.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\nmodule rec\n  Foo:sig\n        type t = private Ojs.t\n        val t_of_js : Ojs.t -> t\n        val t_to_js : t -> Ojs.t\n        val create : string -> t\n        val describe : t -> string\n        val to_bar : t -> Bar.t\n      end =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let create : string -> t =\n      fun (x3 : string) ->\n        t_of_js\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Foo\")\n             [|(Ojs.string_to_js x3)|])\n    let describe : t -> string =\n      fun (x4 : t) ->\n        Ojs.string_of_js (Ojs.call (t_to_js x4) \"describe\" [||])\n    let to_bar : t -> Bar.t =\n      fun (x5 : t) -> Bar.t_of_js (Ojs.call (t_to_js x5) \"toBar\" [||])\n  end\n and\n  Bar:sig\n        type t = private Ojs.t\n        val t_of_js : Ojs.t -> t\n        val t_to_js : t -> Ojs.t\n        val create : string -> t\n        val describe : t -> string\n        val to_foo : t -> Foo.t\n      end =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x7 : Ojs.t) -> x7\n    and t_to_js : t -> Ojs.t = fun (x6 : Ojs.t) -> x6\n    let create : string -> t =\n      fun (x8 : string) ->\n        t_of_js\n          (Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Bar\")\n             [|(Ojs.string_to_js x8)|])\n    let describe : t -> string =\n      fun (x9 : t) ->\n        Ojs.string_of_js (Ojs.call (t_to_js x9) \"describe\" [||])\n    let to_foo : t -> Foo.t =\n      fun (x10 : t) -> Foo.t_of_js (Ojs.call (t_to_js x10) \"toFoo\" [||])\n  end\n"
  },
  {
    "path": "ppx-test/expected/scoped.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\n[@@@warning \"-22\"]\nmodule M =\n  struct\n    type t = Ojs.t\n    let rec t_of_js : Ojs.t -> t = fun (x2 : Ojs.t) -> x2\n    and t_to_js : t -> Ojs.t = fun (x1 : Ojs.t) -> x1\n    let prop_get_arg : t -> int =\n      ((fun (x3 : t) ->\n          Ojs.int_of_js (Ojs.get_prop_ascii (t_to_js x3) \"propGetArg\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.get' attribute.\"])\n    let prop_get : unit -> int =\n      ((fun () ->\n          Ojs.int_of_js\n            (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"scope\")\n               \"propGet\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.get' attribute.\"])\n    let set_prop : t -> int -> unit =\n      ((fun (x4 : t) (x5 : int) ->\n          Ojs.set_prop_ascii (t_to_js x4) \"prop\" (Ojs.int_to_js x5))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.set' attribute.\"])\n    let set_global : int -> unit =\n      ((fun (x6 : int) ->\n          Ojs.set_prop_ascii (Ojs.get_prop_ascii Ojs.global \"scope\") \"global\"\n            (Ojs.int_to_js x6))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.set' attribute.\"])\n    let new_thing_unit : unit -> t =\n      ((fun () ->\n          t_of_js\n            (Ojs.new_obj\n               (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"scope\")\n                  \"ThingUnit\") [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.new' attribute.\"])\n    let new_thing_args : int -> t =\n      ((fun (x7 : int) ->\n          t_of_js\n            (Ojs.new_obj\n               (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"scope\")\n                  \"ThingArgs\") [|(Ojs.int_to_js x7)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.new' attribute.\"])\n    let method_call_global : t -> unit =\n      ((fun (x8 : t) ->\n          ignore (Ojs.call (t_to_js x8) \"methodCallGlobal\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_unit : t -> unit -> int =\n      ((fun (x9 : t) () ->\n          Ojs.int_of_js (Ojs.call (t_to_js x9) \"methodCallUnit\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_args : t -> int -> int =\n      ((fun (x11 : t) (x10 : int) ->\n          Ojs.int_of_js\n            (Ojs.call (t_to_js x11) \"methodCallArgs\" [|(Ojs.int_to_js x10)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_unit_unit : t -> unit -> unit =\n      ((fun (x12 : t) () ->\n          ignore (Ojs.call (t_to_js x12) \"methodCallUnitUnit\" [||]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let method_call_args_unit : t -> int -> unit =\n      ((fun (x14 : t) (x13 : int) ->\n          ignore\n            (Ojs.call (t_to_js x14) \"methodCallArgsUnit\"\n               [|(Ojs.int_to_js x13)|]))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.call' attribute.\"])\n    let global : t =\n      ((t_of_js\n          (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"scope\")\n             \"global\"))\n      [@ocaml.ppwarning\n        \"Heuristic for automatic binding is deprecated; please add the '@js.global' attribute.\"])\n    let invoke : unit -> unit =\n      fun () ->\n        Ojs.unit_of_js\n          (Ojs.apply (Ojs.get_prop_ascii Ojs.global \"scope\") [||])\n  end\nlet d : unit -> unit =\n  fun () ->\n    ignore\n      (Ojs.call\n         (Ojs.get_prop_ascii\n            (Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global \"a\") \"b\") \"c\")\n         \"d\" [||])\n"
  },
  {
    "path": "ppx-test/expected/types.ml",
    "content": "type 'a of_js = Ojs.t -> 'a\ntype 'a to_js = 'a -> Ojs.t\n[@@@ocaml.text \" JS-able types \"]\nlet _ : string of_js = Ojs.string_of_js\nlet _ : string to_js = Ojs.string_to_js\nlet _ : int of_js = Ojs.int_of_js\nlet _ : int to_js = Ojs.int_to_js\nlet _ : bool of_js = Ojs.bool_of_js\nlet _ : bool to_js = Ojs.bool_to_js\nlet _ : float of_js = Ojs.float_of_js\nlet _ : float to_js = Ojs.float_to_js\nlet _ : Ojs.t of_js = fun (x9 : Ojs.t) -> x9\nlet _ : Ojs.t to_js = fun (x10 : Ojs.t) -> x10\nlet _ : (string * int) of_js =\n  fun (x11 : Ojs.t) ->\n    let x12 = x11 in\n    ((Ojs.string_of_js (Ojs.array_get x12 0)),\n      (Ojs.int_of_js (Ojs.array_get x12 1)))\nlet _ : (string * int) to_js =\n  fun (x13 : (string * int)) ->\n    let (x14, x15) = x13 in\n    let x16 = Ojs.array_make 2 in\n    Ojs.array_set x16 0 (Ojs.string_to_js x14);\n    Ojs.array_set x16 1 (Ojs.int_to_js x15);\n    x16\nlet _ : (string * int * bool) of_js =\n  fun (x17 : Ojs.t) ->\n    let x18 = x17 in\n    ((Ojs.string_of_js (Ojs.array_get x18 0)),\n      (Ojs.int_of_js (Ojs.array_get x18 1)),\n      (Ojs.bool_of_js (Ojs.array_get x18 2)))\nlet _ : (string * int * bool) to_js =\n  fun (x19 : (string * int * bool)) ->\n    let (x20, x21, x22) = x19 in\n    let x23 = Ojs.array_make 3 in\n    Ojs.array_set x23 0 (Ojs.string_to_js x20);\n    Ojs.array_set x23 1 (Ojs.int_to_js x21);\n    Ojs.array_set x23 2 (Ojs.bool_to_js x22);\n    x23\nlet _ : (string -> int) of_js =\n  fun (x24 : Ojs.t) (x25 : string) ->\n    Ojs.int_of_js (Ojs.apply x24 [|(Ojs.string_to_js x25)|])\nlet _ : (string -> int) to_js =\n  fun (x26 : string -> int) ->\n    Ojs.fun_to_js 1\n      (fun (x27 : Ojs.t) -> Ojs.int_to_js (x26 (Ojs.string_of_js x27)))\nlet _ : ((string -> int) -> bool -> unit) of_js =\n  fun (x28 : Ojs.t) (x29 : string -> int) (x31 : bool) ->\n    ignore\n      (Ojs.apply x28\n         [|(Ojs.fun_to_js 1\n              (fun (x30 : Ojs.t) ->\n                 Ojs.int_to_js (x29 (Ojs.string_of_js x30))));(Ojs.bool_to_js\n                                                                 x31)|])\nlet _ : ((string -> int) -> bool -> unit) to_js =\n  fun (x32 : (string -> int) -> bool -> unit) ->\n    Ojs.fun_to_js 2\n      (fun (x33 : Ojs.t) (x35 : Ojs.t) ->\n         x32\n           (fun (x34 : string) ->\n              Ojs.int_of_js (Ojs.apply x33 [|(Ojs.string_to_js x34)|]))\n           (Ojs.bool_of_js x35))\nlet _ : string array of_js =\n  fun (x36 : Ojs.t) -> Ojs.array_of_js Ojs.string_of_js x36\nlet _ : string array to_js =\n  fun (x38 : string array) -> Ojs.array_to_js Ojs.string_to_js x38\nlet _ : string list of_js =\n  fun (x40 : Ojs.t) -> Ojs.list_of_js Ojs.string_of_js x40\nlet _ : string list to_js =\n  fun (x42 : string list) -> Ojs.list_to_js Ojs.string_to_js x42\nlet _ : string option of_js =\n  fun (x44 : Ojs.t) -> Ojs.option_of_js Ojs.string_of_js x44\nlet _ : string option to_js =\n  fun (x46 : string option) -> Ojs.option_to_js Ojs.string_to_js x46\nlet _ : (_ -> _) of_js =\n  fun (x48 : Ojs.t) (x49 : 'a) ->\n    Obj.magic (Ojs.apply x48 [|(Obj.magic x49)|])\nlet _ : (_ -> _) to_js =\n  fun (x50 : 'a -> 'b) ->\n    Ojs.fun_to_js 1 (fun (x51 : Ojs.t) -> Obj.magic (x50 (Obj.magic x51)))\nlet _ : [ `foo  | `bar  | `Baz  | `I of int  | `S of string ] of_js =\n  fun (x52 : Ojs.t) ->\n    let x53 = x52 in\n    match Ojs.type_of x53 with\n    | \"number\" -> (match Ojs.int_of_js x53 with | 42 -> `bar | x54 -> `I x54)\n    | \"string\" ->\n        (match Ojs.string_of_js x53 with\n         | \"foo\" -> `foo\n         | \"Baz\" -> `Baz\n         | x55 -> `S x55)\n    | _ -> assert false\nlet _ : [ `foo  | `bar  | `Baz  | `I of int  | `S of string ] to_js =\n  fun (x56 : [ `foo  | `bar  | `Baz  | `I of int  | `S of string ]) ->\n    match x56 with\n    | `foo -> Ojs.string_to_js \"foo\"\n    | `bar -> Ojs.int_to_js 42\n    | `Baz -> Ojs.string_to_js \"Baz\"\n    | `I x57 -> Ojs.int_to_js x57\n    | `S x58 -> Ojs.string_to_js x58\n[@@@ocaml.text \" Label & Options Value \"]\nlet _ : (label:int -> ?opt:int -> unit -> unit) of_js =\n  fun (x59 : Ojs.t) ~label:(x60 : int) ?opt:(x61 : int option) () ->\n    ignore\n      (Ojs.call x59 \"apply\"\n         [|Ojs.null;((let x62 =\n                        Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                          [||] in\n                      ignore (Ojs.call x62 \"push\" [|(Ojs.int_to_js x60)|]);\n                      (match x61 with\n                       | Some x63 ->\n                           ignore\n                             (Ojs.call x62 \"push\" [|(Ojs.int_to_js x63)|])\n                       | None -> ());\n                      x62))|])\nlet _ : (label:int -> ?opt:int -> unit -> unit) to_js =\n  fun (x64 : label:int -> ?opt:int -> unit -> unit) ->\n    Ojs.fun_to_js 2\n      (fun (x65 : Ojs.t) (x66 : Ojs.t) ->\n         x64 ~label:(Ojs.int_of_js x65)\n           ?opt:(Ojs.option_of_js Ojs.int_of_js x66) ())\nlet _ : (label:int -> ?opt:int -> unit -> unit) of_js =\n  fun (x68 : Ojs.t) ~label:(x69 : int) ?opt:(x70 : int option) () ->\n    ignore\n      (Ojs.call x68 \"apply\"\n         [|Ojs.null;((let x71 =\n                        Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                          [||] in\n                      ignore (Ojs.call x71 \"push\" [|(Ojs.int_to_js x69)|]);\n                      (match x70 with\n                       | Some x72 ->\n                           ignore\n                             (Ojs.call x71 \"push\" [|(Ojs.int_to_js x72)|])\n                       | None -> ());\n                      x71))|])\nlet _ : (label:int -> ?opt:int -> unit -> unit) to_js =\n  fun (x73 : label:int -> ?opt:int -> unit -> unit) ->\n    Ojs.fun_to_js 2\n      (fun (x74 : Ojs.t) (x75 : Ojs.t) ->\n         x73 ~label:(Ojs.int_of_js x74)\n           ?opt:(Ojs.option_of_js Ojs.int_of_js x75) ())\n[@@@ocaml.text \" Functions \"]\nmodule B :\n  sig\n    val default0 : ?x:int -> unit -> unit\n    val default1 : ?x:int -> unit -> unit\n    val builder0 : unit -> Ojs.t\n    val builder1 : x:int -> Ojs.t\n    val builder2 : ?x:int -> ?y:string -> unit -> Ojs.t\n    val builder3 : x:int -> y:string -> unit -> Ojs.t\n    val builder4 : x:int -> y:string -> z:unit -> Ojs.t\n    val builder5 : ?x:int -> ?y:string -> unit -> Ojs.t\n    val builder6 : ?x:int -> ?y:string -> ?z:int -> unit -> Ojs.t\n    val sep : string -> string list -> string\n  end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      let default0 : ?x:int -> unit -> unit =\n        fun ?x:(x77 : int option) () ->\n          ignore\n            (let x80 = Ojs.global in\n             Ojs.call (Ojs.get_prop_ascii x80 \"default0\") \"apply\"\n               [|x80;((let x78 =\n                         Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                           [||] in\n                       (match x77 with\n                        | Some x79 ->\n                            ignore\n                              (Ojs.call x78 \"push\" [|(Ojs.int_to_js x79)|])\n                        | None -> ());\n                       x78))|])\n      let default1 : ?x:int -> unit -> unit =\n        fun ?x:(x81 : int option) () ->\n          ignore\n            (Ojs.call Ojs.global \"default1\"\n               [|(Ojs.int_to_js\n                    (match x81 with | Some x82 -> x82 | None -> 42))|])\n      let builder0 : unit -> Ojs.t =\n        fun () -> let x83 = Ojs.empty_obj () in x83\n      let builder1 : x:int -> Ojs.t =\n        fun ~x:(x84 : int) ->\n          let x85 = Ojs.empty_obj () in\n          Ojs.set_prop_ascii x85 \"x\" (Ojs.int_to_js x84); x85\n      let builder2 : ?x:int -> ?y:string -> unit -> Ojs.t =\n        fun ?x:(x86 : int option) ?y:(x87 : string option) () ->\n          let x88 = Ojs.empty_obj () in\n          (match x86 with\n           | Some x90 -> Ojs.set_prop_ascii x88 \"x\" (Ojs.int_to_js x90)\n           | None -> ());\n          (match x87 with\n           | Some x89 -> Ojs.set_prop_ascii x88 \"y\" (Ojs.string_to_js x89)\n           | None -> ());\n          x88\n      let builder3 : x:int -> y:string -> unit -> Ojs.t =\n        fun ~x:(x91 : int) ~y:(x92 : string) () ->\n          let x93 = Ojs.empty_obj () in\n          Ojs.set_prop_ascii x93 \"x\" (Ojs.int_to_js x91);\n          Ojs.set_prop_ascii x93 \"y\" (Ojs.string_to_js x92);\n          x93\n      let builder4 : x:int -> y:string -> z:unit -> Ojs.t =\n        fun ~x:(x94 : int) ~y:(x95 : string) ~z:(x96 : unit) ->\n          let x97 = Ojs.empty_obj () in\n          Ojs.set_prop_ascii x97 \"x\" (Ojs.int_to_js x94);\n          Ojs.set_prop_ascii x97 \"y\" (Ojs.string_to_js x95);\n          Ojs.set_prop_ascii x97 \"z\" (Ojs.unit_to_js x96);\n          x97\n      let builder5 : ?x:int -> ?y:string -> unit -> Ojs.t =\n        fun ?x:(x98 : int option) ?y:(x99 : string option) () ->\n          let x100 = Ojs.empty_obj () in\n          (match x98 with\n           | Some x102 -> Ojs.set_prop_ascii x100 \"x\" (Ojs.int_to_js x102)\n           | None -> ());\n          (match x99 with\n           | Some x101 -> Ojs.set_prop_ascii x100 \"y\" (Ojs.string_to_js x101)\n           | None -> ());\n          x100\n      let builder6 : ?x:int -> ?y:string -> ?z:int -> unit -> Ojs.t =\n        fun ?x:(x103 : int option) ?y:(x104 : string option)\n          ?z:(x105 : int option) () ->\n          let x106 = Ojs.empty_obj () in\n          Ojs.set_prop_ascii x106 \"x\"\n            (Ojs.int_to_js (match x103 with | Some x109 -> x109 | None -> 42));\n          Ojs.set_prop_ascii x106 \"y\"\n            (Ojs.string_to_js\n               (match x104 with | Some x108 -> x108 | None -> \"42\"));\n          (match x105 with\n           | Some x107 -> Ojs.set_prop_ascii x106 \"z\" (Ojs.int_to_js x107)\n           | None -> ());\n          x106\n      let sep : string -> string list -> string =\n        fun (x110 : string) (x111 : string list) ->\n          Ojs.string_of_js\n            (let x114 = Ojs.global in\n             Ojs.call (Ojs.get_prop_ascii x114 \"sep\") \"apply\"\n               [|x114;((let x112 =\n                          Ojs.new_obj (Ojs.get_prop_ascii Ojs.global \"Array\")\n                            [||] in\n                        ignore\n                          (Ojs.call x112 \"push\" [|(Ojs.string_to_js x110)|]);\n                        List.iter\n                          (fun (x113 : string) ->\n                             ignore\n                               (Ojs.call x112 \"push\"\n                                  [|(Ojs.string_to_js x113)|])) x111;\n                        x112))|])\n    end)[@merlin.hide ]) \nmodule T :\n  sig\n    type js = private Ojs.t\n    type abstract\n    type alias = js\n    type private_alias = private alias\n    type record = {\n      x: js ;\n      y: js }\n    type mutable_record = {\n      mutable x: js ;\n      y: js }\n    type record_relabel = {\n      x: int ;\n      y: int }\n    type ('a, 'b) parametrized = {\n      x: 'a ;\n      y: 'b }\n    type 'a abs = ('a -> int) -> unit\n    type specialized = (int, int) parametrized\n    type enum =\n      | Foo \n      | Bar \n      | Baz \n      | Qux \n    type status =\n      | OK \n      | KO \n      | OO \n      | OtherS of string \n      | OtherI of int \n    type poly = [ `foo  | `bar  | `baz  | `Qux  | `I of int  | `S of string ]\n    type sum =\n      | A \n      | B of int \n      | C of int * string \n      | D of {\n      age: int ;\n      name: string } \n      | Unknown of Ojs.t \n    type t =\n      | A \n      | B of int \n      | C of int * string \n      | D of {\n      age: int ;\n      name: string } \n      | E of int \n      | Unknown of Ojs.t \n    type union =\n      | A \n      | B of int \n      | C of int \n      | D of Ojs.t \n    type poly_union = [ `A  | `B of int  | `C of int  | `D of Ojs.t ]\n    type discr_union =\n      | A \n      | B of int \n      | C of int \n      | D of Ojs.t \n    type discr_poly_union = [ `A  | `B of int  | `C of int  | `D of Ojs.t ]\n    type discr_union_value =\n      | A \n      | B of int \n      | C of int \n      | D of Ojs.t \n    module NestedScope0 : sig val f : string -> unit end\n    module NestedScope1 : sig val f : string -> unit end\n    module NestedScope2 : sig val f : string -> unit end\n  end =\n  ((struct\n      [@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n      [@@@ocaml.warning \"-7-32-39\"]\n      type js = Ojs.t\n      let rec js_of_js : Ojs.t -> js = fun (x116 : Ojs.t) -> x116\n      and js_to_js : js -> Ojs.t = fun (x115 : Ojs.t) -> x115\n      type abstract = Ojs.t\n      let rec abstract_of_js : Ojs.t -> abstract = fun (x118 : Ojs.t) -> x118\n      and abstract_to_js : abstract -> Ojs.t = fun (x117 : Ojs.t) -> x117\n      type alias = js\n      let rec alias_of_js : Ojs.t -> alias =\n        fun (x120 : Ojs.t) -> js_of_js x120\n      and alias_to_js : alias -> Ojs.t = fun (x119 : js) -> js_to_js x119\n      type private_alias = alias\n      let rec private_alias_of_js : Ojs.t -> private_alias =\n        fun (x122 : Ojs.t) -> alias_of_js x122\n      and private_alias_to_js : private_alias -> Ojs.t =\n        fun (x121 : alias) -> alias_to_js x121\n      type record = {\n        x: js ;\n        y: js }\n      let rec record_of_js : Ojs.t -> record =\n        fun (x124 : Ojs.t) ->\n          {\n            x = (js_of_js (Ojs.get_prop_ascii x124 \"x\"));\n            y = (js_of_js (Ojs.get_prop_ascii x124 \"y\"))\n          }\n      and record_to_js : record -> Ojs.t =\n        fun (x123 : record) ->\n          Ojs.obj [|(\"x\", (js_to_js x123.x));(\"y\", (js_to_js x123.y))|]\n      type mutable_record = {\n        mutable x: js ;\n        y: js }\n      let rec mutable_record_of_js : Ojs.t -> mutable_record =\n        fun (x126 : Ojs.t) ->\n          {\n            x = (js_of_js (Ojs.get_prop_ascii x126 \"x\"));\n            y = (js_of_js (Ojs.get_prop_ascii x126 \"y\"))\n          }\n      and mutable_record_to_js : mutable_record -> Ojs.t =\n        fun (x125 : mutable_record) ->\n          Ojs.obj [|(\"x\", (js_to_js x125.x));(\"y\", (js_to_js x125.y))|]\n      type record_relabel = {\n        x: int ;\n        y: int }\n      let rec record_relabel_of_js : Ojs.t -> record_relabel =\n        fun (x128 : Ojs.t) ->\n          {\n            x = (Ojs.int_of_js (Ojs.get_prop_ascii x128 \"x\"));\n            y = (Ojs.int_of_js (Ojs.get_prop_ascii x128 \"Y\"))\n          }\n      and record_relabel_to_js : record_relabel -> Ojs.t =\n        fun (x127 : record_relabel) ->\n          Ojs.obj\n            [|(\"x\", (Ojs.int_to_js x127.x));(\"Y\", (Ojs.int_to_js x127.y))|]\n      type ('a, 'b) parametrized = {\n        x: 'a ;\n        y: 'b }\n      let rec parametrized_of_js :\n        'a 'b .\n          (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> Ojs.t -> ('a, 'b) parametrized\n        =\n        fun (type __a) (type __b) (__a_of_js : Ojs.t -> __a)\n          (__b_of_js : Ojs.t -> __b) ->\n          fun (x130 : Ojs.t) ->\n            {\n              x = (__a_of_js (Ojs.get_prop_ascii x130 \"x\"));\n              y = (__b_of_js (Ojs.get_prop_ascii x130 \"y\"))\n            }\n      and parametrized_to_js :\n        'a 'b .\n          ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('a, 'b) parametrized -> Ojs.t\n        =\n        fun (type __a) (type __b) (__a_to_js : __a -> Ojs.t)\n          (__b_to_js : __b -> Ojs.t) ->\n          fun (x129 : (__a, __b) parametrized) ->\n            Ojs.obj [|(\"x\", (__a_to_js x129.x));(\"y\", (__b_to_js x129.y))|]\n      type 'a abs = ('a -> int) -> unit\n      let rec abs_of_js : 'a . (Ojs.t -> 'a) -> Ojs.t -> 'a abs =\n        fun (type __a) (__a_of_js : Ojs.t -> __a) ->\n          fun (x134 : Ojs.t) (x135 : __a -> int) ->\n            ignore\n              (Ojs.apply x134\n                 [|(Ojs.fun_to_js 1\n                      (fun (x136 : Ojs.t) ->\n                         Ojs.int_to_js (x135 (__a_of_js x136))))|])\n      and abs_to_js : 'a . ('a -> Ojs.t) -> 'a abs -> Ojs.t =\n        fun (type __a) (__a_to_js : __a -> Ojs.t) ->\n          fun (x131 : (__a -> int) -> unit) ->\n            Ojs.fun_to_js 1\n              (fun (x132 : Ojs.t) ->\n                 x131\n                   (fun (x133 : __a) ->\n                      Ojs.int_of_js (Ojs.apply x132 [|(__a_to_js x133)|])))\n      type specialized = (int, int) parametrized\n      let rec specialized_of_js : Ojs.t -> specialized =\n        fun (x140 : Ojs.t) ->\n          parametrized_of_js Ojs.int_of_js Ojs.int_of_js x140\n      and specialized_to_js : specialized -> Ojs.t =\n        fun (x137 : (int, int) parametrized) ->\n          parametrized_to_js Ojs.int_to_js Ojs.int_to_js x137\n      type enum =\n        | Foo \n        | Bar \n        | Baz \n        | Qux \n      let rec enum_of_js : Ojs.t -> enum =\n        fun (x144 : Ojs.t) ->\n          let x145 = x144 in\n          match Ojs.type_of x145 with\n          | \"number\" ->\n              (match Ojs.float_of_js x145 with\n               | 4.2 -> Baz\n               | _ ->\n                   (match Ojs.int_of_js x145 with\n                    | 42 -> Bar\n                    | _ -> assert false))\n          | \"string\" ->\n              (match Ojs.string_of_js x145 with\n               | \"foo\" -> Foo\n               | \"Qux\" -> Qux\n               | _ -> assert false)\n          | _ -> assert false\n      and enum_to_js : enum -> Ojs.t =\n        fun (x143 : enum) ->\n          match x143 with\n          | Foo -> Ojs.string_to_js \"foo\"\n          | Bar -> Ojs.int_to_js 42\n          | Baz -> Ojs.float_to_js 4.2\n          | Qux -> Ojs.string_to_js \"Qux\"\n      type status =\n        | OK \n        | KO \n        | OO \n        | OtherS of string \n        | OtherI of int \n      let rec status_of_js : Ojs.t -> status =\n        fun (x149 : Ojs.t) ->\n          let x150 = x149 in\n          match Ojs.type_of x150 with\n          | \"number\" ->\n              (match Ojs.float_of_js x150 with\n               | 1.5 -> OO\n               | _ ->\n                   (match Ojs.int_of_js x150 with\n                    | 1 -> OK\n                    | 2 -> KO\n                    | x152 -> OtherI x152))\n          | \"string\" ->\n              (match Ojs.string_of_js x150 with | x151 -> OtherS x151)\n          | _ -> assert false\n      and status_to_js : status -> Ojs.t =\n        fun (x146 : status) ->\n          match x146 with\n          | OK -> Ojs.int_to_js 1\n          | KO -> Ojs.int_to_js 2\n          | OO -> Ojs.float_to_js 1.5\n          | OtherS x147 -> Ojs.string_to_js x147\n          | OtherI x148 -> Ojs.int_to_js x148\n      type poly =\n        [ `foo  | `bar  | `baz  | `Qux  | `I of int  | `S of string ]\n      let rec poly_of_js : Ojs.t -> poly =\n        fun (x156 : Ojs.t) ->\n          let x157 = x156 in\n          match Ojs.type_of x157 with\n          | \"number\" ->\n              (match Ojs.float_of_js x157 with\n               | 4.2 -> `baz\n               | _ ->\n                   (match Ojs.int_of_js x157 with\n                    | 42 -> `bar\n                    | x158 -> `I x158))\n          | \"string\" ->\n              (match Ojs.string_of_js x157 with\n               | \"foo\" -> `foo\n               | \"Qux\" -> `Qux\n               | x159 -> `S x159)\n          | _ -> assert false\n      and poly_to_js : poly -> Ojs.t =\n        fun\n          (x153 :\n            [ `foo  | `bar  | `baz  | `Qux  | `I of int  | `S of string ])\n          ->\n          match x153 with\n          | `foo -> Ojs.string_to_js \"foo\"\n          | `bar -> Ojs.int_to_js 42\n          | `baz -> Ojs.float_to_js 4.2\n          | `Qux -> Ojs.string_to_js \"Qux\"\n          | `I x154 -> Ojs.int_to_js x154\n          | `S x155 -> Ojs.string_to_js x155\n      type sum =\n        | A \n        | B of int \n        | C of int * string \n        | D of {\n        age: int ;\n        name: string } \n        | Unknown of Ojs.t \n      let rec sum_of_js : Ojs.t -> sum =\n        fun (x167 : Ojs.t) ->\n          let x168 = x167 in\n          match Ojs.type_of (Ojs.get_prop_ascii x168 \"kind\") with\n          | \"number\" -> Unknown x168\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x168 \"kind\") with\n               | \"A\" -> A\n               | \"B\" -> B (Ojs.int_of_js (Ojs.get_prop_ascii x168 \"arg\"))\n               | \"C\" ->\n                   C\n                     ((Ojs.int_of_js\n                         (Ojs.array_get (Ojs.get_prop_ascii x168 \"arg\") 0)),\n                       (Ojs.string_of_js\n                          (Ojs.array_get (Ojs.get_prop_ascii x168 \"arg\") 1)))\n               | \"D\" ->\n                   D\n                     {\n                       age = (Ojs.int_of_js (Ojs.get_prop_ascii x168 \"age\"));\n                       name =\n                         (Ojs.string_of_js (Ojs.get_prop_ascii x168 \"name\"))\n                     }\n               | _ -> Unknown x168)\n          | \"boolean\" -> Unknown x168\n          | _ -> Unknown x168\n      and sum_to_js : sum -> Ojs.t =\n        fun (x160 : sum) ->\n          match x160 with\n          | A -> Ojs.obj [|(\"kind\", (Ojs.string_to_js \"A\"))|]\n          | B x161 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"B\"));(\"arg\",\n                                                     (Ojs.int_to_js x161))|]\n          | C (x162, x163) ->\n              let x164 = Ojs.array_make 2 in\n              (Ojs.array_set x164 1 (Ojs.string_to_js x163);\n               Ojs.array_set x164 0 (Ojs.int_to_js x162);\n               Ojs.obj [|(\"kind\", (Ojs.string_to_js \"C\"));(\"arg\", x164)|])\n          | D x165 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"D\"));(\"age\",\n                                                     (Ojs.int_to_js x165.age));\n                  (\"name\", (Ojs.string_to_js x165.name))|]\n          | Unknown x166 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"Unknown\"));(\"arg\", x166)|]\n      type t =\n        | A \n        | B of int \n        | C of int * string \n        | D of {\n        age: int ;\n        name: string } \n        | E of int \n        | Unknown of Ojs.t \n      let rec t_of_js : Ojs.t -> t =\n        fun (x177 : Ojs.t) ->\n          let x178 = x177 in\n          match Ojs.type_of (Ojs.get_prop_ascii x178 \"kind\") with\n          | \"number\" -> Unknown x178\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x178 \"kind\") with\n               | \"A\" -> A\n               | \"B\" -> B (Ojs.int_of_js (Ojs.get_prop_ascii x178 \"bArg\"))\n               | \"C\" ->\n                   C\n                     ((Ojs.int_of_js\n                         (Ojs.array_get (Ojs.get_prop_ascii x178 \"cArg\") 0)),\n                       (Ojs.string_of_js\n                          (Ojs.array_get (Ojs.get_prop_ascii x178 \"cArg\") 1)))\n               | \"D\" ->\n                   D\n                     {\n                       age = (Ojs.int_of_js (Ojs.get_prop_ascii x178 \"X\"));\n                       name =\n                         (Ojs.string_of_js (Ojs.get_prop_ascii x178 \"Y\"))\n                     }\n               | \"F\" -> E (Ojs.int_of_js (Ojs.get_prop_ascii x178 \"fArg\"))\n               | _ -> Unknown x178)\n          | \"boolean\" -> Unknown x178\n          | _ -> Unknown x178\n      and t_to_js : t -> Ojs.t =\n        fun (x169 : t) ->\n          match x169 with\n          | A -> Ojs.obj [|(\"kind\", (Ojs.string_to_js \"A\"))|]\n          | B x170 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"B\"));(\"bArg\",\n                                                     (Ojs.int_to_js x170))|]\n          | C (x171, x172) ->\n              let x173 = Ojs.array_make 2 in\n              (Ojs.array_set x173 1 (Ojs.string_to_js x172);\n               Ojs.array_set x173 0 (Ojs.int_to_js x171);\n               Ojs.obj [|(\"kind\", (Ojs.string_to_js \"C\"));(\"cArg\", x173)|])\n          | D x174 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"D\"));(\"X\",\n                                                     (Ojs.int_to_js x174.age));\n                  (\"Y\", (Ojs.string_to_js x174.name))|]\n          | E x175 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"F\"));(\"fArg\",\n                                                     (Ojs.int_to_js x175))|]\n          | Unknown x176 ->\n              Ojs.obj\n                [|(\"kind\", (Ojs.string_to_js \"Unknown\"));(\"arg\", x176)|]\n      type union =\n        | A \n        | B of int \n        | C of int \n        | D of Ojs.t \n      let rec union_to_js : union -> Ojs.t =\n        fun (x179 : union) ->\n          match x179 with\n          | A -> Ojs.null\n          | B x180 -> Ojs.int_to_js x180\n          | C x181 -> Ojs.int_to_js x181\n          | D x182 -> x182\n      type poly_union = [ `A  | `B of int  | `C of int  | `D of Ojs.t ]\n      let rec poly_union_to_js : poly_union -> Ojs.t =\n        fun (x185 : [ `A  | `B of int  | `C of int  | `D of Ojs.t ]) ->\n          match x185 with\n          | `A -> Ojs.null\n          | `B x186 -> Ojs.int_to_js x186\n          | `C x187 -> Ojs.int_to_js x187\n          | `D x188 -> x188\n      type discr_union =\n        | A \n        | B of int \n        | C of int \n        | D of Ojs.t \n      let rec discr_union_of_js : Ojs.t -> discr_union =\n        fun (x195 : Ojs.t) ->\n          let x196 = x195 in\n          match Ojs.type_of (Ojs.get_prop_ascii x196 \"discr\") with\n          | \"number\" -> D x196\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x196 \"discr\") with\n               | \"A\" -> A\n               | \"B\" -> B (Ojs.int_of_js x196)\n               | \"C\" -> C (Ojs.int_of_js x196)\n               | _ -> D x196)\n          | \"boolean\" -> D x196\n          | _ -> D x196\n      and discr_union_to_js : discr_union -> Ojs.t =\n        fun (x191 : discr_union) ->\n          match x191 with\n          | A -> Ojs.null\n          | B x192 -> Ojs.int_to_js x192\n          | C x193 -> Ojs.int_to_js x193\n          | D x194 -> x194\n      type discr_poly_union = [ `A  | `B of int  | `C of int  | `D of Ojs.t ]\n      let rec discr_poly_union_of_js : Ojs.t -> discr_poly_union =\n        fun (x201 : Ojs.t) ->\n          let x202 = x201 in\n          match Ojs.type_of (Ojs.get_prop_ascii x202 \"discr\") with\n          | \"number\" -> `D x202\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x202 \"discr\") with\n               | \"A\" -> `A\n               | \"B\" -> `B (Ojs.int_of_js x202)\n               | \"C\" -> `C (Ojs.int_of_js x202)\n               | _ -> `D x202)\n          | \"boolean\" -> `D x202\n          | _ -> `D x202\n      and discr_poly_union_to_js : discr_poly_union -> Ojs.t =\n        fun (x197 : [ `A  | `B of int  | `C of int  | `D of Ojs.t ]) ->\n          match x197 with\n          | `A -> Ojs.null\n          | `B x198 -> Ojs.int_to_js x198\n          | `C x199 -> Ojs.int_to_js x199\n          | `D x200 -> x200\n      type discr_union_value =\n        | A \n        | B of int \n        | C of int \n        | D of Ojs.t \n      let rec discr_union_value_of_js : Ojs.t -> discr_union_value =\n        fun (x207 : Ojs.t) ->\n          let x208 = x207 in\n          match Ojs.type_of (Ojs.get_prop_ascii x208 \"discr\") with\n          | \"number\" ->\n              (match Ojs.int_of_js (Ojs.get_prop_ascii x208 \"discr\") with\n               | 0 -> A\n               | _ -> D x208)\n          | \"string\" ->\n              (match Ojs.string_of_js (Ojs.get_prop_ascii x208 \"discr\") with\n               | \"42\" -> B (Ojs.int_of_js x208)\n               | \"C\" -> C (Ojs.int_of_js x208)\n               | _ -> D x208)\n          | \"boolean\" -> D x208\n          | _ -> D x208\n      and discr_union_value_to_js : discr_union_value -> Ojs.t =\n        fun (x203 : discr_union_value) ->\n          match x203 with\n          | A -> Ojs.null\n          | B x204 -> Ojs.int_to_js x204\n          | C x205 -> Ojs.int_to_js x205\n          | D x206 -> x206\n      module NestedScope0 =\n        struct\n          let f : string -> unit =\n            fun (x209 : string) ->\n              ignore\n                (Ojs.call\n                   (Ojs.get_prop_ascii\n                      (Ojs.get_prop_ascii Ojs.global \"outer\") \"inner\") \"f\"\n                   [|(Ojs.string_to_js x209)|])\n        end\n      module NestedScope1 =\n        struct\n          let f : string -> unit =\n            fun (x210 : string) ->\n              ignore\n                (Ojs.call\n                   (Ojs.get_prop_ascii\n                      (Ojs.get_prop_ascii Ojs.global \"outer\") \"inner\") \"f\"\n                   [|(Ojs.string_to_js x210)|])\n        end\n      module NestedScope2 =\n        struct\n          let f : string -> unit =\n            fun (x211 : string) ->\n              ignore\n                (Ojs.call\n                   (Ojs.get_prop_ascii\n                      (Ojs.get_prop_ascii Ojs.global \"outer\") \"inner\") \"f\"\n                   [|(Ojs.string_to_js x211)|])\n        end\n    end)[@merlin.hide ]) [@@ocaml.doc \" Types Declarations \"]\n"
  },
  {
    "path": "ppx-test/expected/union_and_enum.ml",
    "content": "[@@@js.dummy \"!! This code has been generated by gen_js_api !!\"]\n[@@@ocaml.warning \"-7-32-39\"]\ntype enum_int =\n  | Enum_int_0 \n  | Enum_int_1 \n  | Enum_int_other of int \nlet rec enum_int_of_js : Ojs.t -> enum_int =\n  fun (x3 : Ojs.t) ->\n    let x4 = x3 in\n    match Ojs.int_of_js x4 with\n    | 0 -> Enum_int_0\n    | 1 -> Enum_int_1\n    | x5 -> Enum_int_other x5\nand enum_int_to_js : enum_int -> Ojs.t =\n  fun (x1 : enum_int) ->\n    match x1 with\n    | Enum_int_0 -> Ojs.int_to_js 0\n    | Enum_int_1 -> Ojs.int_to_js 1\n    | Enum_int_other x2 -> Ojs.int_to_js x2\ntype enum_float =\n  | Enum_float_0_1 \n  | Enum_float_1_1 \n  | Enum_float_other of float \nlet rec enum_float_of_js : Ojs.t -> enum_float =\n  fun (x8 : Ojs.t) ->\n    let x9 = x8 in\n    match Ojs.float_of_js x9 with\n    | 0.1 -> Enum_float_0_1\n    | 1.1 -> Enum_float_1_1\n    | x10 -> Enum_float_other x10\nand enum_float_to_js : enum_float -> Ojs.t =\n  fun (x6 : enum_float) ->\n    match x6 with\n    | Enum_float_0_1 -> Ojs.float_to_js 0.1\n    | Enum_float_1_1 -> Ojs.float_to_js 1.1\n    | Enum_float_other x7 -> Ojs.float_to_js x7\ntype enum_number_1 =\n  | Enum_number_0 \n  | Enum_number_1 \n  | Enum_number_0_1 \n  | Enum_number_1_1 \n  | Enum_number_other of int \nlet rec enum_number_1_of_js : Ojs.t -> enum_number_1 =\n  fun (x13 : Ojs.t) ->\n    let x14 = x13 in\n    match Ojs.float_of_js x14 with\n    | 0.1 -> Enum_number_0_1\n    | 1.1 -> Enum_number_1_1\n    | _ ->\n        (match Ojs.int_of_js x14 with\n         | 0 -> Enum_number_0\n         | 1 -> Enum_number_1\n         | x15 -> Enum_number_other x15)\nand enum_number_1_to_js : enum_number_1 -> Ojs.t =\n  fun (x11 : enum_number_1) ->\n    match x11 with\n    | Enum_number_0 -> Ojs.int_to_js 0\n    | Enum_number_1 -> Ojs.int_to_js 1\n    | Enum_number_0_1 -> Ojs.float_to_js 0.1\n    | Enum_number_1_1 -> Ojs.float_to_js 1.1\n    | Enum_number_other x12 -> Ojs.int_to_js x12\ntype enum_number_2 =\n  | Enum_number_0 \n  | Enum_number_1 \n  | Enum_number_0_1 \n  | Enum_number_1_1 \n  | Enum_number_other of float \nlet rec enum_number_2_of_js : Ojs.t -> enum_number_2 =\n  fun (x18 : Ojs.t) ->\n    let x19 = x18 in\n    match Ojs.float_of_js x19 with\n    | 0.1 -> Enum_number_0_1\n    | 1.1 -> Enum_number_1_1\n    | x20 ->\n        (match Ojs.int_of_js x19 with\n         | 0 -> Enum_number_0\n         | 1 -> Enum_number_1\n         | _ -> Enum_number_other x20)\nand enum_number_2_to_js : enum_number_2 -> Ojs.t =\n  fun (x16 : enum_number_2) ->\n    match x16 with\n    | Enum_number_0 -> Ojs.int_to_js 0\n    | Enum_number_1 -> Ojs.int_to_js 1\n    | Enum_number_0_1 -> Ojs.float_to_js 0.1\n    | Enum_number_1_1 -> Ojs.float_to_js 1.1\n    | Enum_number_other x17 -> Ojs.float_to_js x17\ntype enum_string =\n  | Enum_string_foo \n  | Enum_string_bar \n  | Enum_string_other of string \nlet rec enum_string_of_js : Ojs.t -> enum_string =\n  fun (x23 : Ojs.t) ->\n    let x24 = x23 in\n    match Ojs.string_of_js x24 with\n    | \"foo\" -> Enum_string_foo\n    | \"bar\" -> Enum_string_bar\n    | x25 -> Enum_string_other x25\nand enum_string_to_js : enum_string -> Ojs.t =\n  fun (x21 : enum_string) ->\n    match x21 with\n    | Enum_string_foo -> Ojs.string_to_js \"foo\"\n    | Enum_string_bar -> Ojs.string_to_js \"bar\"\n    | Enum_string_other x22 -> Ojs.string_to_js x22\ntype enum_bool =\n  | Enum_bool_true \n  | Enum_bool_false \nlet rec enum_bool_of_js : Ojs.t -> enum_bool =\n  fun (x27 : Ojs.t) ->\n    let x28 = x27 in\n    match Ojs.bool_of_js x28 with\n    | true -> Enum_bool_true\n    | false -> Enum_bool_false\nand enum_bool_to_js : enum_bool -> Ojs.t =\n  fun (x26 : enum_bool) ->\n    match x26 with\n    | Enum_bool_true -> Ojs.bool_to_js true\n    | Enum_bool_false -> Ojs.bool_to_js false\ntype enum_bool_partial =\n  | Enum_bool_true \nlet rec enum_bool_partial_of_js : Ojs.t -> enum_bool_partial =\n  fun (x30 : Ojs.t) ->\n    let x31 = x30 in\n    match Ojs.bool_of_js x31 with\n    | true -> Enum_bool_true\n    | _ -> assert false\nand enum_bool_partial_to_js : enum_bool_partial -> Ojs.t =\n  fun (x29 : enum_bool_partial) ->\n    match x29 with | Enum_bool_true -> Ojs.bool_to_js true\ntype enum_bool_partial2 =\n  | Enum_bool_true \n  | Enum_bool_other of bool \nlet rec enum_bool_partial2_of_js : Ojs.t -> enum_bool_partial2 =\n  fun (x34 : Ojs.t) ->\n    let x35 = x34 in\n    match Ojs.bool_of_js x35 with\n    | true -> Enum_bool_true\n    | x36 -> Enum_bool_other x36\nand enum_bool_partial2_to_js : enum_bool_partial2 -> Ojs.t =\n  fun (x32 : enum_bool_partial2) ->\n    match x32 with\n    | Enum_bool_true -> Ojs.bool_to_js true\n    | Enum_bool_other x33 -> Ojs.bool_to_js x33\ntype enum_mixed =\n  | Enum_int_0 \n  | Enum_int_1 \n  | Enum_float_0_1 \n  | Enum_float_1_1 \n  | Enum_number_other of int \n  | Enum_string_foo \n  | Enum_string_bar \n  | Enum_string_other of string \n  | Enum_bool_true \n  | Enum_bool_false \nlet rec enum_mixed_of_js : Ojs.t -> enum_mixed =\n  fun (x40 : Ojs.t) ->\n    let x41 = x40 in\n    match Ojs.type_of x41 with\n    | \"number\" ->\n        (match Ojs.float_of_js x41 with\n         | 0.1 -> Enum_float_0_1\n         | 1.1 -> Enum_float_1_1\n         | _ ->\n             (match Ojs.int_of_js x41 with\n              | 0 -> Enum_int_0\n              | 1 -> Enum_int_1\n              | x42 -> Enum_number_other x42))\n    | \"string\" ->\n        (match Ojs.string_of_js x41 with\n         | \"foo\" -> Enum_string_foo\n         | \"bar\" -> Enum_string_bar\n         | x43 -> Enum_string_other x43)\n    | \"boolean\" ->\n        (match Ojs.bool_of_js x41 with\n         | true -> Enum_bool_true\n         | false -> Enum_bool_false)\n    | _ -> assert false\nand enum_mixed_to_js : enum_mixed -> Ojs.t =\n  fun (x37 : enum_mixed) ->\n    match x37 with\n    | Enum_int_0 -> Ojs.int_to_js 0\n    | Enum_int_1 -> Ojs.int_to_js 1\n    | Enum_float_0_1 -> Ojs.float_to_js 0.1\n    | Enum_float_1_1 -> Ojs.float_to_js 1.1\n    | Enum_number_other x38 -> Ojs.int_to_js x38\n    | Enum_string_foo -> Ojs.string_to_js \"foo\"\n    | Enum_string_bar -> Ojs.string_to_js \"bar\"\n    | Enum_string_other x39 -> Ojs.string_to_js x39\n    | Enum_bool_true -> Ojs.bool_to_js true\n    | Enum_bool_false -> Ojs.bool_to_js false\ntype enum_mixed_partial_bool =\n  | Enum_int_0 \n  | Enum_int_1 \n  | Enum_float_0_1 \n  | Enum_float_1_1 \n  | Enum_number_other of float \n  | Enum_string_foo \n  | Enum_string_bar \n  | Enum_string_other of string \n  | Enum_bool_true \nlet rec enum_mixed_partial_bool_of_js : Ojs.t -> enum_mixed_partial_bool =\n  fun (x47 : Ojs.t) ->\n    let x48 = x47 in\n    match Ojs.type_of x48 with\n    | \"number\" ->\n        (match Ojs.float_of_js x48 with\n         | 0.1 -> Enum_float_0_1\n         | 1.1 -> Enum_float_1_1\n         | x49 ->\n             (match Ojs.int_of_js x48 with\n              | 0 -> Enum_int_0\n              | 1 -> Enum_int_1\n              | _ -> Enum_number_other x49))\n    | \"string\" ->\n        (match Ojs.string_of_js x48 with\n         | \"foo\" -> Enum_string_foo\n         | \"bar\" -> Enum_string_bar\n         | x50 -> Enum_string_other x50)\n    | \"boolean\" ->\n        (match Ojs.bool_of_js x48 with\n         | true -> Enum_bool_true\n         | _ -> assert false)\n    | _ -> assert false\nand enum_mixed_partial_bool_to_js : enum_mixed_partial_bool -> Ojs.t =\n  fun (x44 : enum_mixed_partial_bool) ->\n    match x44 with\n    | Enum_int_0 -> Ojs.int_to_js 0\n    | Enum_int_1 -> Ojs.int_to_js 1\n    | Enum_float_0_1 -> Ojs.float_to_js 0.1\n    | Enum_float_1_1 -> Ojs.float_to_js 1.1\n    | Enum_number_other x45 -> Ojs.float_to_js x45\n    | Enum_string_foo -> Ojs.string_to_js \"foo\"\n    | Enum_string_bar -> Ojs.string_to_js \"bar\"\n    | Enum_string_other x46 -> Ojs.string_to_js x46\n    | Enum_bool_true -> Ojs.bool_to_js true\ntype enum_mixed_partial_bool2 =\n  | Enum_int_0 \n  | Enum_int_1 \n  | Enum_float_0_1 \n  | Enum_float_1_1 \n  | Enum_number_other of float \n  | Enum_string_foo \n  | Enum_string_bar \n  | Enum_string_other of string \n  | Enum_bool_true \n  | Enum_bool_other of bool \nlet rec enum_mixed_partial_bool2_of_js : Ojs.t -> enum_mixed_partial_bool2 =\n  fun (x55 : Ojs.t) ->\n    let x56 = x55 in\n    match Ojs.type_of x56 with\n    | \"number\" ->\n        (match Ojs.float_of_js x56 with\n         | 0.1 -> Enum_float_0_1\n         | 1.1 -> Enum_float_1_1\n         | x57 ->\n             (match Ojs.int_of_js x56 with\n              | 0 -> Enum_int_0\n              | 1 -> Enum_int_1\n              | _ -> Enum_number_other x57))\n    | \"string\" ->\n        (match Ojs.string_of_js x56 with\n         | \"foo\" -> Enum_string_foo\n         | \"bar\" -> Enum_string_bar\n         | x58 -> Enum_string_other x58)\n    | \"boolean\" ->\n        (match Ojs.bool_of_js x56 with\n         | true -> Enum_bool_true\n         | x59 -> Enum_bool_other x59)\n    | _ -> assert false\nand enum_mixed_partial_bool2_to_js : enum_mixed_partial_bool2 -> Ojs.t =\n  fun (x51 : enum_mixed_partial_bool2) ->\n    match x51 with\n    | Enum_int_0 -> Ojs.int_to_js 0\n    | Enum_int_1 -> Ojs.int_to_js 1\n    | Enum_float_0_1 -> Ojs.float_to_js 0.1\n    | Enum_float_1_1 -> Ojs.float_to_js 1.1\n    | Enum_number_other x52 -> Ojs.float_to_js x52\n    | Enum_string_foo -> Ojs.string_to_js \"foo\"\n    | Enum_string_bar -> Ojs.string_to_js \"bar\"\n    | Enum_string_other x53 -> Ojs.string_to_js x53\n    | Enum_bool_true -> Ojs.bool_to_js true\n    | Enum_bool_other x54 -> Ojs.bool_to_js x54\ntype dummy1 = Ojs.t\nlet rec dummy1_of_js : Ojs.t -> dummy1 = fun (x61 : Ojs.t) -> x61\nand dummy1_to_js : dummy1 -> Ojs.t = fun (x60 : Ojs.t) -> x60\ntype dummy2 = Ojs.t\nlet rec dummy2_of_js : Ojs.t -> dummy2 = fun (x63 : Ojs.t) -> x63\nand dummy2_to_js : dummy2 -> Ojs.t = fun (x62 : Ojs.t) -> x62\ntype dummy3 = Ojs.t\nlet rec dummy3_of_js : Ojs.t -> dummy3 = fun (x65 : Ojs.t) -> x65\nand dummy3_to_js : dummy3 -> Ojs.t = fun (x64 : Ojs.t) -> x64\ntype dummy4 = Ojs.t\nlet rec dummy4_of_js : Ojs.t -> dummy4 = fun (x67 : Ojs.t) -> x67\nand dummy4_to_js : dummy4 -> Ojs.t = fun (x66 : Ojs.t) -> x66\ntype dummy5 = Ojs.t\nlet rec dummy5_of_js : Ojs.t -> dummy5 = fun (x69 : Ojs.t) -> x69\nand dummy5_to_js : dummy5 -> Ojs.t = fun (x68 : Ojs.t) -> x68\ntype dummy6 = Ojs.t\nlet rec dummy6_of_js : Ojs.t -> dummy6 = fun (x71 : Ojs.t) -> x71\nand dummy6_to_js : dummy6 -> Ojs.t = fun (x70 : Ojs.t) -> x70\ntype union_int =\n  | Union_int_0 of dummy1 \n  | Union_int_1 of dummy2 \n  | Unknown of Ojs.t \nlet rec union_int_of_js : Ojs.t -> union_int =\n  fun (x76 : Ojs.t) ->\n    let x77 = x76 in\n    match Ojs.type_of (Ojs.get_prop_ascii x77 \"tag\") with\n    | \"number\" ->\n        (match Ojs.int_of_js (Ojs.get_prop_ascii x77 \"tag\") with\n         | 0 -> Union_int_0 (dummy1_of_js x77)\n         | 1 -> Union_int_1 (dummy2_of_js x77)\n         | _ -> Unknown x77)\n    | \"string\" -> Unknown x77\n    | \"boolean\" -> Unknown x77\n    | _ -> Unknown x77\nand union_int_to_js : union_int -> Ojs.t =\n  fun (x72 : union_int) ->\n    match x72 with\n    | Union_int_0 x73 -> dummy1_to_js x73\n    | Union_int_1 x74 -> dummy2_to_js x74\n    | Unknown x75 -> x75\ntype union_float =\n  | Union_float_0_1 of dummy1 \n  | Union_float_1_1 of dummy2 \n  | Unknown of Ojs.t \nlet rec union_float_of_js : Ojs.t -> union_float =\n  fun (x82 : Ojs.t) ->\n    let x83 = x82 in\n    match Ojs.type_of (Ojs.get_prop_ascii x83 \"tag\") with\n    | \"number\" ->\n        (match Ojs.float_of_js (Ojs.get_prop_ascii x83 \"tag\") with\n         | 0.1 -> Union_float_0_1 (dummy1_of_js x83)\n         | 1.1 -> Union_float_1_1 (dummy2_of_js x83)\n         | _ -> Unknown x83)\n    | \"string\" -> Unknown x83\n    | \"boolean\" -> Unknown x83\n    | _ -> Unknown x83\nand union_float_to_js : union_float -> Ojs.t =\n  fun (x78 : union_float) ->\n    match x78 with\n    | Union_float_0_1 x79 -> dummy1_to_js x79\n    | Union_float_1_1 x80 -> dummy2_to_js x80\n    | Unknown x81 -> x81\ntype union_string =\n  | Union_string_foo of dummy3 \n  | Union_string_bar of dummy4 \n  | Unknown of Ojs.t \nlet rec union_string_of_js : Ojs.t -> union_string =\n  fun (x88 : Ojs.t) ->\n    let x89 = x88 in\n    match Ojs.type_of (Ojs.get_prop_ascii x89 \"tag\") with\n    | \"number\" -> Unknown x89\n    | \"string\" ->\n        (match Ojs.string_of_js (Ojs.get_prop_ascii x89 \"tag\") with\n         | \"foo\" -> Union_string_foo (dummy3_of_js x89)\n         | \"bar\" -> Union_string_bar (dummy4_of_js x89)\n         | _ -> Unknown x89)\n    | \"boolean\" -> Unknown x89\n    | _ -> Unknown x89\nand union_string_to_js : union_string -> Ojs.t =\n  fun (x84 : union_string) ->\n    match x84 with\n    | Union_string_foo x85 -> dummy3_to_js x85\n    | Union_string_bar x86 -> dummy4_to_js x86\n    | Unknown x87 -> x87\ntype union_bool =\n  | Union_bool_true of dummy5 \n  | Union_bool_false of dummy6 \nlet rec union_bool_of_js : Ojs.t -> union_bool =\n  fun (x93 : Ojs.t) ->\n    let x94 = x93 in\n    match Ojs.bool_of_js (Ojs.get_prop_ascii x94 \"tag\") with\n    | true -> Union_bool_true (dummy5_of_js x94)\n    | false -> Union_bool_false (dummy6_of_js x94)\nand union_bool_to_js : union_bool -> Ojs.t =\n  fun (x90 : union_bool) ->\n    match x90 with\n    | Union_bool_true x91 -> dummy5_to_js x91\n    | Union_bool_false x92 -> dummy6_to_js x92\ntype union_bool_partial =\n  | Union_bool_true of dummy5 \nlet rec union_bool_partial_of_js : Ojs.t -> union_bool_partial =\n  fun (x97 : Ojs.t) ->\n    let x98 = x97 in\n    match Ojs.bool_of_js (Ojs.get_prop_ascii x98 \"tag\") with\n    | true -> Union_bool_true (dummy5_of_js x98)\n    | _ -> assert false\nand union_bool_partial_to_js : union_bool_partial -> Ojs.t =\n  fun (x95 : union_bool_partial) ->\n    match x95 with | Union_bool_true x96 -> dummy5_to_js x96\ntype union_bool_partial2 =\n  | Union_bool_true of dummy5 \n  | Unknown of Ojs.t \nlet rec union_bool_partial2_of_js : Ojs.t -> union_bool_partial2 =\n  fun (x102 : Ojs.t) ->\n    let x103 = x102 in\n    match Ojs.type_of (Ojs.get_prop_ascii x103 \"tag\") with\n    | \"number\" -> Unknown x103\n    | \"string\" -> Unknown x103\n    | \"boolean\" ->\n        (match Ojs.bool_of_js (Ojs.get_prop_ascii x103 \"tag\") with\n         | true -> Union_bool_true (dummy5_of_js x103)\n         | _ -> Unknown x103)\n    | _ -> Unknown x103\nand union_bool_partial2_to_js : union_bool_partial2 -> Ojs.t =\n  fun (x99 : union_bool_partial2) ->\n    match x99 with\n    | Union_bool_true x100 -> dummy5_to_js x100\n    | Unknown x101 -> x101\ntype union_mixed =\n  | Union_int_0 of dummy1 \n  | Union_int_1 of dummy2 \n  | Union_float_0_1 of dummy1 \n  | Union_float_1_1 of dummy2 \n  | Union_string_foo of dummy3 \n  | Union_string_bar of dummy4 \n  | Union_bool_true of dummy5 \n  | Union_bool_false of dummy6 \n  | Unknown of Ojs.t \nlet rec union_mixed_of_js : Ojs.t -> union_mixed =\n  fun (x114 : Ojs.t) ->\n    let x115 = x114 in\n    match Ojs.type_of (Ojs.get_prop_ascii x115 \"tag\") with\n    | \"number\" ->\n        (match Ojs.float_of_js (Ojs.get_prop_ascii x115 \"tag\") with\n         | 0.1 -> Union_float_0_1 (dummy1_of_js x115)\n         | 1.1 -> Union_float_1_1 (dummy2_of_js x115)\n         | _ ->\n             (match Ojs.int_of_js (Ojs.get_prop_ascii x115 \"tag\") with\n              | 0 -> Union_int_0 (dummy1_of_js x115)\n              | 1 -> Union_int_1 (dummy2_of_js x115)\n              | _ -> Unknown x115))\n    | \"string\" ->\n        (match Ojs.string_of_js (Ojs.get_prop_ascii x115 \"tag\") with\n         | \"foo\" -> Union_string_foo (dummy3_of_js x115)\n         | \"bar\" -> Union_string_bar (dummy4_of_js x115)\n         | _ -> Unknown x115)\n    | \"boolean\" ->\n        (match Ojs.bool_of_js (Ojs.get_prop_ascii x115 \"tag\") with\n         | true -> Union_bool_true (dummy5_of_js x115)\n         | false -> Union_bool_false (dummy6_of_js x115))\n    | _ -> Unknown x115\nand union_mixed_to_js : union_mixed -> Ojs.t =\n  fun (x104 : union_mixed) ->\n    match x104 with\n    | Union_int_0 x105 -> dummy1_to_js x105\n    | Union_int_1 x106 -> dummy2_to_js x106\n    | Union_float_0_1 x107 -> dummy1_to_js x107\n    | Union_float_1_1 x108 -> dummy2_to_js x108\n    | Union_string_foo x109 -> dummy3_to_js x109\n    | Union_string_bar x110 -> dummy4_to_js x110\n    | Union_bool_true x111 -> dummy5_to_js x111\n    | Union_bool_false x112 -> dummy6_to_js x112\n    | Unknown x113 -> x113\ntype union_mixed_partial_bool =\n  | Union_int_0 of dummy1 \n  | Union_int_1 of dummy2 \n  | Union_float_0_1 of dummy1 \n  | Union_float_1_1 of dummy2 \n  | Union_string_foo of dummy3 \n  | Union_string_bar of dummy4 \n  | Union_bool_true of dummy5 \n  | Unknown of Ojs.t \nlet rec union_mixed_partial_bool_of_js : Ojs.t -> union_mixed_partial_bool =\n  fun (x125 : Ojs.t) ->\n    let x126 = x125 in\n    match Ojs.type_of (Ojs.get_prop_ascii x126 \"tag\") with\n    | \"number\" ->\n        (match Ojs.float_of_js (Ojs.get_prop_ascii x126 \"tag\") with\n         | 0.1 -> Union_float_0_1 (dummy1_of_js x126)\n         | 1.1 -> Union_float_1_1 (dummy2_of_js x126)\n         | _ ->\n             (match Ojs.int_of_js (Ojs.get_prop_ascii x126 \"tag\") with\n              | 0 -> Union_int_0 (dummy1_of_js x126)\n              | 1 -> Union_int_1 (dummy2_of_js x126)\n              | _ -> Unknown x126))\n    | \"string\" ->\n        (match Ojs.string_of_js (Ojs.get_prop_ascii x126 \"tag\") with\n         | \"foo\" -> Union_string_foo (dummy3_of_js x126)\n         | \"bar\" -> Union_string_bar (dummy4_of_js x126)\n         | _ -> Unknown x126)\n    | \"boolean\" ->\n        (match Ojs.bool_of_js (Ojs.get_prop_ascii x126 \"tag\") with\n         | true -> Union_bool_true (dummy5_of_js x126)\n         | _ -> Unknown x126)\n    | _ -> Unknown x126\nand union_mixed_partial_bool_to_js : union_mixed_partial_bool -> Ojs.t =\n  fun (x116 : union_mixed_partial_bool) ->\n    match x116 with\n    | Union_int_0 x117 -> dummy1_to_js x117\n    | Union_int_1 x118 -> dummy2_to_js x118\n    | Union_float_0_1 x119 -> dummy1_to_js x119\n    | Union_float_1_1 x120 -> dummy2_to_js x120\n    | Union_string_foo x121 -> dummy3_to_js x121\n    | Union_string_bar x122 -> dummy4_to_js x122\n    | Union_bool_true x123 -> dummy5_to_js x123\n    | Unknown x124 -> x124\n"
  },
  {
    "path": "ppx-test/extension.ml",
    "content": "\nlet _ = [%js.of: int]\nlet _ = [%js.of: int -> int]\n"
  },
  {
    "path": "ppx-test/first_class_modules.mli",
    "content": "module[@js.scope \"console\"] Console: sig\n  val log: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.global \"log\"]\n  val log2:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    'a -> 'b -> unit [@@js.global \"log\"]\n  val log3:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    (module[@js] Ojs.T with type t = 'c) ->\n    'a -> 'b -> 'c -> unit [@@js.global \"log\"]\nend\n\nmodule Console2: sig\n  type t\n  val log: (module[@js] Ojs.T with type t = 'a) -> t -> 'a -> unit [@@js.call \"log\"]\n  val log2:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    t -> 'a -> 'b -> unit [@@js.call \"log\"]\n  val log3:\n    (module[@js] Ojs.T with type t = 'a) ->\n    (module[@js] Ojs.T with type t = 'b) ->\n    (module[@js] Ojs.T with type t = 'c) ->\n    t -> 'a -> 'b -> 'c -> unit [@@js.call \"log\"]\nend\n\nmodule[@js.scope \"console\"] Console3: sig\n  module [@js.scope \"log\"] Log: sig\n    val _1: (module[@js] Ojs.T with type t = 'a) -> 'a -> unit [@@js.invoke]\n    val _2:\n      (module[@js] Ojs.T with type t = 'a) ->\n      (module[@js] Ojs.T with type t = 'b) ->\n      'a -> 'b -> unit [@@js.invoke]\n    val _3:\n      (module[@js] Ojs.T with type t = 'a) ->\n      (module[@js] Ojs.T with type t = 'b) ->\n      (module[@js] Ojs.T with type t = 'c) ->\n      'a -> 'b -> 'c -> unit [@@js.invoke]\n  end\nend\n\nmodule[@js.scope \"Array\"] Array: sig\n  type 'a t\n  val t_to_js: ('a -> Ojs.t) -> 'a t -> Ojs.t\n  val t_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a t\n\n  val create:  (module[@js] Ojs.T with type t = 'a) -> ('a list [@js.variadic]) -> 'a t [@@js.create]\n  val create': (module[@js] Ojs.T with type t = 'a) -> ('a list [@js.variadic]) -> 'a t [@@js.invoke]\n\n  val push: (module[@js] Ojs.T with type t = 'a) -> 'a t -> 'a -> unit [@@js.call]\n  val pop:  (module[@js] Ojs.T with type t = 'a) -> 'a t -> 'a option [@@js.call]\nend"
  },
  {
    "path": "ppx-test/issues.ml",
    "content": "module Issue116 = [%js: type t]\nmodule Issue117 = [%js:\n  module T: sig\n    val log: 'a -> unit [@@js.global]\n    val log2: 'a -> 'b -> unit [@@js.global \"jsLog2\"]\n  end [@js.scope \"console\"]\n]\nmodule Issue124 = [%js:\n  type a\n  and b =\n    { a : a }\n    [@@js.custom {\n      to_js = (fun { a } -> [%js.of: a] a);\n      of_js = (fun js -> { a = [%js.to: a] js})\n    }]\n\n  type 'a dummy\n\n  type 'a wrapped =\n    | Wrapped of 'a\n    [@@js.custom {\n      to_js = (\n        let f a_to_js =\n          function Wrapped a ->\n            a_to_js a\n        in f);\n      of_js = (\n        let f a_of_js x =\n          Wrapped (a_of_js x)\n        in f\n      )\n    }]\n\n  type u =\n    | Unknown of Ojs.t [@js.default]\n    | T of t [@js \"t\"]\n    | WrappedT of t wrapped [@js \"wrapped_t\"]\n    [@@js.union on_field \"type\"]\n\n  and t = [`U of u] dummy [@@js.custom {\n    to_js = Obj.magic; of_js = Obj.magic\n  }]\n\n  type ('a, 'b) base = [ `BaseA of 'a | `BaseB of 'b ] dummy [@@js.custom {\n    to_js = (fun _ _ -> Obj.magic);\n    of_js = (fun _ _ -> Obj.magic)\n  }]\n  and base1 = (int, string) base\n  and base2 = (string, int) base\n]\nmodule Issue109 = [%js:\n  type t =\n    [ `S of string [@js.default]\n    | `I of int [@js.default]\n    ] [@@js.enum]\n]\nmodule Issue142 = [%js:\n  type t = [`Foo [@js 42]] [@js.enum]\n  and u = t\n]\nmodule Issue144 = [%js:\n  type t\n  val f: t -> (args:int -> int [@js.dummy]) [@@js.call \"f\"]\n]\nmodule Issue146 = [%js:\n  val f: ?arg:([`Foo [@js 42]] [@js.enum]) -> unit -> int [@@js.global \"f\"]\n]\nmodule PR165 = [%js:\n  module Markdown : sig\n    type t\n  end\n\n  module [@js.scope \"ParameterInformation\"] ParameterInformation : sig\n    type t\n    val create: label:([`String of string | `Tuple of (int * int)] [@js.union]) -> ?documentation:([`String of string | `Markdown of Markdown.t] [@js.union]) -> unit -> t [@@js.create]\n  end\n]"
  },
  {
    "path": "ppx-test/issues_mli.mli",
    "content": "module Issue144: sig\n  type t\n  val f: t -> (args:int -> int [@js.dummy]) [@@js.call \"f\"]\nend\n"
  },
  {
    "path": "ppx-test/modules.mli",
    "content": "module Event: sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\nend\n\nmodule Foo: sig\n  module E = Event\n\n  val foo: E.t -> string -> unit [@@js.call]\nend\n\nmodule Bar: sig\n  include (module type of Event)\n\n  val bar: t -> string -> unit [@@js.call]\nend\n"
  },
  {
    "path": "ppx-test/ppx/dune",
    "content": "(executable\n (name main)\n (libraries ppxlib gen_js_api_ppx_driver))\n"
  },
  {
    "path": "ppx-test/ppx/main.ml",
    "content": "\n(* To run as a standalone binary, run the registered drivers *)\nlet () = Ppxlib.Driver.standalone ()\n"
  },
  {
    "path": "ppx-test/recursive_modules.mli",
    "content": "module [@js.scope \"Foo\"] rec Foo : sig\n  type t = private Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n  val create: string -> t [@@js.create]\n  val describe: t -> string [@@js.call \"describe\"]\n  val to_bar: t -> Bar.t [@@js.call \"toBar\"]\nend\n\nand [@js.scope \"Bar\"] Bar : sig\n  type t = private Ojs.t\n  val t_of_js: Ojs.t -> t\n  val t_to_js: t -> Ojs.t\n  val create: string -> t [@@js.create]\n  val describe: t -> string [@@js.call \"describe\"]\n  val to_foo: t -> Foo.t [@@js.call \"toFoo\"]\nend\n"
  },
  {
    "path": "ppx-test/scoped.mli",
    "content": "(* The gen_js_api is released under the terms of an MIT-like license.     *)\n(* See the attached LICENSE file.                                         *)\n(* Copyright 2015 by LexiFi.                                              *)\n\n[@@@js.implem [@@@warning \"-22\"]]\n\nmodule M : sig\n  type t = private Ojs.t\n  val t_to_js: t -> Ojs.t\n  val t_of_js: Ojs.t -> t\n\n  val prop_get_arg: t -> int\n  val prop_get: unit -> int\n  val set_prop: t -> int -> unit\n  val set_global: int -> unit\n  val new_thing_unit: unit -> t\n  val new_thing_args: int -> t\n  val method_call_global: t -> unit\n  val method_call_unit: t -> unit -> int\n  val method_call_args: t -> int -> int\n  val method_call_unit_unit: t -> unit -> unit\n  val method_call_args_unit: t -> int -> unit\n  val global: t\n  val invoke: unit -> unit [@@js.invoke]\nend[@js.scope \"scope\"]\n\nval d: unit -> unit [@@js.scope (\"a\", \"b\", \"c\")] [@@js.global]\n"
  },
  {
    "path": "ppx-test/types.ml",
    "content": "\ntype 'a of_js = Ojs.t -> 'a\ntype 'a to_js = 'a -> Ojs.t\n\n(** JS-able types *)\n\nlet _ : string of_js = [%js.to: string]\nlet _ : string to_js = [%js.of: string]\n\nlet _ : int of_js = [%js.to: int]\nlet _ : int to_js = [%js.of: int]\nlet _ : bool of_js = [%js.to: bool]\nlet _ : bool to_js = [%js.of: bool]\nlet _ : float of_js = [%js.to: float]\nlet _ : float to_js = [%js.of: float]\nlet _ : Ojs.t of_js = [%js.to: Ojs.t]\nlet _ : Ojs.t to_js = [%js.of: Ojs.t]\nlet _ : (string * int) of_js = [%js.to: string * int]\nlet _ : (string * int) to_js = [%js.of: string * int]\nlet _ : (string * int * bool) of_js = [%js.to: string * int * bool]\nlet _ : (string * int * bool) to_js = [%js.of: string * int * bool]\nlet _ : (string -> int) of_js = [%js.to: string -> int]\nlet _ : (string -> int) to_js = [%js.of: string -> int]\nlet _ : ((string -> int) -> bool -> unit) of_js = [%js.to: (string -> int) -> bool -> unit]\nlet _ : ((string -> int) -> bool -> unit) to_js = [%js.of: (string -> int) -> bool -> unit]\nlet _ : (string array) of_js = [%js.to: string array]\nlet _ : (string array) to_js = [%js.of: string array]\nlet _ : (string list) of_js = [%js.to: string list]\nlet _ : (string list) to_js = [%js.of: string list]\nlet _ : (string option) of_js = [%js.to: string option]\nlet _ : (string option) to_js = [%js.of: string option]\nlet _ : (_ -> _) of_js = [%js.to: 'a -> 'b]\nlet _ : (_ -> _) to_js = [%js.of: 'a -> 'b]\nlet _ : [`foo | `bar | `Baz | `I of int | `S of string ] of_js = [%js.to: [`foo | `bar [@js 42] | `Baz | `I of int [@js.default] | `S of string[@js.default] ] [@js.enum]]\nlet _ : [`foo | `bar | `Baz | `I of int | `S of string ] to_js = [%js.of: [`foo | `bar [@js 42] | `Baz | `I of int [@js.default] | `S of string[@js.default] ] [@js.enum]]\n\n(** Label & Options Value *)\n\nlet _ : (label:int -> ?opt:int -> unit -> unit) of_js = [%js.to: label:int -> ?opt:int -> unit -> unit]\nlet _ : (label:int -> ?opt:int -> unit -> unit) to_js = [%js.of: label:int -> ?opt:int -> unit -> unit]\nlet _ : (label:int -> ?opt:int -> unit -> unit) of_js =  [%js.to: label:int -> ?opt:int -> unit -> unit] (* js.default is ignored *)\nlet _ : (label:int -> ?opt:int -> unit -> unit) to_js = [%js.of: label:int -> ?opt:int -> unit -> unit]  (* js.default is ignored *)\n\n(** Functions *)\n\nmodule B  = [%js:\n    val default0: ?x:int -> unit -> unit [@@js.global]\n    val default1: ?x:(int[@js.default 42]) -> unit -> unit [@@js.global]\n\n    val builder0: unit -> Ojs.t [@@js.builder]\n    val builder1: x:int -> Ojs.t [@@js.builder]\n    val builder2: ?x:int -> ?y:string -> unit -> Ojs.t [@@js.builder]\n    val builder3: x:int -> y:string -> unit -> Ojs.t [@@js.builder]\n    val builder4: x:int -> y:string -> z:unit -> Ojs.t [@@js.builder]\n    val builder5: ?x:int -> ?y:string -> unit -> Ojs.t [@@js.builder]\n    val builder6: ?x:(int [@js.default 42]) -> ?y:(string [@js.default \"42\"]) -> ?z:int -> unit -> Ojs.t [@@js.builder]\n\n    val sep: string -> (string list [@js.variadic]) -> string [@@js.global]\n]\n\n\n(** Types Declarations *)\nmodule T  = [%js:\n    type js = private Ojs.t\n\n    type abstract\n\n    type alias = js\n\n    type private_alias = private alias\n\n    type record = { x: js; y: js }\n\n    type mutable_record = { mutable x: js; y: js }\n\n    type record_relabel =  { x : int; y : int [@js \"Y\"]}\n\n    type ('a, 'b) parametrized = { x : 'a; y : 'b }\n\n    type 'a abs = ('a -> int) -> unit\n\n    type specialized = (int, int) parametrized\n\n    type enum =\n      | Foo [@js \"foo\"]\n      | Bar [@js 42]\n      | Baz [@js 4.2]\n      | Qux\n        [@@js.enum]\n\n    type status =\n    | OK [@js 1]\n    | KO [@js 2]\n    | OO [@js 1.5]\n    | OtherS of string [@js.default]\n    | OtherI of int [@js.default]\n      [@@js.enum]\n\n    type poly = [`foo | `bar [@js 42] | `baz [@js 4.2] | `Qux | `I of int [@js.default] | `S of string[@js.default]] [@js.enum]\n\n    type sum =\n        | A\n        | B of int\n        | C of int * string\n        | D of {age: int; name: string}\n        | Unknown of Ojs.t [@js.default]\n    [@@js.sum]\n\n    type t =\n      | A [@js \"A\"]\n      | B of int [@js.arg \"bArg\"]\n      | C of int * string [@js.arg \"cArg\"]\n      | D of {age: int [@js \"X\"]; name: string [@js \"Y\"]}\n      | E of int [@js \"F\"][@js.arg \"fArg\"]\n      | Unknown of Ojs.t [@js.default]\n    [@@js.sum \"kind\"]\n\n    type union =\n      A | B of int | C of int | D of Ojs.t [@js.default] [@@js.union]\n\n    type poly_union =\n      [`A | `B of int | `C of int | `D of Ojs.t [@js.default]] [@js.union]\n\n    type discr_union =\n      A | B of int | C of int | D of Ojs.t [@js.default] [@@js.union on_field \"discr\"]\n\n    type discr_poly_union =\n      [`A | `B of int | `C of int | `D of Ojs.t [@js.default]] [@js.union on_field \"discr\"]\n\n    type discr_union_value =\n      A [@js 0] | B of int [@js \"42\"] | C of int | D of Ojs.t [@js.default] [@@js.union on_field \"discr\"]\n\n    module NestedScope0 : sig\n      val f: string -> unit [@@js.global \"outer.inner.f\"]\n    end\n\n    module [@js.scope (\"outer\", \"inner\")] NestedScope1 : sig\n      val f: string -> unit [@@js.global]\n    end\n\n    module NestedScope2 : sig\n     val f: string -> unit [@@js.global]\n    end [@js.scope \"inner\"] [@js.scope \"outer\"]\n\n]\n"
  },
  {
    "path": "ppx-test/union_and_enum.mli",
    "content": "type enum_int =\n  | Enum_int_0 [@js 0]\n  | Enum_int_1 [@js 1]\n  | Enum_int_other of int [@js.default]\n  [@@js.enum]\n\ntype enum_float =\n  | Enum_float_0_1 [@js 0.1]\n  | Enum_float_1_1 [@js 1.1]\n  | Enum_float_other of float [@js.default]\n  [@@js.enum]\n\n(* float cases should be matched first *)\ntype enum_number_1 =\n  | Enum_number_0 [@js 0]\n  | Enum_number_1 [@js 1]\n  | Enum_number_0_1 [@js 0.1]\n  | Enum_number_1_1 [@js 1.1]\n  | Enum_number_other of int [@js.default]\n  [@@js.enum]\n\n(* float cases should be matched first even if the default case is float *)\ntype enum_number_2 =\n  | Enum_number_0 [@js 0]\n  | Enum_number_1 [@js 1]\n  | Enum_number_0_1 [@js 0.1]\n  | Enum_number_1_1 [@js 1.1]\n  | Enum_number_other of float [@js.default]\n  [@@js.enum]\n\ntype enum_string =\n  | Enum_string_foo [@js \"foo\"]\n  | Enum_string_bar [@js \"bar\"]\n  | Enum_string_other of string [@js.default]\n  [@@js.enum]\n\n(* if both true and false are expected, the boolean part of `_of_js` should not have the default case *)\ntype enum_bool =\n  | Enum_bool_true [@js true]\n  | Enum_bool_false [@js false]\n  [@@js.enum]\n\n(* otherwise, an unknown boolean value should trigger `assert false` *)\ntype enum_bool_partial =\n  | Enum_bool_true [@js true]\n  [@@js.enum]\n\n(* or it should be mapped to the case with `js.default` *)\ntype enum_bool_partial2 =\n  | Enum_bool_true [@js true]\n  | Enum_bool_other of bool [@js.default]\n  [@@js.enum]\n\n(* if both true and false are expected, the boolean part of `_of_js` should not have the default case *)\ntype enum_mixed =\n  | Enum_int_0 [@js 0]\n  | Enum_int_1 [@js 1]\n  | Enum_float_0_1 [@js 0.1]\n  | Enum_float_1_1 [@js 1.1]\n  | Enum_number_other of int [@js.default]\n  | Enum_string_foo [@js \"foo\"]\n  | Enum_string_bar [@js \"bar\"]\n  | Enum_string_other of string [@js.default]\n  | Enum_bool_true [@js true]\n  | Enum_bool_false [@js false]\n  [@@js.enum]\n\n(* otherwise, an unknown boolean value should trigger `assert false` *)\ntype enum_mixed_partial_bool =\n  | Enum_int_0 [@js 0]\n  | Enum_int_1 [@js 1]\n  | Enum_float_0_1 [@js 0.1]\n  | Enum_float_1_1 [@js 1.1]\n  | Enum_number_other of float [@js.default]\n  | Enum_string_foo [@js \"foo\"]\n  | Enum_string_bar [@js \"bar\"]\n  | Enum_string_other of string [@js.default]\n  | Enum_bool_true [@js true]\n  [@@js.enum]\n\n(* or it should be mapped to the case with `js.default` *)\ntype enum_mixed_partial_bool2 =\n  | Enum_int_0 [@js 0]\n  | Enum_int_1 [@js 1]\n  | Enum_float_0_1 [@js 0.1]\n  | Enum_float_1_1 [@js 1.1]\n  | Enum_number_other of float [@js.default]\n  | Enum_string_foo [@js \"foo\"]\n  | Enum_string_bar [@js \"bar\"]\n  | Enum_string_other of string [@js.default]\n  | Enum_bool_true [@js true]\n  | Enum_bool_other of bool [@js.default]\n  [@@js.enum]\n\ntype dummy1\ntype dummy2\ntype dummy3\ntype dummy4\ntype dummy5\ntype dummy6\n\ntype union_int =\n  | Union_int_0 of dummy1 [@js 0]\n  | Union_int_1 of dummy2 [@js 1]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]\n\ntype union_float =\n  | Union_float_0_1 of dummy1 [@js 0.1]\n  | Union_float_1_1 of dummy2 [@js 1.1]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]\n\ntype union_string =\n  | Union_string_foo of dummy3 [@js \"foo\"]\n  | Union_string_bar of dummy4 [@js \"bar\"]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]\n\n(* if both true and false are expected, the boolean part of `_of_js` should not have the default case *)\ntype union_bool =\n  | Union_bool_true of dummy5 [@js true]\n  | Union_bool_false of dummy6 [@js false]\n  [@@js.union on_field \"tag\"]\n\n(* otherwise, an unknown boolean value should trigger `assert false` *)\ntype union_bool_partial =\n  | Union_bool_true of dummy5 [@js true]\n  [@@js.union on_field \"tag\"]\n\n(* or it should be mapped to `Unknown` *)\ntype union_bool_partial2 =\n  | Union_bool_true of dummy5 [@js true]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]\n\n(* if both true and false are expected, the boolean part of `_of_js` should not have the default case *)\ntype union_mixed =\n  | Union_int_0 of dummy1 [@js 0]\n  | Union_int_1 of dummy2 [@js 1]\n  | Union_float_0_1 of dummy1 [@js 0.1]\n  | Union_float_1_1 of dummy2 [@js 1.1]\n  | Union_string_foo of dummy3 [@js \"foo\"]\n  | Union_string_bar of dummy4 [@js \"bar\"]\n  | Union_bool_true of dummy5 [@js true]\n  | Union_bool_false of dummy6 [@js false]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]\n\n(* otherwise, an unknown boolean value should be mapped to `Unknown` *)\ntype union_mixed_partial_bool =\n  | Union_int_0 of dummy1 [@js 0]\n  | Union_int_1 of dummy2 [@js 1]\n  | Union_float_0_1 of dummy1 [@js 0.1]\n  | Union_float_1_1 of dummy2 [@js 1.1]\n  | Union_string_foo of dummy3 [@js \"foo\"]\n  | Union_string_bar of dummy4 [@js \"bar\"]\n  | Union_bool_true of dummy5 [@js true]\n  | Unknown of Ojs.t [@js.default]\n  [@@js.union on_field \"tag\"]"
  }
]