mozilla / mentat

UNMAINTAINED A persistent, relational store inspired by Datomic and DataScript.
https://mozilla.github.io/mentat/
Apache License 2.0
1.65k stars 115 forks source link

JS Interface #608

Open fluffyemily opened 6 years ago

fluffyemily commented 6 years ago

Create a JS interface to Mentat allowing all of mentat's FFI exposed functionality to be callable from JS.

victorporof commented 6 years ago

It seems to me that the current ffi architecture is mostly (if not entirely) built around passing pointers to the outside world. We do a great job and making sure things are both opaque and don't ever die (by intentionally "leaking" thanks to the boxing trick).

I'm not really comfortable with how the API functions in its entirety, so what I'd like to understand is if we're ever interested in providing data directly consumable by the outside world (e.g. actual final results instead of pointers to opaque things that would eventually end up back into mentat). If this is indeed the case, ffi for JS is going to be especially interesting because

  1. The asm.js case is different from the wasm case in terms of where things are explicit vs. implicit
  2. The asm.js case requires a bit of arcane memory management, since ccall and cwrap don't (and can't) automatically deallocate. This is going to be a complexity issue for anything that's not a primitive.
  3. Although there's the possibility of "sharing memory", it to is quite arcane and it's incredibly awkward to avoid cloning things when passing the asm.js/wasm to js boundary. There's some efforts underway over at the web assembly team, so we might want to cross pollinate there if we're really interested in this.
fluffyemily commented 6 years ago

There are certainly cases where we do want to provide data rather than opaque pointers over the FFI. Examples of this are:

There are other cases when we may want to provide single data or an opaque pointer. TypedValues/ query results are an example of this. In many cases, such as a scalar or tuple query execution result or fetching an value for an attribute, where the passing of the raw data would make sense. However, in the case of Rel or Col query execution we may not want to serialise the entire result set, but provide a cursor such that we can iterate or reference only certain parts of the result set. Also, once we have pull expressions it is possible we may want to on provide a particular 'level' of a result set at a time. In these cases we'd need more than one way of providing results according to the needs of the consumer.

It's definitely something worth considering though, especially if we can do it in a way that doesn't have a large overhead in transformation.