| LEFT | RIGHT |
| 1 #pragma once | 1 #pragma once |
| 2 | 2 |
| 3 #include <cstddef> |
| 3 #include <cstdint> | 4 #include <cstdint> |
| 4 #include <cstdio> | 5 #include <cstdio> |
| 5 #include <cstdlib> | 6 #include <cstdlib> |
| 6 #include <exception> | 7 #include <exception> |
| 7 #include <map> | 8 #include <map> |
| 8 #include <string> | 9 #include <string> |
| 9 #include <type_traits> | 10 #include <type_traits> |
| 10 #include <utility> | 11 #include <utility> |
| 11 #include <vector> | 12 #include <vector> |
| 12 | 13 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 }; | 271 }; |
| 271 | 272 |
| 272 struct ClassInfo | 273 struct ClassInfo |
| 273 { | 274 { |
| 274 ClassInfo* baseClass; | 275 ClassInfo* baseClass; |
| 275 std::string name; | 276 std::string name; |
| 276 std::vector<PropertyInfo> properties; | 277 std::vector<PropertyInfo> properties; |
| 277 std::vector<MethodInfo> methods; | 278 std::vector<MethodInfo> methods; |
| 278 std::vector<FunctionInfo> initializers; | 279 std::vector<FunctionInfo> initializers; |
| 279 DifferentiatorInfo subclass_differentiator; | 280 DifferentiatorInfo subclass_differentiator; |
| 281 ptrdiff_t ref_counted_offset; |
| 280 }; | 282 }; |
| 281 | 283 |
| 282 std::map<TYPEID, ClassInfo> classes; | 284 std::map<TYPEID, ClassInfo> classes; |
| 283 | 285 |
| 284 void register_class(const char* name, TYPEID classID, TYPEID baseClassID) | 286 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, |
| 287 ptrdiff_t ref_counted_offset) |
| 285 { | 288 { |
| 286 auto it = classes.find(classID); | 289 auto it = classes.find(classID); |
| 287 if (it != classes.end()) | 290 if (it != classes.end()) |
| 288 throw std::runtime_error(std::string("Duplicate definition for class ") +
name); | 291 throw std::runtime_error(std::string("Duplicate definition for class ") +
name); |
| 289 | 292 |
| 290 ClassInfo* baseClass = nullptr; | 293 ClassInfo* baseClass = nullptr; |
| 291 if (baseClassID != TypeInfo<NoBaseClass>()) | 294 if (baseClassID != TypeInfo<NoBaseClass>()) |
| 292 { | 295 { |
| 293 it = classes.find(baseClassID); | 296 it = classes.find(baseClassID); |
| 294 if (it == classes.end()) | 297 if (it == classes.end()) |
| 295 throw std::runtime_error(std::string("Unknown base class defined for cla
ss ") + name); | 298 throw std::runtime_error(std::string("Unknown base class defined for cla
ss ") + name); |
| 296 baseClass = &(it->second); | 299 baseClass = &(it->second); |
| 297 } | 300 } |
| 298 | 301 |
| 299 ClassInfo classInfo; | 302 ClassInfo classInfo; |
| 300 classInfo.baseClass = baseClass; | 303 classInfo.baseClass = baseClass; |
| 301 classInfo.name = name; | 304 classInfo.name = name; |
| 302 classInfo.subclass_differentiator.offset = SIZE_MAX; | 305 classInfo.subclass_differentiator.offset = SIZE_MAX; |
| 306 classInfo.ref_counted_offset = ref_counted_offset; |
| 303 classes[classID] = classInfo; | 307 classes[classID] = classInfo; |
| 304 } | 308 } |
| 305 | 309 |
| 306 void register_property(TYPEID classID, const char* name, | 310 void register_property(TYPEID classID, const char* name, |
| 307 const FunctionInfo& getter, const FunctionInfo& setter, | 311 const FunctionInfo& getter, const FunctionInfo& setter, |
| 308 const char* jsValue = "") | 312 const char* jsValue = "") |
| 309 { | 313 { |
| 310 auto it = classes.find(classID); | 314 auto it = classes.find(classID); |
| 311 if (it == classes.end()) | 315 if (it == classes.end()) |
| 312 throw std::runtime_error(std::string("Property defined on unknown class: "
) + name); | 316 throw std::runtime_error(std::string("Property defined on unknown class: "
) + name); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 return result; | 509 return result; |
| 506 } | 510 } |
| 507 | 511 |
| 508 function readString(str) | 512 function readString(str) |
| 509 { | 513 { |
| 510 var length = Module._GetStringLength(str); | 514 var length = Module._GetStringLength(str); |
| 511 var pointer = Module._GetStringData(str) >> 1; | 515 var pointer = Module._GetStringData(str) >> 1; |
| 512 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len
gth)); | 516 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len
gth)); |
| 513 } | 517 } |
| 514 | 518 |
| 515 function createClass(superclass) | 519 function createClass(superclass, ref_counted_offset) |
| 516 { | 520 { |
| 517 var result = function(pointer) | 521 var result = function(pointer) |
| 518 { | 522 { |
| 519 this._pointer = pointer; | 523 this._pointer = pointer; |
| 520 }; | 524 }; |
| 521 if (superclass) | 525 if (superclass) |
| 522 result.prototype = Object.create(superclass.prototype); | 526 result.prototype = Object.create(superclass.prototype); |
| 523 result.prototype.delete = function() | 527 result.prototype.delete = function() |
| 524 { | 528 { |
| 525 // This is dangerous because this._pointer is a pointer to SomeClass, | 529 Module._ReleaseRef(this._pointer + ref_counted_offset); |
| 526 // yet ReleaseRef expects ref_counted*. Even with SomeClass inheriting | |
| 527 // from ref_counted, the numerical pointer values aren't necessarily | |
| 528 // identical in C++. | |
| 529 Module._ReleaseRef(this._pointer); | |
| 530 }; | 530 }; |
| 531 return result; | 531 return result; |
| 532 })"); | 532 })"); |
| 533 } | 533 } |
| 534 | 534 |
| 535 void printClass(const ClassInfo& cls) | 535 void printClass(const ClassInfo& cls) |
| 536 { | 536 { |
| 537 DifferentiatorInfo differentiator = cls.subclass_differentiator; | 537 DifferentiatorInfo differentiator = cls.subclass_differentiator; |
| 538 if (differentiator.offset != SIZE_MAX) | 538 if (differentiator.offset != SIZE_MAX) |
| 539 { | 539 { |
| 540 printf("var %s_mapping = \n", cls.name.c_str()); | 540 printf("var %s_mapping = \n", cls.name.c_str()); |
| 541 puts("{"); | 541 puts("{"); |
| 542 for (const auto& item : differentiator.mapping) | 542 for (const auto& item : differentiator.mapping) |
| 543 printf(" %i: '%s',\n", item.first, item.second.c_str()); | 543 printf(" %i: '%s',\n", item.first, item.second.c_str()); |
| 544 puts("};"); | 544 puts("};"); |
| 545 } | 545 } |
| 546 | 546 |
| 547 printf("exports.%s = createClass(%s);\n", cls.name.c_str(), | 547 printf("exports.%s = createClass(%s, %i);\n", cls.name.c_str(), |
| 548 (cls.baseClass ? ("exports." + cls.baseClass->name).c_str() : "")); | 548 (cls.baseClass ? ("exports." + cls.baseClass->name).c_str() : "null"), |
| 549 cls.ref_counted_offset); |
| 549 | 550 |
| 550 for (const auto& item : cls.properties) | 551 for (const auto& item : cls.properties) |
| 551 { | 552 { |
| 552 printf("Object.defineProperty(exports.%s.prototype, '%s', {%s});\n", | 553 printf("Object.defineProperty(exports.%s.prototype, '%s', {%s});\n", |
| 553 cls.name.c_str(), item.name.c_str(), | 554 cls.name.c_str(), item.name.c_str(), |
| 554 generatePropertyDescriptor(item).c_str()); | 555 generatePropertyDescriptor(item).c_str()); |
| 555 } | 556 } |
| 556 | 557 |
| 557 for (const auto& item : cls.methods) | 558 for (const auto& item : cls.methods) |
| 558 { | 559 { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 String::size_type EMSCRIPTEN_KEEPALIVE GetStringLength(\ | 623 String::size_type EMSCRIPTEN_KEEPALIVE GetStringLength(\ |
| 623 const String& str)\ | 624 const String& str)\ |
| 624 {\ | 625 {\ |
| 625 return str.length();\ | 626 return str.length();\ |
| 626 }\ | 627 }\ |
| 627 const String::value_type* EMSCRIPTEN_KEEPALIVE GetStringData(\ | 628 const String::value_type* EMSCRIPTEN_KEEPALIVE GetStringData(\ |
| 628 const String& str)\ | 629 const String& str)\ |
| 629 {\ | 630 {\ |
| 630 return str.data();\ | 631 return str.data();\ |
| 631 }\ | 632 }\ |
| 632 void EMSCRIPTEN_KEEPALIVE AddRef(ref_counted* ptr)\ | |
| 633 {\ | |
| 634 ptr->AddRef();\ | |
| 635 }\ | |
| 636 void EMSCRIPTEN_KEEPALIVE ReleaseRef(ref_counted* ptr)\ | 633 void EMSCRIPTEN_KEEPALIVE ReleaseRef(ref_counted* ptr)\ |
| 637 {\ | 634 {\ |
| 638 ptr->ReleaseRef();\ | 635 ptr->ReleaseRef();\ |
| 639 }\ | 636 }\ |
| 640 }\ | 637 }\ |
| 641 void BindingsInitializer_dummy() | 638 void BindingsInitializer_dummy() |
| 642 #endif | 639 #endif |
| 643 | 640 |
| 644 template<typename ClassType, | 641 template<typename ClassType, |
| 645 typename BaseClass = bindings_internal::NoBaseClass, | 642 typename BaseClass = bindings_internal::NoBaseClass, |
| 646 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ
e* = nullptr> | 643 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ
e* = nullptr> |
| 647 class class_ | 644 class class_ |
| 648 { | 645 { |
| 649 public: | 646 public: |
| 650 class_(const char* name) | 647 class_(const char* name) |
| 651 { | 648 { |
| 649 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000); |
| 650 ptrdiff_t ref_counted_offset = |
| 651 reinterpret_cast<char*>(static_cast<ref_counted*>(ptr)) - |
| 652 reinterpret_cast<char*>(ptr); |
| 652 bindings_internal::register_class(name, | 653 bindings_internal::register_class(name, |
| 653 bindings_internal::TypeInfo<ClassType>(), | 654 bindings_internal::TypeInfo<ClassType>(), |
| 654 bindings_internal::TypeInfo<BaseClass>()); | 655 bindings_internal::TypeInfo<BaseClass>(), |
| 656 ref_counted_offset |
| 657 ); |
| 655 } | 658 } |
| 656 | 659 |
| 657 template<typename FieldType> | 660 template<typename FieldType> |
| 658 const class_& property(const char* name, | 661 const class_& property(const char* name, |
| 659 FieldType (ClassType::*getter)() const, | 662 FieldType (ClassType::*getter)() const, |
| 660 void (ClassType::*setter)(FieldType) = nullptr) const | 663 void (ClassType::*setter)(FieldType) = nullptr) const |
| 661 { | 664 { |
| 662 bindings_internal::register_property( | 665 bindings_internal::register_property( |
| 663 bindings_internal::TypeInfo<ClassType>(), name, getter, setter); | 666 bindings_internal::TypeInfo<ClassType>(), name, getter, setter); |
| 664 return *this; | 667 return *this; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 | 718 |
| 716 std::vector<std::pair<int, std::string>> mapping; | 719 std::vector<std::pair<int, std::string>> mapping; |
| 717 for (const auto& item : list) | 720 for (const auto& item : list) |
| 718 mapping.emplace_back(item.first, item.second); | 721 mapping.emplace_back(item.first, item.second); |
| 719 | 722 |
| 720 bindings_internal::register_differentiator( | 723 bindings_internal::register_differentiator( |
| 721 bindings_internal::TypeInfo<ClassType>(), offset, mapping); | 724 bindings_internal::TypeInfo<ClassType>(), offset, mapping); |
| 722 return *this; | 725 return *this; |
| 723 } | 726 } |
| 724 }; | 727 }; |
| LEFT | RIGHT |