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