Cannot read property '_handle' of null when compiled code uses Curry

Hello there,

I’m a newcomer (started learning rescript yesterday), and I might be doing this wrong so bare with me…

I learned rescript can perform interop with native Node.JS modules, and I wanted to see if the basic http server code would be feasable using rescript interop so here is what I wrote:

type request = {
  method: string,
  url: string,
  httpVersion: string,
  statusCode: int
}

type response = {
  end: (string) => unit,
  setHeader: (string, string) => unit,
  mutable statusCode: int
}

type server = {
  listen: (int, string, int, () => unit) => unit
}

@module("http")
external createServer: ((request, response) => unit) => server = "createServer"

let server = createServer((_, res) => {
  res.setHeader("Content-Type", "application/json")
  res.end("hello world")
})

server.listen(8000, "127.0.0.1", 511, (_) => {
  Js.Console.log("Listening...")
})

When I check the compiled code, I notice it uses uncurry functions. And it looks like this causes some issue because when I run the compiled js code using node src/index.js, this is what I get from Node interpreter:

node:net:1396
  if (this._handle) {
           ^

TypeError: Cannot read property '_handle' of null
    at Server.listen (node:net:1396:12)
    at app (/home/node/node_modules/rescript/lib/js/curry.js:24:12)
    at Object._4 (/home/node/node_modules/rescript/lib/js/curry.js:214:16)
    at Object.<anonymous> (/home/node/src/index.js:12:7)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47

Note that when I manually change in the compiled code from this code

Curry._4(server.listen, 8000, "127.0.0.1", 511, (function (param) {
    console.log("Listening...");
}));

To this

server.listen(8000, "127.0.0.1", 511, (function (param) {
    console.log("Listening...");
}));

The interpreter no longer throw an error, and I can see “Listening…” on my console.

Do I do this wrong? Is using “unit” as a return type leading to this error?

Hi, it is recommended to have a look at generated code if something is going wrong, especially for bindings

It seems your bindings is wrong

The callback seems to be an uncurried function, (almost all bindings should be uncurried). A potential fix is ((.request, response) => unit) => server

Thanks for the quick reply :slight_smile:

Now the compiler is saying I should indeed use an uncurried function:

  52 │ }
  53 │
  54 │ let server = createServer((req, res) => {
  55 │     let content = switch getRouteParts(req.method, req.url) {
   . │ ...
  61 │     res.end(content)
  62 │ })
  63 │
  64 │ server.listen(8000, "127.0.0.1", 511, (_) => {

  This expression is expected to have an uncurried function

I’ll try to work around this thanks!

Edit

Yep, had to mark all the interop functions as uncurried, this little dot saved the day thanks again @Hongbo

Now everything works peacefully!

1 Like