PuerTS  is an open-source integration framework that enables developers to script game logic in JavaScript or TypeScript while seamlessly interfacing with native C++ or C# game engines such as Unreal Engine and Unity.
OneJS use PuerTS for easy access to the 3 JS backends it provides: V8, QuickJS, and NodeJS.
Switching Backends
Having 3 backends to choose from is nice. Use QuickJS for its small build size (~20MB). Use V8 for raw speed and WebAssembly. Use NodeJS for its robust ecosystem.
To check which backend you’re currently using, go to Tools > OneJS > Backend
in the Unity menu.
If you want to switch to a different backend, you’ll need to close the Unity Editor first. Then in your terminal or VSCode, run:
QuickJS
npm run switch quickjs
Unity doesn’t have a reliable way to unload and replace native plugins while it’s running, so the editor needs to be closed for the switch to work properly.
PuerTS Primer
Source: chexiongsheng/puerts_unity_demo 
// You can access all C# namespaces and classes from the CS. global namespace in JS
const { $ref, $unref, $generic, $promise, $typeof } = puer;
// Static function
CS.UnityEngine.Debug.Log('hello world');
// Object construction
let obj = new CS.PuertsTest.DerivedClass();
// Instance member access
obj.BMFunc(); // Parent class method
obj.DMFunc(CS.PuertsTest.MyEnum.E1); // Subclass method
console.log(obj.BMF, obj.DMF);
obj.BMF = 10; // Parent class property
obj.DMF = 30; // Subclass property
console.log(obj.BMF, obj.DMF);
// Static members
console.log(CS.PuertsTest.BaseClass.BSF, CS.PuertsTest.DerivedClass.DSF, CS.PuertsTest.DerivedClass.BSF);
// Delegates, events
// If you don't need -= later, you can pass a function as a delegate directly like this
obj.MyCallback = msg => console.log("do not need remove, msg=" + msg);
// Delegates created via new can later use this reference for -=
let delegate = new CS.PuertsTest.MyCallback(msg => console.log('can be removed, msg=' + msg));
// Since TS doesn't support operator overloading, Delegate.Combine is equivalent to obj.myCallback += delegate in C#
obj.MyCallback = CS.System.Delegate.Combine(obj.MyCallback, delegate);
obj.Trigger();
// Delegate.Remove is equivalent to obj.myCallback -= delegate in C#
obj.MyCallback = CS.System.Delegate.Remove(obj.MyCallback, delegate);
obj.Trigger();
// Events
obj.add_MyEvent(delegate);
obj.Trigger();
obj.remove_MyEvent(delegate);
obj.Trigger();
// Static events
CS.PuertsTest.DerivedClass.add_MyStaticEvent(delegate);
obj.Trigger();
CS.PuertsTest.DerivedClass.remove_MyStaticEvent(delegate);
obj.Trigger();
// Variable arguments
obj.ParamsFunc(1024, 'haha', 'hehe', 'heihei');
// in out parameters
let p1 = $ref(1);
let p2 = $ref(10);
let ret = obj.InOutArgFunc(100, p1, p2);
console.log('ret=' + ret + ', out=' + $unref(p1) + ', ref=' + $unref(p2));
// Generics
// First, instantiate generic parameters through $generic
let List = $generic(CS.System.Collections.Generic.List$1, CS.System.Int32); //$generic invocation performance isn't great, so it's recommended to use it only once per project or at least per file for the same generic parameter
let Dictionary = $generic(CS.System.Collections.Generic.Dictionary$2, CS.System.String, List);
let lst = new List();
lst.Add(1);
lst.Add(0);
lst.Add(2);
lst.Add(4);
obj.PrintList(lst);
let dic = new Dictionary();
dic.Add("aaa", lst);
obj.PrintList(dic.get_Item("aaa"));
let Arr = CS.System.Array.CreateInstance(puer.$typeof(CS.System.String), 3);
Arr.SetValue("aaa", 0);
Arr.SetValue("bbb", 1);
Arr.SetValue("ccc", 2);
obj.PrintArray(Arr);
// arraybuffer
let ab = obj.GetAb(5);
let u8a0 = new Uint8Array(ab);
console.log(obj.SumOfAb(u8a0));
let u8a1 = new Uint8Array(2);
u8a1[0] = 123;
u8a1[1] = 101;
console.log(obj.SumOfAb(u8a1));
// Engine API
let go = new CS.UnityEngine.GameObject("testObject");
go.AddComponent($typeof(CS.UnityEngine.ParticleSystem));
go.transform.position = new CS.UnityEngine.Vector3(7, 8, 9);
// Extension methods
puer.$extension(CS.PuertsTest.BaseClass, CS.PuertsTest.BaseClassExtension);
obj.PlainExtension();
obj.Extension1();
obj.Extension2(go);
let obj1 = new CS.PuertsTest.BaseClass1();
obj.Extension2(obj1);