Writing a web application framework plugin


#1

Hi all,

I’m trying to write a plugin in Tern for a Node.js web application framework, i.e. Express. I’ve come up with a minimal example that illustrates my problem.

Let’s say we have two global function definitions in our typedefs for the framework:

const defs = {
  "foo": "fn(fun: fn(arg: +Object))",
  "bar": "fn(fun: fn(arg: +Object))"
}

When analyzing the types of the following piece of code:

foo(arg => { arg.x = 1 })
bar(arg => { arg.y = 1 })

Tern will tell us that the type of the argument in both functions is {x: number, y: number}
My suspicion is, since Tern can’t detect any call to one of the inner functions, that it will use the same object type for the argument in both functions.
How do you tell Tern to treat the argument in these two functions seperately, i.e. as two seperate objects?

Cheers,

Max


#2

I found a way around my issue. The trick I used is to type the argument of the inner function as an unknown type ("?") and provide the argument type in a custom effect to the function.

const defs = {
  "foo": {
    "!type": "fn(fun: fn(arg: ?))",
    "!effects": ["custom provideArg"]
  },
  "bar": {
    "!type": "fn(fun: fn(arg: ?))",
    "!effects": ["custom provideArg"]
  }
}
...
infer.registerFunction("provideArg", function (self, args, argNodes) {
  const fun = args[0].getFunctionType()
  const obj = new infer.Obj
  obj.propagate(fun.args[0])
}

I guess, in this case, Tern will not start propagating things through the type graph until we provide the argument with some type. Are all the +Object's in a typedef referring to the same instance of an object then?