# \[ANN\] jlbun: use Julia from Bun

**URL:** <https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348>\
**Category:** Package Announcements\
**Tags:** javascript, typescript, bun\
**Created:** [December 31, 2022, 3:14am UTC](https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348 "2022-12-31T03:14:05Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lucifer1004](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucifer1004/32/22311_2.png) [@lucifer1004](https://discourse.julialang.org/u/lucifer1004)\
**Post date:** [December 31, 2022, 3:14am UTC](https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348/1 "2022-12-31T03:14:05Z")

</div>

[`Bun`](https://bun.sh/) 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`](https://github.com/lucifer1004/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

---

<div class="post-metadata">

**Author:** ![lucifer1004](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucifer1004/32/22311_2.png) [@lucifer1004](https://discourse.julialang.org/u/lucifer1004)\
**Post date:** [January 1, 2023, 6:05pm UTC](https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348/2 "2023-01-01T18:05:11Z")

</div>

With the latest update, we can now do something interesting, e.g., combining Julia’s `Task` with Javascript’s `Promise`. Here is an example:

```javascript
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();

```

---

<div class="post-metadata">

**Author:** ![lucifer1004](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucifer1004/32/22311_2.png) [@lucifer1004](https://discourse.julialang.org/u/lucifer1004)\
**Post date:** [January 2, 2023, 3:37pm UTC](https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348/3 "2023-01-02T15:37:09Z")

</div>

Very interesting. Since Julia can `ccall` libjulia, we can do the following trick:

```javascript
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`.

---

<div class="post-metadata">

**Author:** ![lucifer1004](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucifer1004/32/22311_2.png) [@lucifer1004](https://discourse.julialang.org/u/lucifer1004)\
**Post date:** [January 3, 2023, 4:53pm UTC](https://discourse.julialang.org/t/ann-jlbun-use-julia-from-bun/92348/4 "2023-01-03T16:53:47Z")

</div>

Using Bun’s `JSCallback`, we can now use JS functions in the Julia scope:

```javascript
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();

```
