Bun is a new Javascript runtime. It is fast, and it has a very fast bun:ffi.
Based on bun:ffi, I just wrote an experimental package jlbun which enables using Julia from Javascript/Typescript.
The package has been published at NPM, so you can directly install it via npm install jlbun. However, since a thin dynamic library needs to be built locally, cmake is needed. Only Linux and macOS are supported right now, since Bun does not support Windows yet.
To use the package, you need both Julia and Bun. There are a few examples in the repo’s README.
It is still at a very early stage. Feedbacks and suggestions are welcome, especially those related to the following topics:
- API design
 
- Memory management
 
- Performance
 
             
            
              
              
              14 Likes
            
            
           
          
            
            
              With the latest update, we can now do something interesting, e.g., combining Julia’s Task with Javascript’s Promise. Here is an example:
import { Julia, JuliaFunction, JuliaTask, JuliaValue } from "../jlbun";
Julia.init();
const promises: Promise<JuliaValue>[] = [];
const func = Julia.eval(`function ()
  println(Threads.threadid());
  ans = 0;
  for i in 1:1000
    ans += i
  end
  ans
end
`) as JuliaFunction;
for (let i = 0; i < Julia.nthreads; i++) {
  promises.push(JuliaTask.from(func).schedule(i).value);
}
const results = (await Promise.all(promises)).map(promise => promise.value);
console.log(results);
Julia.close();
             
            
              
              
              3 Likes
            
            
           
          
            
            
              Very interesting. Since Julia can ccall libjulia, we can do the following trick:
const interpolated = `
  function ()
    ptr = ccall(:jl_call, 
      Ptr{Nothing}, 
      (Ptr{Nothing}, Ptr{Nothing}, Cint),
      convert(Ptr{Nothing}, ${funcPtr}),
      convert(Ptr{Nothing}, ${argsPtr}),
      ${argsLength},
    )
    
    unsafe_pointer_to_objref(ptr)
  end
`;
Just eval() the interpolated string above, and we will get a zero-argument version of the original function. The wrapped function can then be used to initiate a Task.
             
            
              
              
              1 Like
            
            
           
          
            
            
              Using Bun’s JSCallback, we can now use JS functions in the Julia scope:
import { Julia, JuliaArray, JuliaFunction, safeCString } from "jlbun";
Julia.init();
const jsFunc = (x: number) => {
  return safeCString(x.toString());
};
const cb = JuliaFunction.from(jsFunc, {
  returns: "cstring",
  args: ["i32"],
});
const arr = JuliaArray.from(new Int32Array([1, 10, 20, 30, 100]));
Julia.Base["sort!"].callWithKwargs({ by: cb, rev: true }, arr);
Julia.println(arr); // Int32[30, 20, 100, 10, 1]
cb.close();
Julia.close();
             
            
              
              
              2 Likes