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 |