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

Powered by Google App Engine
This is Rietveld