Skip to content

Commit

Permalink
feat: Support adopting Prototypes and NativeState (Nitro support 🔥) (#…
Browse files Browse the repository at this point in the history
…223)

* feat: Add NativeState creator

* Create dummy native

* Update App.tsx

* Get NativeState

* Update App.tsx

* fix: Copy over prototype

* fix: Only look for native state & prototype

* Revert unnecessary changes
  • Loading branch information
mrousavy authored Nov 6, 2024
1 parent e8a63b4 commit 9ef89f6
Showing 1 changed file with 32 additions and 22 deletions.
54 changes: 32 additions & 22 deletions cpp/wrappers/WKTJsiObjectWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,8 @@ class JsiObjectWrapper : public JsiHostObject,
} else {
setObjectValue(runtime, object);
}
// NativeState functionality is also available in JSC with react-native 74+, but let's just keep this simple for now
#if JS_RUNTIME_HERMES
updateNativeState(runtime, object);
#endif
}

#if JS_RUNTIME_HERMES
void updateNativeState(jsi::Runtime &runtime, jsi::Object &obj) {
if (obj.hasNativeState(runtime)) {
_nativeState = obj.getNativeState(runtime);
} else {
_nativeState = nullptr;
}
}
#endif

/**
* Overridden get value where we convert from the internal representation to
* a jsi value
Expand All @@ -91,13 +77,21 @@ class JsiObjectWrapper : public JsiHostObject,
}
}

jsi::Object obj = getObject(runtime);
#if JS_RUNTIME_HERMES
if (_nativeState != nullptr) {
obj.setNativeState(runtime, _nativeState);
if (_prototype != nullptr && _nativeState != nullptr) {
// We have a Prototype and NativeState!
// It's likely a Nitro HybridObject that does not have properties by itself.
jsi::Object Object = runtime.global().getPropertyAsObject(runtime, "Object");
jsi::Function create = Object.getPropertyAsFunction(runtime, "create");
jsi::Value result = create.call(runtime, _prototype->getValue(runtime));
result.getObject(runtime).setNativeState(runtime, _nativeState);
return result;
} else {
jsi::Object obj = getObject(runtime);
if (_nativeState != nullptr) {
obj.setNativeState(runtime, _nativeState);
}
return obj;
}
#endif
return obj;
}

jsi::Object getObject(jsi::Runtime &runtime) {
Expand Down Expand Up @@ -208,6 +202,23 @@ class JsiObjectWrapper : public JsiHostObject,
nameString,
JsiWrapper::wrap(runtime, value, this, getUseProxiesForUnwrapping()));
}

if (obj.hasNativeState(runtime)) {
// 1. Get NativeState and keep it in memory.
_nativeState = obj.getNativeState(runtime);
// 2. If we have a NativeState, we likely also have a prototype chain. Recursively copy those over.
jsi::Object Object = runtime.global().getPropertyAsObject(runtime, "Object");
jsi::Function getPrototypeOf = Object.getPropertyAsFunction(runtime, "getPrototypeOf");
jsi::Value prototype = getPrototypeOf.call(runtime, obj);
if (prototype.isObject()) {
jsi::Object prototypeObject = prototype.getObject(runtime);
_prototype = std::make_shared<JsiObjectWrapper>(nullptr, false);
_prototype->setObjectValue(runtime, prototypeObject);
}
} else {
_nativeState = nullptr;
_prototype = nullptr;
}
}

void setHostObjectValue(jsi::Runtime &runtime, jsi::Object &obj) {
Expand Down Expand Up @@ -252,11 +263,10 @@ class JsiObjectWrapper : public JsiHostObject,
}

private:
std::shared_ptr<JsiObjectWrapper> _prototype;
std::map<std::string, std::shared_ptr<JsiWrapper>> _properties;
std::shared_ptr<jsi::HostFunctionType> _hostFunction;
std::shared_ptr<jsi::HostObject> _hostObject;
#if JS_RUNTIME_HERMES
std::shared_ptr<jsi::NativeState> _nativeState;
#endif
};
} // namespace RNWorklet

0 comments on commit 9ef89f6

Please sign in to comment.