Skip to content

Instantly share code, notes, and snippets.

@tmikov
Last active August 8, 2024 10:43
Show Gist options
  • Save tmikov/3e6310abcd77ff8066297cdd4927b44d to your computer and use it in GitHub Desktop.
Save tmikov/3e6310abcd77ff8066297cdd4927b44d to your computer and use it in GitHub Desktop.
Example usage of NativeState
/// Pseudocode implementation of jsi::Object::setNativeState()
function setNativeState(obj, ns) { obj.__ns = ns; }
/// Pseudocode implementation of jsi::object::getNativeState()
function getNativeState(obj) { return obj.__ns; }
/// This is a HostFunction, shown as JS pseudo-code
/// Create and initialize NativeState instance.
function _installNativeState(constructor, object, ...args) {
switch (constructor.name) {
case "Camera":
setNativeState(object, {marker: "Camera", param: args[0]});
break;
default:
throw Error("Invalid native constructor " + constructor.name);
}
}
/// This is a HostFunction, shown as JS pseudo-code
/// Create and populate native methods
function _installMethods(constructor, prototype) {
switch (constructor.name) {
case "Camera":
// Attach a native HostFunction, shown here as JS
// for illustration.
prototype.update = function update() {
let ns = getNativeState(this);
if (ns?.marker !== "Camera")
throw TypeError("Not a Camera object");
return ns.param++;
}
break;
default:
throw Error("Invalid native constructor " + constructor.name);
}
}
/// This defines the camera Class, backed by native data and
/// native methods.
class Camera {
name;
constructor(name, param) {
// JS properties work too.
this.name = name;
// Create NativeState, possibly using constructor arguments,
// and attach it.
_installNativeState(Camera, this, param);
}
// JS methods work too.
bar() {}
}
// Attach the native methods.
_installMethods(Camera, Camera.prototype);
// Example usage.
let c = new Camera("my cam", 10);
c.bar();
console.log(c.update());
console.log(c.update());
console.log(c.update());
@mrousavy
Copy link

mrousavy commented Aug 8, 2024

Really helpful to see how this would work from the JS side by using classes and allowing new / instanceof, thanks for sharing! 🙏

I went the C++ route, created a jsi::Object for each prototype on that side and created my instance using Object.create(prototype). Set up the prototype chain properly to represent inheritance, and all objects have associated nativestate automatically. Works like a charm, and all JS functions are HostFunctions - meaning they could be shared between Runtimes/worklet contexts! (which a JS class currently can't)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment