| OLD | NEW | 
|---|
| 1 #pragma once | 1 #pragma once | 
| 2 | 2 | 
| 3 #include <cstdint> | 3 #include <cstdint> | 
| 4 #include <cstdio> | 4 #include <cstdio> | 
| 5 #include <cstdlib> | 5 #include <cstdlib> | 
| 6 #include <exception> | 6 #include <exception> | 
| 7 #include <map> | 7 #include <map> | 
| 8 #include <string> | 8 #include <string> | 
| 9 #include <type_traits> | 9 #include <type_traits> | 
| 10 #include <utility> | 10 #include <utility> | 
| 11 #include <vector> | 11 #include <vector> | 
| 12 | 12 | 
| 13 #include <emscripten.h> | 13 #include <emscripten.h> | 
| 14 | 14 | 
| 15 #include "String.h" | 15 #include "String.h" | 
| 16 #include "intrusive_ptr.h" | 16 #include "intrusive_ptr.h" | 
| 17 | 17 | 
| 18 namespace bindings_internal | 18 namespace bindings_internal | 
| 19 { | 19 { | 
| 20   typedef void* TYPEID; | 20   typedef void* TYPEID; | 
| 21 | 21 | 
| 22   enum class TypeCategory | 22   enum class TypeCategory | 
| 23   { | 23   { | 
| 24     UNKNOWN, | 24     UNKNOWN, | 
| 25     VOID, | 25     VOID, | 
| 26     INT, | 26     INT, | 
|  | 27     FLOAT, | 
| 27     DEPENDENT_STRING, | 28     DEPENDENT_STRING, | 
| 28     OWNED_STRING, | 29     OWNED_STRING, | 
| 29     STRING_REF, | 30     STRING_REF, | 
| 30     CLASS_PTR | 31     CLASS_PTR | 
| 31   }; | 32   }; | 
| 32 | 33 | 
| 33   template<typename T> | 34   template<typename T> | 
| 34   struct TypeInfo | 35   struct TypeInfo | 
| 35   { | 36   { | 
| 36     /* | 37     /* | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 48     } | 49     } | 
| 49 | 50 | 
| 50     constexpr operator TypeCategory() const | 51     constexpr operator TypeCategory() const | 
| 51     { | 52     { | 
| 52       if (std::is_void<T>()) | 53       if (std::is_void<T>()) | 
| 53         return TypeCategory::VOID; | 54         return TypeCategory::VOID; | 
| 54 | 55 | 
| 55       if (std::is_integral<T>() || std::is_enum<T>()) | 56       if (std::is_integral<T>() || std::is_enum<T>()) | 
| 56         return TypeCategory::INT; | 57         return TypeCategory::INT; | 
| 57 | 58 | 
|  | 59       if (std::is_floating_point<T>()) | 
|  | 60         return TypeCategory::FLOAT; | 
|  | 61 | 
| 58       if (std::is_same<DependentString, T>() || std::is_same<const DependentStri
     ng, T>()) | 62       if (std::is_same<DependentString, T>() || std::is_same<const DependentStri
     ng, T>()) | 
| 59         return TypeCategory::DEPENDENT_STRING; | 63         return TypeCategory::DEPENDENT_STRING; | 
| 60 | 64 | 
| 61       if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>()
     ) | 65       if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>()
     ) | 
| 62         return TypeCategory::OWNED_STRING; | 66         return TypeCategory::OWNED_STRING; | 
| 63 | 67 | 
| 64       if (std::is_same<String&, T>() || std::is_same<const String&, T>() || | 68       if (std::is_same<String&, T>() || std::is_same<const String&, T>() || | 
| 65         std::is_same<DependentString&, T>()) | 69         std::is_same<DependentString&, T>()) | 
| 66       { | 70       { | 
| 67         return TypeCategory::STRING_REF; | 71         return TypeCategory::STRING_REF; | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 107           instance_function(instance_function) | 111           instance_function(instance_function) | 
| 108     { | 112     { | 
| 109       name[0] = '\0'; | 113       name[0] = '\0'; | 
| 110 | 114 | 
| 111       // The function parameter is a pointer to the function pointer. | 115       // The function parameter is a pointer to the function pointer. | 
| 112       // Emscripten's "function pointers" are actually integers indicating the | 116       // Emscripten's "function pointers" are actually integers indicating the | 
| 113       // position in the call table. 0 represents nullptr. | 117       // position in the call table. 0 represents nullptr. | 
| 114       if (!*reinterpret_cast<int*>(function)) | 118       if (!*reinterpret_cast<int*>(function)) | 
| 115         return; | 119         return; | 
| 116 | 120 | 
|  | 121       char signature[256]; | 
|  | 122       int pos = 0; | 
|  | 123       if (returnType == TypeCategory::DEPENDENT_STRING || | 
|  | 124           returnType == TypeCategory::OWNED_STRING) | 
|  | 125       { | 
|  | 126         // Objects aren't really returned but passed as parameter. Note that | 
|  | 127         // this pointer might come before it but we don't care because both | 
|  | 128         // are integers (pointers) as far as Emscripten is concerned. | 
|  | 129         signature[pos++] = 'v'; | 
|  | 130         signature[pos++] = 'i'; | 
|  | 131       } | 
|  | 132       else if (returnType == TypeCategory::VOID) | 
|  | 133         signature[pos++] = 'v'; | 
|  | 134       else if (returnType == TypeCategory::FLOAT) | 
|  | 135         signature[pos++] = 'd'; | 
|  | 136       else if (returnType == TypeCategory::INT || | 
|  | 137           returnType == TypeCategory::STRING_REF || | 
|  | 138           returnType == TypeCategory::CLASS_PTR) | 
|  | 139       { | 
|  | 140         signature[pos++] = 'i'; | 
|  | 141       } | 
|  | 142       else | 
|  | 143         throw std::runtime_error("Unexpected function return type"); | 
|  | 144 | 
|  | 145       if (instance_function) | 
|  | 146       { | 
|  | 147         // this pointer is an implicit parameter | 
|  | 148         signature[pos++] = 'i'; | 
|  | 149       } | 
|  | 150 | 
| 117       for (const auto& item : argTypes) | 151       for (const auto& item : argTypes) | 
| 118       { | 152       { | 
| 119         if (item != TypeCategory::INT && item != TypeCategory::STRING_REF && | 153         if (item == TypeCategory::INT || item == TypeCategory::STRING_REF || | 
| 120             item != TypeCategory::CLASS_PTR) | 154             item == TypeCategory::CLASS_PTR) | 
| 121         { | 155         { | 
|  | 156           signature[pos++] = 'i'; | 
|  | 157         } | 
|  | 158         else if (item == TypeCategory::FLOAT) | 
|  | 159           signature[pos++] = 'd'; | 
|  | 160         else | 
| 122           throw std::runtime_error("Unexpected function argument type"); | 161           throw std::runtime_error("Unexpected function argument type"); | 
| 123         } |  | 
| 124         args.push_back(item); | 162         args.push_back(item); | 
| 125       } | 163       } | 
| 126 | 164 | 
| 127       if (returnType != TypeCategory::VOID && returnType != TypeCategory::INT && | 165       signature[pos] = 0; | 
| 128           returnType != TypeCategory::DEPENDENT_STRING && |  | 
| 129           returnType != TypeCategory::OWNED_STRING && |  | 
| 130           returnType != TypeCategory::STRING_REF && |  | 
| 131           returnType != TypeCategory::CLASS_PTR) |  | 
| 132       { |  | 
| 133         throw std::runtime_error("Unexpected function return type"); |  | 
| 134       } |  | 
| 135 | 166 | 
| 136       effectiveArgs = args.size(); | 167       get_function_name(function, signature); | 
| 137       effectiveReturnType = returnType; |  | 
| 138       if (instance_function) |  | 
| 139         effectiveArgs++; |  | 
| 140 |  | 
| 141       if (returnType == TypeCategory::DEPENDENT_STRING || |  | 
| 142           returnType == TypeCategory::OWNED_STRING) |  | 
| 143       { |  | 
| 144         effectiveArgs++; |  | 
| 145         effectiveReturnType = TypeCategory::VOID; |  | 
| 146       } |  | 
| 147 |  | 
| 148       get_function_name(function, effectiveArgs, |  | 
| 149           effectiveReturnType == TypeCategory::VOID); |  | 
| 150     } | 168     } | 
| 151 | 169 | 
| 152     template<typename ReturnType, typename... Args> | 170     template<typename ReturnType, typename... Args> | 
| 153     FunctionInfo(ReturnType (*function)(Args...)) | 171     FunctionInfo(ReturnType (*function)(Args...)) | 
| 154         : FunctionInfo(TypeInfo<ReturnType>(), | 172         : FunctionInfo(TypeInfo<ReturnType>(), | 
| 155           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, | 173           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, | 
| 156           &function) | 174           &function) | 
| 157     { | 175     { | 
| 158     } | 176     } | 
| 159 | 177 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 171           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, | 189           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, | 
| 172           &function) | 190           &function) | 
| 173     { | 191     { | 
| 174     } | 192     } | 
| 175 | 193 | 
| 176     bool empty() const | 194     bool empty() const | 
| 177     { | 195     { | 
| 178       return name[0] == '\0'; | 196       return name[0] == '\0'; | 
| 179     } | 197     } | 
| 180 | 198 | 
| 181     void get_function_name(void* ptr, int numArgs, bool voidResult) | 199     void get_function_name(void* ptr, char* signature) | 
| 182     { | 200     { | 
| 183       // This is a hack, C++ won't let us get the mangled function name. | 201       // This is a hack, C++ won't let us get the mangled function name. | 
| 184       // JavaScript is more dynamic so we pass the pointer to our function | 202       // JavaScript is more dynamic so we pass the pointer to our function | 
| 185       // there. With that and the function signature we can call the function - | 203       // there. With that and the function signature we can call the function - | 
| 186       // with a full stack so that we will cause it to abort. Sometimes the | 204       // with a full stack so that we will cause it to abort. Sometimes the | 
| 187       // function we are calling will also be missing from the build. The result | 205       // function we are calling will also be missing from the build. The result | 
| 188       // is the same: abort() is called which in turn calls stackTrace(). By | 206       // is the same: abort() is called which in turn calls stackTrace(). By | 
| 189       // replacing stackTrace() we get access to the call stack and search it | 207       // replacing stackTrace() we get access to the call stack and search it | 
| 190       // for the name of our function. | 208       // for the name of our function. | 
| 191 | 209 | 
| 192       EM_ASM_ARGS({ | 210       EM_ASM_ARGS({ | 
| 193         var signature = $3 ? "v" : "i"; | 211         var signature = AsciiToString($2); | 
| 194         var args = []; | 212         var args = []; | 
| 195         for (var i = 0; i < $2; i++) | 213         for (var i = 1; i < signature.length; i++) | 
| 196         { |  | 
| 197           signature += "i"; |  | 
| 198           args.push(0); | 214           args.push(0); | 
| 199         } |  | 
| 200 | 215 | 
| 201         var oldPrint = Module.print; | 216         var oldPrint = Module.print; | 
| 202         var oldPrintErr = Module.printErr; | 217         var oldPrintErr = Module.printErr; | 
| 203         var oldStackTrace = stackTrace; | 218         var oldStackTrace = stackTrace; | 
| 204         var sp = Runtime.stackSave(); | 219         var sp = Runtime.stackSave(); | 
| 205         Module.print = function(){}; | 220         Module.print = function(){}; | 
| 206         Module.printErr = function(){}; | 221         Module.printErr = function(){}; | 
| 207         stackTrace = function() | 222         stackTrace = function() | 
| 208         { | 223         { | 
| 209           var stack = []; | 224           var stack = []; | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 234         { | 249         { | 
| 235           Module.stringToAscii(e, $0); | 250           Module.stringToAscii(e, $0); | 
| 236         } | 251         } | 
| 237         finally | 252         finally | 
| 238         { | 253         { | 
| 239           Runtime.stackRestore(sp); | 254           Runtime.stackRestore(sp); | 
| 240           Module.print = oldPrint; | 255           Module.print = oldPrint; | 
| 241           Module.printErr = oldPrintErr; | 256           Module.printErr = oldPrintErr; | 
| 242           stackTrace = oldStackTrace; | 257           stackTrace = oldStackTrace; | 
| 243         } | 258         } | 
| 244       }, name, ptr, numArgs, voidResult); | 259       }, name, ptr, signature); | 
| 245     } | 260     } | 
| 246   }; | 261   }; | 
| 247 | 262 | 
| 248   class NoBaseClass | 263   class NoBaseClass | 
| 249   { | 264   { | 
| 250   }; | 265   }; | 
| 251 | 266 | 
| 252   struct PropertyInfo | 267   struct PropertyInfo | 
| 253   { | 268   { | 
| 254     std::string name; | 269     std::string name; | 
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 374     for (int i = 0; i < params.size(); i++) | 389     for (int i = 0; i < params.size(); i++) | 
| 375     { | 390     { | 
| 376       if (i > 0) | 391       if (i > 0) | 
| 377         call_str += ", "; | 392         call_str += ", "; | 
| 378       call_str += params[i]; | 393       call_str += params[i]; | 
| 379     } | 394     } | 
| 380     call_str += ")"; | 395     call_str += ")"; | 
| 381 | 396 | 
| 382     if (call.returnType == TypeCategory::VOID) | 397     if (call.returnType == TypeCategory::VOID) | 
| 383       return "  " + call_str + ";\n"; | 398       return "  " + call_str + ";\n"; | 
| 384     else if (call.returnType == TypeCategory::INT) | 399     else if (call.returnType == TypeCategory::INT || | 
|  | 400           call.returnType == TypeCategory::FLOAT) | 
|  | 401     { | 
| 385       return "  var result = " + call_str + ";\n"; | 402       return "  var result = " + call_str + ";\n"; | 
|  | 403     } | 
| 386     else if (call.returnType == TypeCategory::DEPENDENT_STRING || | 404     else if (call.returnType == TypeCategory::DEPENDENT_STRING || | 
| 387         call.returnType == TypeCategory::OWNED_STRING) | 405         call.returnType == TypeCategory::OWNED_STRING) | 
| 388     { | 406     { | 
| 389       std::string result; | 407       std::string result; | 
| 390       result += "  var string = createString();\n"; | 408       result += "  var string = createString();\n"; | 
| 391       result += "  " + call_str + ";\n"; | 409       result += "  " + call_str + ";\n"; | 
| 392       result += "  var result = readString(string);\n"; | 410       result += "  var result = readString(string);\n"; | 
| 393       if (call.returnType == TypeCategory::OWNED_STRING) | 411       if (call.returnType == TypeCategory::OWNED_STRING) | 
| 394         result += "  Module._DestroyString(string);\n"; | 412         result += "  Module._DestroyString(string);\n"; | 
| 395       return result; | 413       return result; | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 440       sprintf(buffer, "arg%i", i); | 458       sprintf(buffer, "arg%i", i); | 
| 441       if (i > 0) | 459       if (i > 0) | 
| 442         prefix += ", "; | 460         prefix += ", "; | 
| 443       prefix += buffer; | 461       prefix += buffer; | 
| 444 | 462 | 
| 445       if (call.args[i] == TypeCategory::STRING_REF) | 463       if (call.args[i] == TypeCategory::STRING_REF) | 
| 446       { | 464       { | 
| 447         hasStringArgs = true; | 465         hasStringArgs = true; | 
| 448         params.push_back(std::string("createString(") + buffer + ")"); | 466         params.push_back(std::string("createString(") + buffer + ")"); | 
| 449       } | 467       } | 
|  | 468       else if (call.args[i] == TypeCategory::CLASS_PTR) | 
|  | 469         params.push_back(std::string(buffer) + "._pointer"); | 
| 450       else | 470       else | 
| 451         params.push_back(buffer); | 471         params.push_back(buffer); | 
| 452     } | 472     } | 
| 453     prefix += ")\n{\n"; | 473     prefix += ")\n{\n"; | 
| 454 | 474 | 
| 455     std::string suffix = "}"; | 475     std::string suffix = "}"; | 
| 456     if (call.returnType != TypeCategory::VOID) | 476     if (call.returnType != TypeCategory::VOID) | 
| 457       suffix = "  return result;\n" + suffix; | 477       suffix = "  return result;\n" + suffix; | 
| 458 | 478 | 
| 459     if (call.returnType == TypeCategory::DEPENDENT_STRING || | 479     if (call.returnType == TypeCategory::DEPENDENT_STRING || | 
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 718 | 738 | 
| 719     std::vector<std::pair<int, std::string>> mapping; | 739     std::vector<std::pair<int, std::string>> mapping; | 
| 720     for (const auto& item : list) | 740     for (const auto& item : list) | 
| 721       mapping.emplace_back(item.first, item.second); | 741       mapping.emplace_back(item.first, item.second); | 
| 722 | 742 | 
| 723     bindings_internal::register_differentiator( | 743     bindings_internal::register_differentiator( | 
| 724         bindings_internal::TypeInfo<ClassType>(), offset, mapping); | 744         bindings_internal::TypeInfo<ClassType>(), offset, mapping); | 
| 725     return *this; | 745     return *this; | 
| 726   } | 746   } | 
| 727 }; | 747 }; | 
| OLD | NEW | 
|---|