1 // Copyright 2022-present 650 Industries. All rights reserved. 2 3 // MARK: - Arguments 4 5 /** 6 Tries to cast given argument to the type that is wrapped by the dynamic type. 7 - Parameters: 8 - argument: A value to be cast. If it's a ``JavaScriptValue``, it's first unpacked to the raw value. 9 - argumentType: Something that implements ``AnyDynamicType`` and knows how to cast the argument. 10 - Returns: A new value converted according to the dynamic type. 11 - Throws: Rethrows various exceptions that could be thrown by the dynamic types. 12 */ 13 internal func castArgument(_ argument: Any, toType argumentType: AnyDynamicType) throws -> Any { 14 // TODO: Accept JavaScriptValue and JavaScriptObject as argument types. 15 if argumentType is DynamicSharedObjectType { 16 return try argumentType.cast(argument) 17 } 18 if let argument = argument as? JavaScriptValue { 19 return try argumentType.cast(argument.getRaw()) 20 } 21 return try argumentType.cast(argument) 22 } 23 24 /** 25 Same as ``castArgument(_:argumentType:)`` but for an array of arguments. 26 - Parameters: 27 - arguments: An array of arguments to be cast. 28 - argumentTypes: An array of the dynamic types in the same order as the array of arguments. 29 - Returns: An array of arguments after casting. Its size is the same as the input arrays. 30 - Throws: ``InvalidArgsNumberException`` when the sizes of arrays passed as parameters are not equal. 31 Rethrows exceptions thrown by ``castArgument(_:argumentType:)``. 32 */ 33 internal func castArguments(_ arguments: [Any], toTypes argumentTypes: [AnyDynamicType]) throws -> [Any] { 34 if arguments.count != argumentTypes.count { 35 throw InvalidArgsNumberException((received: arguments.count, expected: argumentTypes.count)) 36 } 37 return try arguments.enumerated().map { index, argument in 38 let argumentType = argumentTypes[index] 39 40 do { 41 return try castArgument(argument, toType: argumentType) 42 } catch { 43 throw ArgumentCastException((index: index, type: argumentType)).causedBy(error) 44 } 45 } 46 } 47 48 // MARK: - Exceptions 49 50 internal class InvalidArgsNumberException: GenericException<(received: Int, expected: Int)> { 51 override var reason: String { 52 "Received \(param.received) arguments, but \(param.expected) was expected" 53 } 54 } 55 56 internal class ArgumentCastException: GenericException<(index: Int, type: AnyDynamicType)> { 57 override var reason: String { 58 "Argument at index '\(param.index)' couldn't be cast to type \(param.type.description)" 59 } 60 } 61 62 private class ModuleUnavailableException: GenericException<String> { 63 override var reason: String { 64 "Module '\(param)' is no longer available" 65 } 66 } 67