1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "ExpoModulesHostObject.h" 4 #include "LazyObject.h" 5 6 #include <folly/dynamic.h> 7 #include <jsi/JSIDynamic.h> 8 #include <react/bridging/LongLivedObject.h> 9 10 namespace jsi = facebook::jsi; 11 12 namespace expo { 13 14 ExpoModulesHostObject::ExpoModulesHostObject(JSIInteropModuleRegistry *installer) 15 : installer(installer) {} 16 17 /** 18 * Clears jsi references held by JSRegistry and JavaScriptRuntime. 19 */ 20 ExpoModulesHostObject::~ExpoModulesHostObject() { 21 facebook::react::LongLivedObjectCollection::get().clear(); 22 installer->jsRegistry.reset(); 23 installer->runtimeHolder.reset(); 24 } 25 26 jsi::Value ExpoModulesHostObject::get(jsi::Runtime &runtime, const jsi::PropNameID &name) { 27 auto cName = name.utf8(runtime); 28 29 if (!installer->hasModule(cName)) { 30 modulesCache.erase(cName); 31 return jsi::Value::undefined(); 32 } 33 if (UniqueJSIObject &cachedObject = modulesCache[cName]) { 34 return jsi::Value(runtime, *cachedObject); 35 } 36 37 // Create a lazy object for the specific module. It defers initialization of the final module object. 38 LazyObject::Shared moduleLazyObject = std::make_shared<LazyObject>( 39 [this, cName](jsi::Runtime &rt) { 40 auto module = installer->getModule(cName); 41 module->cthis()->jsiInteropModuleRegistry = installer; 42 return module->cthis()->getJSIObject(rt); 43 }); 44 45 // Save the module's lazy host object for later use. 46 modulesCache[cName] = std::make_unique<jsi::Object>( 47 jsi::Object::createFromHostObject(runtime, moduleLazyObject)); 48 49 return jsi::Value(runtime, *modulesCache[cName]); 50 } 51 52 void ExpoModulesHostObject::set(jsi::Runtime &runtime, const jsi::PropNameID &name, 53 const jsi::Value &value) { 54 throw jsi::JSError( 55 runtime, 56 "RuntimeError: Cannot override the host object for expo module '" + name.utf8(runtime) + "'" 57 ); 58 } 59 60 std::vector<jsi::PropNameID> ExpoModulesHostObject::getPropertyNames(jsi::Runtime &rt) { 61 auto names = installer->getModulesName(); 62 size_t size = names->size(); 63 std::vector<jsi::PropNameID> result; 64 result.reserve(size); 65 for (int i = 0; i < size; i++) { 66 result.push_back( 67 jsi::PropNameID::forUtf8(rt, names->getElement(i)->toStdString()) 68 ); 69 } 70 return result; 71 } 72 } // namespace expo 73