164f5c95fSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
264f5c95fSŁukasz Kosmaty
364f5c95fSŁukasz Kosmaty #include "ExpoModulesHostObject.h"
4b627df43SŁukasz Kosmaty #include "LazyObject.h"
564f5c95fSŁukasz Kosmaty
664f5c95fSŁukasz Kosmaty #include <folly/dynamic.h>
764f5c95fSŁukasz Kosmaty #include <jsi/JSIDynamic.h>
8695fef9bSKudo Chien #include <react/bridging/LongLivedObject.h>
964f5c95fSŁukasz Kosmaty
1064f5c95fSŁukasz Kosmaty namespace jsi = facebook::jsi;
1164f5c95fSŁukasz Kosmaty
1264f5c95fSŁukasz Kosmaty namespace expo {
1364f5c95fSŁukasz Kosmaty
ExpoModulesHostObject(JSIInteropModuleRegistry * installer)1464f5c95fSŁukasz Kosmaty ExpoModulesHostObject::ExpoModulesHostObject(JSIInteropModuleRegistry *installer)
1564f5c95fSŁukasz Kosmaty : installer(installer) {}
1664f5c95fSŁukasz Kosmaty
1733ae33eaSŁukasz Kosmaty /**
1833ae33eaSŁukasz Kosmaty * Clears jsi references held by JSRegistry and JavaScriptRuntime.
1933ae33eaSŁukasz Kosmaty */
~ExpoModulesHostObject()2033ae33eaSŁukasz Kosmaty ExpoModulesHostObject::~ExpoModulesHostObject() {
21695fef9bSKudo Chien facebook::react::LongLivedObjectCollection::get().clear();
2233ae33eaSŁukasz Kosmaty installer->jsRegistry.reset();
2333ae33eaSŁukasz Kosmaty installer->runtimeHolder.reset();
24*29e8b6f8SŁukasz Kosmaty installer->jsInvoker.reset();
25*29e8b6f8SŁukasz Kosmaty installer->nativeInvoker.reset();
26*29e8b6f8SŁukasz Kosmaty installer->jniDeallocator.reset();
2733ae33eaSŁukasz Kosmaty }
2833ae33eaSŁukasz Kosmaty
get(jsi::Runtime & runtime,const jsi::PropNameID & name)2964f5c95fSŁukasz Kosmaty jsi::Value ExpoModulesHostObject::get(jsi::Runtime &runtime, const jsi::PropNameID &name) {
3064f5c95fSŁukasz Kosmaty auto cName = name.utf8(runtime);
31b627df43SŁukasz Kosmaty
32b627df43SŁukasz Kosmaty if (!installer->hasModule(cName)) {
33b627df43SŁukasz Kosmaty modulesCache.erase(cName);
3464f5c95fSŁukasz Kosmaty return jsi::Value::undefined();
3564f5c95fSŁukasz Kosmaty }
36b627df43SŁukasz Kosmaty if (UniqueJSIObject &cachedObject = modulesCache[cName]) {
37b627df43SŁukasz Kosmaty return jsi::Value(runtime, *cachedObject);
38b627df43SŁukasz Kosmaty }
3964f5c95fSŁukasz Kosmaty
40b627df43SŁukasz Kosmaty // Create a lazy object for the specific module. It defers initialization of the final module object.
41b627df43SŁukasz Kosmaty LazyObject::Shared moduleLazyObject = std::make_shared<LazyObject>(
42b627df43SŁukasz Kosmaty [this, cName](jsi::Runtime &rt) {
43b627df43SŁukasz Kosmaty auto module = installer->getModule(cName);
4464f5c95fSŁukasz Kosmaty module->cthis()->jsiInteropModuleRegistry = installer;
45b627df43SŁukasz Kosmaty return module->cthis()->getJSIObject(rt);
46b627df43SŁukasz Kosmaty });
47b627df43SŁukasz Kosmaty
48b627df43SŁukasz Kosmaty // Save the module's lazy host object for later use.
49b627df43SŁukasz Kosmaty modulesCache[cName] = std::make_unique<jsi::Object>(
50b627df43SŁukasz Kosmaty jsi::Object::createFromHostObject(runtime, moduleLazyObject));
51b627df43SŁukasz Kosmaty
52b627df43SŁukasz Kosmaty return jsi::Value(runtime, *modulesCache[cName]);
5364f5c95fSŁukasz Kosmaty }
5464f5c95fSŁukasz Kosmaty
set(jsi::Runtime & runtime,const jsi::PropNameID & name,const jsi::Value & value)5564f5c95fSŁukasz Kosmaty void ExpoModulesHostObject::set(jsi::Runtime &runtime, const jsi::PropNameID &name,
5664f5c95fSŁukasz Kosmaty const jsi::Value &value) {
5764f5c95fSŁukasz Kosmaty throw jsi::JSError(
5864f5c95fSŁukasz Kosmaty runtime,
5964f5c95fSŁukasz Kosmaty "RuntimeError: Cannot override the host object for expo module '" + name.utf8(runtime) + "'"
6064f5c95fSŁukasz Kosmaty );
6164f5c95fSŁukasz Kosmaty }
6264f5c95fSŁukasz Kosmaty
getPropertyNames(jsi::Runtime & rt)6364f5c95fSŁukasz Kosmaty std::vector<jsi::PropNameID> ExpoModulesHostObject::getPropertyNames(jsi::Runtime &rt) {
6478b3dbc7SŁukasz Kosmaty auto names = installer->getModulesName();
6578b3dbc7SŁukasz Kosmaty size_t size = names->size();
66d3f89796SBartłomiej Klocek std::vector<jsi::PropNameID> result;
67d3f89796SBartłomiej Klocek result.reserve(size);
6878b3dbc7SŁukasz Kosmaty for (int i = 0; i < size; i++) {
6978b3dbc7SŁukasz Kosmaty result.push_back(
7078b3dbc7SŁukasz Kosmaty jsi::PropNameID::forUtf8(rt, names->getElement(i)->toStdString())
7178b3dbc7SŁukasz Kosmaty );
7278b3dbc7SŁukasz Kosmaty }
7378b3dbc7SŁukasz Kosmaty return result;
7464f5c95fSŁukasz Kosmaty }
7564f5c95fSŁukasz Kosmaty } // namespace expo
76