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

Side by Side Diff: compiled/bindings/generator.h

Issue 29410617: Issue 5131 - [emscripten] Clean separation of bindings code and runtime code (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Created April 12, 2017, 2:07 p.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>
23 #include <cstdlib> 22 #include <cstdlib>
24 #include <exception>
25 #include <functional> 23 #include <functional>
26 #include <map>
27 #include <string> 24 #include <string>
28 #include <type_traits> 25 #include <type_traits>
29 #include <utility> 26 #include <utility>
30 #include <vector> 27 #include <vector>
31 28
32 #include <emscripten.h> 29 #include <emscripten.h>
33 30
34 #include "String.h" 31 #include "../String.h"
35 #include "intrusive_ptr.h" 32 #include "../intrusive_ptr.h"
36 33
37 namespace bindings_internal 34 namespace bindings_internal
38 { 35 {
39 typedef void* TYPEID; 36 typedef void* TYPEID;
40 37
41 enum class TypeCategory 38 enum class TypeCategory
42 { 39 {
43 UNKNOWN, 40 UNKNOWN,
44 VOID, 41 VOID,
45 INT, 42 INT,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 struct FunctionInfo 112 struct FunctionInfo
116 { 113 {
117 TypeCategory returnType; 114 TypeCategory returnType;
118 TYPEID pointerType; 115 TYPEID pointerType;
119 std::vector<TypeCategory> args; 116 std::vector<TypeCategory> args;
120 bool instance_function; 117 bool instance_function;
121 int effectiveArgs; 118 int effectiveArgs;
122 TypeCategory effectiveReturnType; 119 TypeCategory effectiveReturnType;
123 char name[1024]; 120 char name[1024];
124 121
125 FunctionInfo() 122 FunctionInfo();
126 {
127 name[0] = '\0';
128 }
129 123
130 FunctionInfo(TypeCategory returnType, TYPEID pointerType, 124 FunctionInfo(TypeCategory returnType, TYPEID pointerType,
131 std::initializer_list<TypeCategory> argTypes, bool instance_function, 125 std::initializer_list<TypeCategory> argTypes, bool instance_function,
132 void* function) 126 void* function);
133 : returnType(returnType), pointerType(pointerType),
134 instance_function(instance_function)
135 {
136 name[0] = '\0';
137
138 // The function parameter is a pointer to the function pointer.
139 // Emscripten's "function pointers" are actually integers indicating the
140 // position in the call table. 0 represents nullptr.
141 if (!*reinterpret_cast<int*>(function))
142 return;
143
144 std::string signature;
145 if (returnType == TypeCategory::DEPENDENT_STRING ||
146 returnType == TypeCategory::OWNED_STRING)
147 {
148 // Objects aren't really returned but passed as parameter. Note that
149 // this pointer might come before it but we don't care because both
150 // are integers (pointers) as far as Emscripten is concerned.
151 signature += "vi";
152 }
153 else if (returnType == TypeCategory::VOID)
154 signature += 'v';
155 else if (returnType == TypeCategory::FLOAT)
156 signature += 'd';
157 else if (returnType == TypeCategory::INT ||
158 returnType == TypeCategory::INT64 ||
159 returnType == TypeCategory::STRING_REF ||
160 returnType == TypeCategory::CLASS_PTR)
161 {
162 signature += 'i';
163 }
164 else
165 throw std::runtime_error("Unexpected function return type");
166
167 if (instance_function)
168 {
169 // this pointer is an implicit parameter
170 signature += 'i';
171 }
172
173 for (const auto& item : argTypes)
174 {
175 if (item == TypeCategory::INT || item == TypeCategory::STRING_REF ||
176 item == TypeCategory::CLASS_PTR)
177 {
178 signature += 'i';
179 }
180 else if (item == TypeCategory::INT64)
181 signature += "ii";
182 else if (item == TypeCategory::FLOAT)
183 signature += 'd';
184 else
185 throw std::runtime_error("Unexpected function argument type");
186 args.push_back(item);
187 }
188
189 get_function_name(function, signature.c_str());
190 }
191 127
192 template<typename ReturnType, typename... Args> 128 template<typename ReturnType, typename... Args>
193 FunctionInfo(ReturnType (*function)(Args...)) 129 FunctionInfo(ReturnType (*function)(Args...))
194 : FunctionInfo(TypeInfo<ReturnType>(), 130 : FunctionInfo(TypeInfo<ReturnType>(),
195 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, 131 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false,
196 &function) 132 &function)
197 { 133 {
198 } 134 }
199 135
200 template<typename ClassType, typename ReturnType, typename... Args> 136 template<typename ClassType, typename ReturnType, typename... Args>
201 FunctionInfo(ReturnType (ClassType::*function)(Args...)) 137 FunctionInfo(ReturnType (ClassType::*function)(Args...))
202 : FunctionInfo(TypeInfo<ReturnType>(), 138 : FunctionInfo(TypeInfo<ReturnType>(),
203 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, 139 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true,
204 &function) 140 &function)
205 { 141 {
206 } 142 }
207 143
208 template<typename ClassType, typename ReturnType, typename... Args> 144 template<typename ClassType, typename ReturnType, typename... Args>
209 FunctionInfo(ReturnType (ClassType::*function)(Args...) const) 145 FunctionInfo(ReturnType (ClassType::*function)(Args...) const)
210 : FunctionInfo(TypeInfo<ReturnType>(), 146 : FunctionInfo(TypeInfo<ReturnType>(),
211 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, 147 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true,
212 &function) 148 &function)
213 { 149 {
214 } 150 }
215 151
216 bool empty() const 152 bool empty() const;
217 {
218 return name[0] == '\0';
219 }
220 153
221 void get_function_name(void* ptr, const char* signature) 154 void get_function_name(void* ptr, const char* signature);
222 {
223 // This is a hack, C++ won't let us get the mangled function name.
224 // JavaScript is more dynamic so we pass the pointer to our function
225 // there. With that and the function signature we can call the function -
226 // with a full stack so that we will cause it to abort. Sometimes the
227 // function we are calling will also be missing from the build. The result
228 // is the same: abort() is called which in turn calls stackTrace(). By
229 // replacing stackTrace() we get access to the call stack and search it
230 // for the name of our function.
231
232 EM_ASM_ARGS({
233 var signature = AsciiToString($2);
234 var args = [];
235 for (var i = 1; i < signature.length; i++)
236 args.push(0);
237
238 var oldPrint = Module.print;
239 var oldPrintErr = Module.printErr;
240 var oldStackTrace = stackTrace;
241 var sp = Runtime.stackSave();
242 Module.print = function(){};
243 Module.printErr = function(){};
244 stackTrace = function()
245 {
246 var stack = [];
247 for (var f = arguments.callee.caller; f; f = f.caller)
248 {
249 if (f.name)
250 {
251 if (f.name.indexOf("dynCall") == 0)
252 break;
253 else
254 stack.push(f.name);
255 }
256 }
257
258 result = stack[stack.length - 1];
259 if (result && result.indexOf("__wrapper") >= 0)
260 result = stack[stack.length - 2];
261 throw result;
262 };
263
264 Runtime.stackRestore(STACK_MAX);
265
266 try
267 {
268 Runtime.dynCall(signature, HEAP32[$1 >> 2], args);
269 }
270 catch(e)
271 {
272 Module.stringToAscii(e, $0);
273 }
274 finally
275 {
276 Runtime.stackRestore(sp);
277 Module.print = oldPrint;
278 Module.printErr = oldPrintErr;
279 stackTrace = oldStackTrace;
280 }
281 }, name, ptr, signature);
282 }
283 }; 155 };
284 156
285 class NoBaseClass 157 class NoBaseClass
286 { 158 {
287 }; 159 };
288 160
289 struct PropertyInfo 161 struct PropertyInfo
290 { 162 {
291 std::string name; 163 std::string name;
292 FunctionInfo getter; 164 FunctionInfo getter;
293 FunctionInfo setter; 165 FunctionInfo setter;
294 std::string jsValue; 166 std::string jsValue;
295 }; 167 };
296 168
297 struct MethodInfo 169 struct MethodInfo
298 { 170 {
299 std::string name; 171 std::string name;
300 FunctionInfo call; 172 FunctionInfo call;
301 }; 173 };
302 174
303 struct DifferentiatorInfo 175 struct DifferentiatorInfo
304 { 176 {
305 size_t offset; 177 size_t offset;
306 std::vector<std::pair<int, std::string>> mapping; 178 std::vector<std::pair<int, std::string>> mapping;
307 }; 179 };
308 180
309 struct ClassInfo 181 struct ClassInfo
310 { 182 {
311 ClassInfo* baseClass; 183 TYPEID id;
184 TYPEID baseClass;
312 std::string name; 185 std::string name;
313 std::vector<PropertyInfo> properties; 186 std::vector<PropertyInfo> properties;
314 std::vector<MethodInfo> methods; 187 std::vector<MethodInfo> methods;
315 DifferentiatorInfo subclass_differentiator; 188 DifferentiatorInfo subclass_differentiator;
316 ptrdiff_t ref_counted_offset; 189 ptrdiff_t ref_counted_offset;
317 }; 190 };
318 191
319 typedef std::function<void()> CustomGenerator; 192 typedef std::function<void()> CustomGenerator;
320 193
321 std::map<TYPEID, ClassInfo> classes;
322 std::vector<CustomGenerator> customGenerators;
323
324 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, 194 void register_class(const char* name, TYPEID classID, TYPEID baseClassID,
325 ptrdiff_t ref_counted_offset) 195 ptrdiff_t ref_counted_offset);
326 {
327 auto it = classes.find(classID);
328 if (it != classes.end())
329 throw std::runtime_error(std::string("Duplicate definition for class ") + name);
330
331 ClassInfo* baseClass = nullptr;
332 if (baseClassID != TypeInfo<NoBaseClass>())
333 {
334 it = classes.find(baseClassID);
335 if (it == classes.end())
336 throw std::runtime_error(std::string("Unknown base class defined for cla ss ") + name);
337 baseClass = &(it->second);
338 }
339
340 ClassInfo classInfo;
341 classInfo.baseClass = baseClass;
342 classInfo.name = name;
343 classInfo.subclass_differentiator.offset = SIZE_MAX;
344 classInfo.ref_counted_offset = ref_counted_offset;
345 classes[classID] = classInfo;
346 }
347 196
348 void register_property(TYPEID classID, const char* name, 197 void register_property(TYPEID classID, const char* name,
349 const FunctionInfo& getter, const FunctionInfo& setter, 198 const FunctionInfo& getter, const FunctionInfo& setter,
350 const char* jsValue = "") 199 const char* jsValue = "");
351 {
352 auto it = classes.find(classID);
353 if (it == classes.end())
354 throw std::runtime_error(std::string("Property defined on unknown class: " ) + name);
355
356 PropertyInfo propertyInfo;
357 propertyInfo.name = name;
358 propertyInfo.getter = getter;
359 propertyInfo.setter = setter;
360 propertyInfo.jsValue = jsValue;
361 it->second.properties.push_back(propertyInfo);
362 }
363 200
364 void register_method(TYPEID classID, const char* name, 201 void register_method(TYPEID classID, const char* name,
365 const FunctionInfo& call) 202 const FunctionInfo& call);
366 {
367 auto it = classes.find(classID);
368 if (it == classes.end())
369 throw std::runtime_error(std::string("Method defined on unknown class: ") + name);
370
371 MethodInfo methodInfo;
372 methodInfo.name = name;
373 methodInfo.call = call;
374 it->second.methods.push_back(methodInfo);
375 }
376 203
377 void register_differentiator(TYPEID classID, size_t offset, 204 void register_differentiator(TYPEID classID, size_t offset,
378 std::vector<std::pair<int, std::string>>& mapping) 205 std::vector<std::pair<int, std::string>>& mapping);
379 {
380 auto it = classes.find(classID);
381 if (it == classes.end())
382 throw std::runtime_error("Subclass differentiator defined on unknown class ");
383
384 if (it->second.subclass_differentiator.offset != SIZE_MAX)
385 throw std::runtime_error("More than one subclass differentiator defined fo r class " + it->second.name);
386
387 DifferentiatorInfo differentiatorInfo;
388 differentiatorInfo.offset = offset;
389 differentiatorInfo.mapping = mapping;
390 it->second.subclass_differentiator = differentiatorInfo;
391 }
392 206
393 const std::string generateCall(const FunctionInfo& call, 207 const std::string generateCall(const FunctionInfo& call,
394 std::vector<std::string>& params) 208 std::vector<std::string>& params);
395 {
396 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
397 call.returnType == TypeCategory::OWNED_STRING)
398 {
399 params.insert(params.begin(), "string");
400 }
401 209
402 std::string call_str(call.name); 210 const std::string wrapCall(const FunctionInfo& call);
403 call_str += "(";
404 for (int i = 0; i < params.size(); i++)
405 {
406 if (i > 0)
407 call_str += ", ";
408 call_str += params[i];
409 }
410 call_str += ")";
411 211
412 if (call.returnType == TypeCategory::VOID) 212 std::string generatePropertyDescriptor(const PropertyInfo& property);
413 return " " + call_str + ";\n";
414 else if (call.returnType == TypeCategory::INT ||
415 call.returnType == TypeCategory::FLOAT)
416 {
417 return " var result = " + call_str + ";\n";
418 }
419 else if (call.returnType == TypeCategory::INT64)
420 {
421 // Emscripten saves the high bits of a 64-bit return value in a special
422 // variable called tempRet0. We cannot use bit operators to combine the
423 // values because JavaScript operates on 32-bit integers.
424 return " var result = (" + call_str + " >>> 0)" +
425 " + (Runtime.getTempRet0() >>> 0) * 0x100000000;\n";
426 }
427 else if (call.returnType == TypeCategory::DEPENDENT_STRING ||
428 call.returnType == TypeCategory::OWNED_STRING)
429 {
430 std::string result;
431 result += " var string = createString();\n";
432 result += " " + call_str + ";\n";
433 result += " var result = readString(string);\n";
434 if (call.returnType == TypeCategory::OWNED_STRING)
435 result += " Module._DestroyString(string);\n";
436 return result;
437 }
438 else if (call.returnType == TypeCategory::STRING_REF)
439 {
440 return " var result = readString(" + call_str + ");\n";
441 }
442 else if (call.returnType == TypeCategory::CLASS_PTR)
443 {
444 std::string result;
445 result += " var result = " + call_str + ";\n";
446 result += " if (result)\n";
447 result += " {\n";
448 213
449 auto it = classes.find(call.pointerType); 214 void printHelpers();
450 if (it == classes.end())
451 throw std::runtime_error("Function " + std::string(call.name) + " return s pointer to unknown class");
452 215
453 const ClassInfo& cls = it->second; 216 void printClass(const ClassInfo& cls);
454 auto offset = cls.subclass_differentiator.offset;
455 if (offset == SIZE_MAX)
456 result += " result = exports." + cls.name + "(result);\n";
457 else
458 result += " result = exports." + cls.name + ".fromPointer(result);\n" ;
459
460 result += " }\n";
461 result += " else\n";
462 result += " result = null;\n";
463 return result;
464 }
465 else
466 throw std::runtime_error("Unexpected return type for " + std::string(call. name));
467 }
468
469 const std::string wrapCall(const FunctionInfo& call)
470 {
471 bool hasStringArgs = false;
472 std::vector<std::string> params;
473 std::string prefix = "function(";
474 for (int i = 0; i < call.args.size(); i++)
475 {
476 std::string argName("arg" + std::to_string(i));
477 if (i > 0)
478 prefix += ", ";
479 prefix += argName;
480
481 if (call.args[i] == TypeCategory::STRING_REF)
482 {
483 hasStringArgs = true;
484 params.push_back(std::string("createString(") + argName + ")");
485 }
486 else if (call.args[i] == TypeCategory::CLASS_PTR)
487 params.push_back(argName + "._pointer");
488 else if (call.args[i] == TypeCategory::INT64)
489 {
490 // 64-bit integers are passed as two integer parameters
491 params.push_back(argName + " >>> 0");
492 params.push_back(argName + " / 0x100000000 >>> 0");
493 }
494 else
495 params.push_back(argName);
496 }
497 prefix += ")\n{\n";
498
499 std::string suffix = "}";
500 if (call.returnType != TypeCategory::VOID)
501 suffix = " return result;\n" + suffix;
502
503 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
504 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
505 {
506 prefix += " var sp = Runtime.stackSave();\n";
507 suffix = " Runtime.stackRestore(sp);\n" + suffix;
508 }
509
510 if (call.instance_function)
511 params.insert(params.begin(), "this._pointer");
512
513 return prefix + generateCall(call, params) + suffix;
514 }
515
516 std::string generatePropertyDescriptor(const PropertyInfo& property)
517 {
518 if (!property.jsValue.empty())
519 return "value: " + property.jsValue;
520
521 std::string result("get: " + wrapCall(property.getter));
522 if (!property.setter.empty())
523 result += ", set: " + wrapCall(property.setter);
524 return result;
525 }
526
527 void printHelpers()
528 {
529 printf("var sizeofString = %i;\n", sizeof(String));
530
531 puts(R"(
532 function copyString(str, buffer)
533 {
534 var length = str.length;
535 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++)
536 HEAP16[pointer] = str.charCodeAt(i);
537 return length;
538 }
539
540 function createString(str)
541 {
542 var length = 0;
543 var buffer = 0;
544 if (str)
545 {
546 buffer = Runtime.stackAlloc(str.length * 2);
547 length = copyString(str, buffer);
548 }
549
550 var result = Runtime.stackAlloc(sizeofString);
551 Module._InitString(result, buffer, length);
552 return result;
553 }
554
555 function readString(str)
556 {
557 var length = Module._GetStringLength(str);
558 var pointer = Module._GetStringData(str) >> 1;
559 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + length));
560 }
561
562 function createClass(superclass, ref_counted_offset)
563 {
564 var result = function(pointer)
565 {
566 this._pointer = pointer;
567 };
568 if (superclass)
569 result.prototype = Object.create(superclass.prototype);
570 result.prototype.delete = function()
571 {
572 Module._ReleaseRef(this._pointer + ref_counted_offset);
573 };
574 return result;
575 }
576 )");
577 }
578
579 void printClass(const ClassInfo& cls)
580 {
581 printf("exports.%s = createClass(%s, %i);\n", cls.name.c_str(),
582 (cls.baseClass ? ("exports." + cls.baseClass->name).c_str() : "null"),
583 cls.ref_counted_offset);
584
585 DifferentiatorInfo differentiator = cls.subclass_differentiator;
586 if (differentiator.offset != SIZE_MAX)
587 {
588 printf("var %s_mapping = \n", cls.name.c_str());
589 puts("{");
590 for (const auto& item : differentiator.mapping)
591 printf(" %i: '%s',\n", item.first, item.second.c_str());
592 puts("};");
593
594 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str());
595 puts("{");
596 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset);
597 printf(" if (type in %s_mapping)\n", cls.name.c_str());
598 printf(" return new (exports[%s_mapping[type]])(ptr);\n", cls.name.c_st r());
599 printf(" throw new Error('Unexpected %s type: ' + type);\n", cls.name.c_s tr());
600 puts("};");
601 }
602 else
603 {
604 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str());
605 puts("{");
606 printf(" return new exports.%s(ptr);\n", cls.name.c_str());
607 puts("};");
608 }
609
610 for (const auto& item : cls.properties)
611 {
612 printf("Object.defineProperty(exports.%s.prototype, '%s', {%s});\n",
613 cls.name.c_str(), item.name.c_str(),
614 generatePropertyDescriptor(item).c_str());
615 }
616
617 for (const auto& item : cls.methods)
618 {
619 std::string obj("exports." + cls.name);
620 if (item.call.instance_function)
621 obj += ".prototype";
622 printf("%s.%s = %s;\n", obj.c_str(), item.name.c_str(),
623 wrapCall(item.call).c_str());
624 }
625 }
626
627 void printBindings()
628 {
629 printHelpers();
630
631 for (const auto& item : classes)
632 printClass(item.second);
633
634 for (const auto& item : customGenerators)
635 item();
636 }
637 } 217 }
638 218
639 #if defined(PRINT_BINDINGS)
640 // Bindings generation step: collect bindings information and print
641 // corresponding JS code.
642 #define EMSCRIPTEN_BINDINGS \
643 void InitializeBindings();\
644 int main()\
645 {\
646 try\
647 {\
648 InitializeBindings();\
649 bindings_internal::printBindings();\
650 }\
651 catch (const std::exception& e)\
652 {\
653 EM_ASM_ARGS(\
654 console.error("Error occurred generating JavaScript bindings: " +\
655 Module.AsciiToString($0)), e.what()\
656 );\
657 abort();\
658 }\
659 return 0;\
660 }\
661 void InitializeBindings()
662 #else
663 // Actual compilation step: ignore bindings information but define some
664 // exported helper functions necessary for the bindings.
665 #define EMSCRIPTEN_BINDINGS \
666 extern "C"\
667 {\
668 void EMSCRIPTEN_KEEPALIVE InitString(DependentString* str,\
669 String::value_type* data, String::size_type len)\
670 {\
671 /* String is already allocated on stack, we merely need to call*/\
672 /* constructor.*/\
673 new (str) DependentString(data, len);\
674 }\
675 void EMSCRIPTEN_KEEPALIVE DestroyString(OwnedString* str)\
676 {\
677 /* Stack memory will be freed automatically, we need to call*/\
678 /* destructor explicitly however.*/\
679 str->~OwnedString();\
680 }\
681 String::size_type EMSCRIPTEN_KEEPALIVE GetStringLength(\
682 const String& str)\
683 {\
684 return str.length();\
685 }\
686 const String::value_type* EMSCRIPTEN_KEEPALIVE GetStringData(\
687 const String& str)\
688 {\
689 return str.data();\
690 }\
691 void EMSCRIPTEN_KEEPALIVE ReleaseRef(ref_counted* ptr)\
692 {\
693 ptr->ReleaseRef();\
694 }\
695 }\
696 void BindingsInitializer_dummy()
697 #endif
698
699 template<typename ClassType, 219 template<typename ClassType,
700 typename BaseClass = bindings_internal::NoBaseClass, 220 typename BaseClass = bindings_internal::NoBaseClass,
701 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr> 221 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr>
702 class class_ 222 class class_
703 { 223 {
704 public: 224 public:
705 class_(const char* name) 225 class_(const char* name)
Wladimir Palant 2017/04/12 14:17:00 I would have preferred to move the implementations
706 { 226 {
707 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000); 227 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000);
708 ptrdiff_t ref_counted_offset = 228 ptrdiff_t ref_counted_offset =
709 reinterpret_cast<char*>(static_cast<ref_counted*>(ptr)) - 229 reinterpret_cast<char*>(static_cast<ref_counted*>(ptr)) -
710 reinterpret_cast<char*>(ptr); 230 reinterpret_cast<char*>(ptr);
711 bindings_internal::register_class(name, 231 bindings_internal::register_class(name,
712 bindings_internal::TypeInfo<ClassType>(), 232 bindings_internal::TypeInfo<ClassType>(),
713 bindings_internal::TypeInfo<BaseClass>(), 233 bindings_internal::TypeInfo<BaseClass>(),
714 ref_counted_offset 234 ref_counted_offset
715 ); 235 );
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 std::vector<std::pair<int, std::string>> mapping; 290 std::vector<std::pair<int, std::string>> mapping;
771 for (const auto& item : list) 291 for (const auto& item : list)
772 mapping.emplace_back(item.first, item.second); 292 mapping.emplace_back(item.first, item.second);
773 293
774 bindings_internal::register_differentiator( 294 bindings_internal::register_differentiator(
775 bindings_internal::TypeInfo<ClassType>(), offset, mapping); 295 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
776 return *this; 296 return *this;
777 } 297 }
778 }; 298 };
779 299
780 void custom_generator(bindings_internal::CustomGenerator generator) 300 void custom_generator(bindings_internal::CustomGenerator generator);
781 { 301
782 bindings_internal::customGenerators.push_back(generator); 302 void printBindings();
783 }
OLDNEW
« no previous file with comments | « compile ('k') | compiled/bindings/generator.cpp » ('j') | compiled/bindings/generator.cpp » ('J')

Powered by Google App Engine
This is Rietveld