(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc)
| 3021 | }); |
| 3022 | }}; |
| 3023 | function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) { |
| 3024 | // humanName: a human-readable string name for the function to be generated. |
| 3025 | // argTypes: An array that contains the embind type objects for all types in the function signature. |
| 3026 | // argTypes[0] is the type object for the function return value. |
| 3027 | // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method. |
| 3028 | // argTypes[2...] are the actual function parameters. |
| 3029 | // classType: The embind type object for the class to be bound, or null if this is not a method of a class. |
| 3030 | // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code. |
| 3031 | // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling. |
| 3032 | var argCount = argTypes.length; |
| 3033 | |
| 3034 | if (argCount < 2) { |
| 3035 | throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); |
| 3036 | } |
| 3037 | |
| 3038 | var isClassMethodFunc = (argTypes[1] !== null && classType !== null); |
| 3039 | |
| 3040 | // Free functions with signature "void function()" do not need an invoker that marshalls between wire types. |
| 3041 | // TODO: This omits argument count check - enable only at -O3 or similar. |
| 3042 | // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) { |
| 3043 | // return FUNCTION_TABLE[fn]; |
| 3044 | // } |
| 3045 | |
| 3046 | // Determine if we need to use a dynamic stack to store the destructors for the function parameters. |
| 3047 | // TODO: Remove this completely once all function invokers are being dynamically generated. |
| 3048 | var needsDestructorStack = false; |
| 3049 | |
| 3050 | for (var i = 1; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. |
| 3051 | if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { // The type does not define a destructor function - must use dynamic stack |
| 3052 | needsDestructorStack = true; |
| 3053 | break; |
| 3054 | } |
| 3055 | } |
| 3056 | |
| 3057 | var returns = (argTypes[0].name !== "void"); |
| 3058 | |
| 3059 | var argsList = ""; |
| 3060 | var argsListWired = ""; |
| 3061 | for (var i = 0; i < argCount - 2; ++i) { |
| 3062 | argsList += (i!==0?", ":"")+"arg"+i; |
| 3063 | argsListWired += (i!==0?", ":"")+"arg"+i+"Wired"; |
| 3064 | } |
| 3065 | |
| 3066 | var invokerFnBody = |
| 3067 | "return function "+makeLegalFunctionName(humanName)+"("+argsList+") {\n" + |
| 3068 | "if (arguments.length !== "+(argCount - 2)+") {\n" + |
| 3069 | "throwBindingError('function "+humanName+" called with ' + arguments.length + ' arguments, expected "+(argCount - 2)+" args!');\n" + |
| 3070 | "}\n"; |
| 3071 | |
| 3072 | if (needsDestructorStack) { |
| 3073 | invokerFnBody += |
| 3074 | "var destructors = [];\n"; |
| 3075 | } |
| 3076 | |
| 3077 | var dtorStack = needsDestructorStack ? "destructors" : "null"; |
| 3078 | var args1 = ["throwBindingError", "invoker", "fn", "runDestructors", "retType", "classParam"]; |
| 3079 | var args2 = [throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]]; |
| 3080 |
no test coverage detected