Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: compiled/bindings.ipp

Issue 29398655: Issue 5062 - [emscripten] Allow generation of custom bindings code (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Created March 30, 2017, 7:59 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #pragma once 18 #pragma once
19 19
20 #include <cstddef> 20 #include <cstddef>
21 #include <cstdint> 21 #include <cstdint>
22 #include <cstdio> 22 #include <cstdio>
23 #include <cstdlib> 23 #include <cstdlib>
24 #include <exception> 24 #include <exception>
25 #include <functional>
25 #include <map> 26 #include <map>
26 #include <string> 27 #include <string>
27 #include <type_traits> 28 #include <type_traits>
28 #include <utility> 29 #include <utility>
29 #include <vector> 30 #include <vector>
30 31
31 #include <emscripten.h> 32 #include <emscripten.h>
32 33
33 #include "String.h" 34 #include "String.h"
34 #include "intrusive_ptr.h" 35 #include "intrusive_ptr.h"
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 size_t offset; 302 size_t offset;
302 std::vector<std::pair<int, std::string>> mapping; 303 std::vector<std::pair<int, std::string>> mapping;
303 }; 304 };
304 305
305 struct ClassInfo 306 struct ClassInfo
306 { 307 {
307 ClassInfo* baseClass; 308 ClassInfo* baseClass;
308 std::string name; 309 std::string name;
309 std::vector<PropertyInfo> properties; 310 std::vector<PropertyInfo> properties;
310 std::vector<MethodInfo> methods; 311 std::vector<MethodInfo> methods;
311 std::vector<FunctionInfo> initializers;
312 DifferentiatorInfo subclass_differentiator; 312 DifferentiatorInfo subclass_differentiator;
313 ptrdiff_t ref_counted_offset; 313 ptrdiff_t ref_counted_offset;
314 }; 314 };
315 315
316 typedef std::function<void()> CustomGenerator;
317
316 std::map<TYPEID, ClassInfo> classes; 318 std::map<TYPEID, ClassInfo> classes;
319 std::vector<CustomGenerator> customGenerators;
317 320
318 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, 321 void register_class(const char* name, TYPEID classID, TYPEID baseClassID,
319 ptrdiff_t ref_counted_offset) 322 ptrdiff_t ref_counted_offset)
320 { 323 {
321 auto it = classes.find(classID); 324 auto it = classes.find(classID);
322 if (it != classes.end()) 325 if (it != classes.end())
323 throw std::runtime_error(std::string("Duplicate definition for class ") + name); 326 throw std::runtime_error(std::string("Duplicate definition for class ") + name);
324 327
325 ClassInfo* baseClass = nullptr; 328 ClassInfo* baseClass = nullptr;
326 if (baseClassID != TypeInfo<NoBaseClass>()) 329 if (baseClassID != TypeInfo<NoBaseClass>())
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 auto it = classes.find(classID); 364 auto it = classes.find(classID);
362 if (it == classes.end()) 365 if (it == classes.end())
363 throw std::runtime_error(std::string("Method defined on unknown class: ") + name); 366 throw std::runtime_error(std::string("Method defined on unknown class: ") + name);
364 367
365 MethodInfo methodInfo; 368 MethodInfo methodInfo;
366 methodInfo.name = name; 369 methodInfo.name = name;
367 methodInfo.call = call; 370 methodInfo.call = call;
368 it->second.methods.push_back(methodInfo); 371 it->second.methods.push_back(methodInfo);
369 } 372 }
370 373
371 void register_initializer(TYPEID classID, const FunctionInfo& call)
372 {
373 auto it = classes.find(classID);
374 if (it == classes.end())
375 throw std::runtime_error("Initializer defined on unknown class");
376
377 it->second.initializers.push_back(call);
378 }
379
380 void register_differentiator(TYPEID classID, size_t offset, 374 void register_differentiator(TYPEID classID, size_t offset,
381 std::vector<std::pair<int, std::string>>& mapping) 375 std::vector<std::pair<int, std::string>>& mapping)
382 { 376 {
383 auto it = classes.find(classID); 377 auto it = classes.find(classID);
384 if (it == classes.end()) 378 if (it == classes.end())
385 throw std::runtime_error("Subclass differentiator defined on unknown class "); 379 throw std::runtime_error("Subclass differentiator defined on unknown class ");
386 380
387 if (it->second.subclass_differentiator.offset != SIZE_MAX) 381 if (it->second.subclass_differentiator.offset != SIZE_MAX)
388 throw std::runtime_error("More than one subclass differentiator defined fo r class " + it->second.name); 382 throw std::runtime_error("More than one subclass differentiator defined fo r class " + it->second.name);
389 383
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 } 590 }
597 591
598 for (const auto& item : cls.methods) 592 for (const auto& item : cls.methods)
599 { 593 {
600 std::string obj("exports." + cls.name); 594 std::string obj("exports." + cls.name);
601 if (item.call.instance_function) 595 if (item.call.instance_function)
602 obj += ".prototype"; 596 obj += ".prototype";
603 printf("%s.%s = %s;\n", obj.c_str(), item.name.c_str(), 597 printf("%s.%s = %s;\n", obj.c_str(), item.name.c_str(),
604 wrapCall(item.call).c_str()); 598 wrapCall(item.call).c_str());
605 } 599 }
606
607 for (const auto& item : cls.initializers)
608 printf("%s()\n", item.name);
609 } 600 }
610 601
611 void printBindings() 602 void printBindings()
612 { 603 {
613 printHelpers(); 604 printHelpers();
614 605
615 for (const auto& item : classes) 606 for (const auto& item : classes)
616 printClass(item.second); 607 printClass(item.second);
608
609 for (const auto& item : customGenerators)
610 item();
617 } 611 }
618 } 612 }
619 613
620 #if defined(PRINT_BINDINGS) 614 #if defined(PRINT_BINDINGS)
621 // Bindings generation step: collect bindings information and print 615 // Bindings generation step: collect bindings information and print
622 // corresponding JS code. 616 // corresponding JS code.
623 #define EMSCRIPTEN_BINDINGS \ 617 #define EMSCRIPTEN_BINDINGS \
624 struct BindingsInitializer {\ 618 struct BindingsInitializer {\
625 BindingsInitializer();\ 619 BindingsInitializer();\
626 BindingsInitializer(bool dummy)\ 620 };\
sergei 2017/03/30 11:09:17 I would make it a simple function `void Initialize
Wladimir Palant 2017/03/30 12:58:58 Done.
627 {\ 621 int main(void)\
sergei 2017/03/30 11:09:17 In C++ there is no need for specifying of void in
sergei 2017/03/30 11:09:17 Do you mind to consider in future moving of such C
Wladimir Palant 2017/03/30 12:58:58 Done.
Wladimir Palant 2017/03/30 12:58:58 Not sure what you mean. This code is inside bindin
sergei 2017/04/04 14:49:30 I mean it would be better to have this code in ano
Wladimir Palant 2017/04/04 15:41:48 But we are not compiling an executable, it's not s
sergei 2017/04/11 16:29:20 I didn't mean to append a cpp with main to SOURCE_
Wladimir Palant 2017/04/11 18:22:44 Let's do this in a follow-up, I'll file an issue.
628 try\ 622 {\
629 {\ 623 try\
630 BindingsInitializer();\ 624 {\
631 bindings_internal::printBindings();\ 625 struct BindingsInitializer instance;\
sergei 2017/03/30 11:09:17 Why did you need to add struct here?
Wladimir Palant 2017/03/30 12:58:57 This is a InitializeBindings() call now - this was
632 }\ 626 bindings_internal::printBindings();\
633 catch (const std::exception& e)\ 627 }\
634 {\ 628 catch (const std::exception& e)\
635 EM_ASM_ARGS(\ 629 {\
636 console.error("Error occurred generating JavaScript bindings: " +\ 630 EM_ASM_ARGS(\
637 Module.AsciiToString($0)), e.what()\ 631 console.error("Error occurred generating JavaScript bindings: " +\
638 );\ 632 Module.AsciiToString($0)), e.what()\
639 abort();\ 633 );\
640 }\ 634 abort();\
641 }\ 635 }\
642 } BindingsInitializer_instance(true);\ 636 return 0;\
637 }\
643 BindingsInitializer::BindingsInitializer() 638 BindingsInitializer::BindingsInitializer()
644 #else 639 #else
645 // Actual compilation step: ignore bindings information but define some 640 // Actual compilation step: ignore bindings information but define some
646 // exported helper functions necessary for the bindings. 641 // exported helper functions necessary for the bindings.
647 #define EMSCRIPTEN_BINDINGS \ 642 #define EMSCRIPTEN_BINDINGS \
648 extern "C"\ 643 extern "C"\
649 {\ 644 {\
650 void EMSCRIPTEN_KEEPALIVE InitString(DependentString* str,\ 645 void EMSCRIPTEN_KEEPALIVE InitString(DependentString* str,\
651 String::value_type* data, String::size_type len)\ 646 String::value_type* data, String::size_type len)\
652 {\ 647 {\
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 } 729 }
735 730
736 template<typename ReturnType, typename... Args> 731 template<typename ReturnType, typename... Args>
737 const class_& class_function(const char* name, ReturnType (*method)(Args...)) const 732 const class_& class_function(const char* name, ReturnType (*method)(Args...)) const
738 { 733 {
739 bindings_internal::register_method( 734 bindings_internal::register_method(
740 bindings_internal::TypeInfo<ClassType>(), name, method); 735 bindings_internal::TypeInfo<ClassType>(), name, method);
741 return *this; 736 return *this;
742 } 737 }
743 738
744 const class_& class_initializer(void (*function)()) const
745 {
746 bindings_internal::register_initializer(
747 bindings_internal::TypeInfo<ClassType>(), function);
748 return *this;
749 }
750
751 template<typename ReturnType, 739 template<typename ReturnType,
752 typename std::enable_if<std::is_convertible<ReturnType, int32_t>::value>:: type* = nullptr> 740 typename std::enable_if<std::is_convertible<ReturnType, int32_t>::value>:: type* = nullptr>
753 const class_& subclass_differentiator(ReturnType ClassType::* member, 741 const class_& subclass_differentiator(ReturnType ClassType::* member,
754 std::initializer_list<std::pair<ReturnType, const char*>> list) const 742 std::initializer_list<std::pair<ReturnType, const char*>> list) const
755 { 743 {
756 ClassType* instance = nullptr; 744 ClassType* instance = nullptr;
757 size_t offset = (char*)&(instance->*member) - (char*)instance; 745 size_t offset = (char*)&(instance->*member) - (char*)instance;
758 746
759 std::vector<std::pair<int, std::string>> mapping; 747 std::vector<std::pair<int, std::string>> mapping;
760 for (const auto& item : list) 748 for (const auto& item : list)
761 mapping.emplace_back(item.first, item.second); 749 mapping.emplace_back(item.first, item.second);
762 750
763 bindings_internal::register_differentiator( 751 bindings_internal::register_differentiator(
764 bindings_internal::TypeInfo<ClassType>(), offset, mapping); 752 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
765 return *this; 753 return *this;
766 } 754 }
767 }; 755 };
756
757 void custom_generator(bindings_internal::CustomGenerator generator)
758 {
759 bindings_internal::customGenerators.push_back(generator);
760 }
OLDNEW

Powered by Google App Engine
This is Rietveld