1 // Copyright 2022-present 650 Industries. All rights reserved. 2 3 // FIXME: Calling module's functions needs solid refactoring to not reference the module holder. 4 // Instead, it should be possible to directly call the function instance from here. (added by @tsapeta) 5 6 /** 7 Creates a block that is executed when the module's async function is called. 8 */ 9 internal func createAsyncFunctionBlock(holder: ModuleHolder, name functionName: String) -> JSAsyncFunctionBlock { 10 let moduleName = holder.name 11 return { [weak holder, moduleName] args, resolve, reject in 12 guard let holder = holder else { 13 let exception = ModuleUnavailableException(moduleName) 14 reject(exception.code, exception.description, exception) 15 return 16 } 17 holder.call(function: functionName, args: args) { result, error in 18 if let error = error { 19 reject(error.code, error.description, error) 20 } else { 21 resolve(result) 22 } 23 } 24 } 25 } 26 27 /** 28 Creates a block that is executed when the module's sync function is called. 29 */ 30 internal func createSyncFunctionBlock(holder: ModuleHolder, name functionName: String) -> JSSyncFunctionBlock { 31 return { [weak holder] args in 32 guard let holder = holder else { 33 return nil 34 } 35 return holder.callSync(function: functionName, args: args) 36 } 37 } 38 39 /** 40 If given argument is a JavaScriptValue, it's unpacked and converted to corresponding Foundation type. 41 Otherwise, the argument is returned as is. 42 */ 43 internal func unpackIfJavaScriptValue(_ value: Any) -> Any { 44 if let value = value as? JavaScriptValue { 45 return value.getRaw() as Any 46 } 47 return value 48 } 49 50 private class ModuleUnavailableException: GenericException<String> { 51 override var reason: String { 52 "Module '\(param)' is no longer available" 53 } 54 } 55