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

Delta Between Two Patch Sets: compiled/bindings.ipp

Issue 29333474: Issue 4125 - [emscripten] Convert filter classes to C++ (Closed)
Left Patch Set: Renamed bindings.h into bindings.ipp Created Feb. 23, 2016, 9:30 p.m.
Right Patch Set: Addressed comments from Patch Set 28 Created March 21, 2017, 10:04 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/bindings.cpp ('k') | compiled/debug.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #pragma once 1 #pragma once
2 2
3 #include <cstddef>
4 #include <cstdint>
3 #include <cstdio> 5 #include <cstdio>
4 #include <cstdlib> 6 #include <cstdlib>
5 #include <cstring>
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
13 #include <emscripten.h> 14 #include <emscripten.h>
14 15
15 #include "String.h" 16 #include "String.h"
(...skipping 10 matching lines...) Expand all
26 INT, 27 INT,
27 DEPENDENT_STRING, 28 DEPENDENT_STRING,
28 OWNED_STRING, 29 OWNED_STRING,
29 STRING_REF, 30 STRING_REF,
30 CLASS_PTR 31 CLASS_PTR
31 }; 32 };
32 33
33 template<typename T> 34 template<typename T>
34 struct TypeInfo 35 struct TypeInfo
35 { 36 {
36 static char c; 37 /*
38 * Since TypeInfo is a templated type, in practice the compiler will define
39 * a new type for each possible template parameter value. We use that fact
40 * to generate type identifiers: each of these TypeInfo types has a
41 * different s_typeIDHelper member, so we use a pointer to that static
42 * variable as a type identifier - it will be different for each template
43 * parameter.
44 */
45 static char s_typeIDHelper;
37 constexpr operator TYPEID() const 46 constexpr operator TYPEID() const
38 { 47 {
39 return &c; 48 return &s_typeIDHelper;
40 } 49 }
41 50
42 constexpr operator TypeCategory() const 51 constexpr operator TypeCategory() const
43 { 52 {
44 if (std::is_void<T>()) 53 if (std::is_void<T>())
45 return TypeCategory::VOID; 54 return TypeCategory::VOID;
46 55
47 if (std::is_integral<T>() || std::is_enum<T>()) 56 if (std::is_integral<T>() || std::is_enum<T>())
48 return TypeCategory::INT; 57 return TypeCategory::INT;
49 58
50 if (std::is_same<DependentString,T>() || std::is_same<const DependentStrin g,T>()) 59 if (std::is_same<DependentString, T>() || std::is_same<const DependentStri ng, T>())
51 return TypeCategory::DEPENDENT_STRING; 60 return TypeCategory::DEPENDENT_STRING;
52 61
53 if (std::is_same<OwnedString,T>() || std::is_same<const OwnedString,T>()) 62 if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>() )
54 return TypeCategory::OWNED_STRING; 63 return TypeCategory::OWNED_STRING;
55 64
56 if (std::is_same<String&,T>() || std::is_same<const String&,T>() || 65 if (std::is_same<String&, T>() || std::is_same<const String&, T>() ||
57 std::is_same<DependentString&,T>()) 66 std::is_same<DependentString&, T>())
58 { 67 {
59 return TypeCategory::STRING_REF; 68 return TypeCategory::STRING_REF;
60 } 69 }
61 70
62 if (std::is_pointer<T>() && std::is_class<typename std::remove_pointer<T>: :type>()) 71 if (std::is_pointer<T>() && std::is_class<typename std::remove_pointer<T>: :type>())
63 return TypeCategory::CLASS_PTR; 72 return TypeCategory::CLASS_PTR;
64 73
65 return TypeCategory::UNKNOWN; 74 return TypeCategory::UNKNOWN;
66 } 75 }
67 76
68 TYPEID pointer_type() const 77 constexpr TYPEID pointer_type() const
69 { 78 {
70 if (std::is_pointer<T>()) 79 if (std::is_pointer<T>())
71 return TypeInfo<typename std::remove_pointer<T>::type>(); 80 return TypeInfo<typename std::remove_pointer<T>::type>();
72 else 81 else
73 return nullptr; 82 return nullptr;
74 } 83 }
75 }; 84 };
76 85
77 template<typename T> 86 template<typename T>
78 char TypeInfo<T>::c; 87 char TypeInfo<T>::s_typeIDHelper;
79 88
80 struct FunctionInfo 89 struct FunctionInfo
81 { 90 {
82 TypeCategory returnType; 91 TypeCategory returnType;
83 TYPEID pointerType; 92 TYPEID pointerType;
84 std::vector<TypeCategory> args; 93 std::vector<TypeCategory> args;
85 bool instance_function; 94 bool instance_function;
86 int effectiveArgs; 95 int effectiveArgs;
87 TypeCategory effectiveReturnType; 96 TypeCategory effectiveReturnType;
88 char name[1024]; 97 char name[1024];
89 98
90 FunctionInfo() 99 FunctionInfo()
91 { 100 {
92 name[0] = 0; 101 name[0] = '\0';
93 } 102 }
94 103
95 FunctionInfo(TypeCategory returnType, TYPEID pointerType, 104 FunctionInfo(TypeCategory returnType, TYPEID pointerType,
96 std::initializer_list<TypeCategory> argTypes, bool instance_function, 105 std::initializer_list<TypeCategory> argTypes, bool instance_function,
97 void* function) 106 void* function)
98 : returnType(returnType), pointerType(pointerType), 107 : returnType(returnType), pointerType(pointerType),
99 instance_function(instance_function) 108 instance_function(instance_function)
100 { 109 {
101 name[0] = 0; 110 name[0] = '\0';
102 111
103 // The function parameter is a pointer to the function pointer. 112 // The function parameter is a pointer to the function pointer.
104 // Emscripten's "function pointers" are actually integers indicating the 113 // Emscripten's "function pointers" are actually integers indicating the
105 // position in the call table. 0 represents nullptr. 114 // position in the call table. 0 represents nullptr.
106 if (!*reinterpret_cast<int*>(function)) 115 if (!*reinterpret_cast<int*>(function))
107 return; 116 return;
108 117
109 for (auto it = argTypes.begin(); it != argTypes.end(); ++it) 118 for (const auto& item : argTypes)
110 { 119 {
111 if (*it != TypeCategory::INT && *it != TypeCategory::STRING_REF && 120 if (item != TypeCategory::INT && item != TypeCategory::STRING_REF &&
112 *it != TypeCategory::CLASS_PTR) 121 item != TypeCategory::CLASS_PTR)
113 { 122 {
114 throw std::runtime_error("Unexpected function argument type"); 123 throw std::runtime_error("Unexpected function argument type");
115 } 124 }
116 args.push_back(*it); 125 args.push_back(item);
117 } 126 }
118 127
119 if (returnType != TypeCategory::VOID && returnType != TypeCategory::INT && 128 if (returnType != TypeCategory::VOID && returnType != TypeCategory::INT &&
120 returnType != TypeCategory::DEPENDENT_STRING && 129 returnType != TypeCategory::DEPENDENT_STRING &&
121 returnType != TypeCategory::OWNED_STRING && 130 returnType != TypeCategory::OWNED_STRING &&
122 returnType != TypeCategory::STRING_REF && 131 returnType != TypeCategory::STRING_REF &&
123 returnType != TypeCategory::CLASS_PTR) 132 returnType != TypeCategory::CLASS_PTR)
124 { 133 {
125 throw std::runtime_error("Unexpected function return type"); 134 throw std::runtime_error("Unexpected function return type");
126 } 135 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 template<typename ClassType, typename ReturnType, typename... Args> 169 template<typename ClassType, typename ReturnType, typename... Args>
161 FunctionInfo(ReturnType (ClassType::*function)(Args...) const) 170 FunctionInfo(ReturnType (ClassType::*function)(Args...) const)
162 : FunctionInfo(TypeInfo<ReturnType>(), 171 : FunctionInfo(TypeInfo<ReturnType>(),
163 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, 172 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true,
164 &function) 173 &function)
165 { 174 {
166 } 175 }
167 176
168 bool empty() const 177 bool empty() const
169 { 178 {
170 return name[0] == 0; 179 return name[0] == '\0';
171 } 180 }
172 181
173 void get_function_name(void* ptr, int numArgs, bool voidResult) 182 void get_function_name(void* ptr, int numArgs, bool voidResult)
174 { 183 {
175 // This is a hack, C++ won't let us get the mangled function name. 184 // This is a hack, C++ won't let us get the mangled function name.
176 // JavaScript is more dynamic so we pass the pointer to our function 185 // JavaScript is more dynamic so we pass the pointer to our function
177 // there. With that and the function signature we can call the function - 186 // there. With that and the function signature we can call the function -
178 // with a full stack so that we will cause it to abort. Sometimes the 187 // with a full stack so that we will cause it to abort. Sometimes the
179 // function we are calling will also be missing from the build. The result 188 // function we are calling will also be missing from the build. The result
180 // is the same: abort() is called which in turn calls stackTrace(). By 189 // is the same: abort() is called which in turn calls stackTrace(). By
181 // replacing stackTrace() we get access to the call stack and search it 190 // replacing stackTrace() we get access to the call stack and search it
182 // for the name of our function. 191 // for the name of our function.
183 192
184 EM_ASM_ARGS({ 193 EM_ASM_ARGS({
185 var signature = $3 ? "v" : "i"; 194 var signature = $3 ? "v" : "i";
186 var args = []; 195 var args = [];
187 for (var i = 0; i < $2; i++) 196 for (var i = 0; i < $2; i++)
188 { 197 {
189 signature += "i"; 198 signature += "i";
190 args.push(0); 199 args.push(0);
191 } 200 }
192 201
202 var oldPrint = Module.print;
193 var oldPrintErr = Module.printErr; 203 var oldPrintErr = Module.printErr;
194 var oldStackTrace = stackTrace; 204 var oldStackTrace = stackTrace;
195 var sp = Runtime.stackSave(); 205 var sp = Runtime.stackSave();
206 Module.print = function(){};
196 Module.printErr = function(){}; 207 Module.printErr = function(){};
197 stackTrace = function() 208 stackTrace = function()
198 { 209 {
199 var stack = []; 210 var stack = [];
200 for (var f = arguments.callee.caller; f; f = f.caller) 211 for (var f = arguments.callee.caller; f; f = f.caller)
201 { 212 {
202 if (f.name) 213 if (f.name)
203 { 214 {
204 if (f.name.indexOf("dynCall") == 0) 215 if (f.name.indexOf("dynCall") == 0)
205 break; 216 break;
(...skipping 14 matching lines...) Expand all
220 { 231 {
221 Runtime.dynCall(signature, HEAP32[$1 >> 2], args); 232 Runtime.dynCall(signature, HEAP32[$1 >> 2], args);
222 } 233 }
223 catch(e) 234 catch(e)
224 { 235 {
225 Module.stringToAscii(e, $0); 236 Module.stringToAscii(e, $0);
226 } 237 }
227 finally 238 finally
228 { 239 {
229 Runtime.stackRestore(sp); 240 Runtime.stackRestore(sp);
241 Module.print = oldPrint;
230 Module.printErr = oldPrintErr; 242 Module.printErr = oldPrintErr;
231 stackTrace = oldStackTrace; 243 stackTrace = oldStackTrace;
232 } 244 }
233 }, name, ptr, numArgs, voidResult); 245 }, name, ptr, numArgs, voidResult);
234 } 246 }
235 }; 247 };
236 248
237 class NoBaseClass 249 class NoBaseClass
238 { 250 {
239 }; 251 };
240 252
241 struct PropertyInfo 253 struct PropertyInfo
242 { 254 {
243 std::string name; 255 std::string name;
244 FunctionInfo getter; 256 FunctionInfo getter;
245 FunctionInfo setter; 257 FunctionInfo setter;
246 std::string jsValue; 258 std::string jsValue;
247 }; 259 };
248 260
249 struct MethodInfo 261 struct MethodInfo
250 { 262 {
251 std::string name; 263 std::string name;
252 FunctionInfo call; 264 FunctionInfo call;
253 }; 265 };
254 266
255 struct DifferentiatorInfo 267 struct DifferentiatorInfo
256 { 268 {
257 FunctionInfo call; 269 size_t offset;
258 std::vector<std::pair<int,std::string>> mapping; 270 std::vector<std::pair<int, std::string>> mapping;
259 }; 271 };
260 272
261 struct ClassInfo 273 struct ClassInfo
262 { 274 {
263 ClassInfo* baseClass; 275 ClassInfo* baseClass;
264 std::string name; 276 std::string name;
265 std::vector<PropertyInfo> properties; 277 std::vector<PropertyInfo> properties;
266 std::vector<MethodInfo> methods; 278 std::vector<MethodInfo> methods;
267 std::vector<FunctionInfo> initializers; 279 std::vector<FunctionInfo> initializers;
268 DifferentiatorInfo subclass_differentiator; 280 DifferentiatorInfo subclass_differentiator;
281 ptrdiff_t ref_counted_offset;
269 }; 282 };
270 283
271 std::map<TYPEID,ClassInfo> classes; 284 std::map<TYPEID, ClassInfo> classes;
272 285
273 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)
274 { 288 {
275 auto it = classes.find(classID); 289 auto it = classes.find(classID);
276 if (it != classes.end()) 290 if (it != classes.end())
277 throw std::runtime_error(std::string("Duplicate definition for class ") + name); 291 throw std::runtime_error(std::string("Duplicate definition for class ") + name);
278 292
279 ClassInfo* baseClass = nullptr; 293 ClassInfo* baseClass = nullptr;
280 if (baseClassID != TypeInfo<NoBaseClass>()) 294 if (baseClassID != TypeInfo<NoBaseClass>())
281 { 295 {
282 it = classes.find(baseClassID); 296 it = classes.find(baseClassID);
283 if (it == classes.end()) 297 if (it == classes.end())
284 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);
285 baseClass = &(it->second); 299 baseClass = &(it->second);
286 } 300 }
287 301
288 ClassInfo classInfo; 302 ClassInfo classInfo;
289 classInfo.baseClass = baseClass; 303 classInfo.baseClass = baseClass;
290 classInfo.name = name; 304 classInfo.name = name;
305 classInfo.subclass_differentiator.offset = SIZE_MAX;
306 classInfo.ref_counted_offset = ref_counted_offset;
291 classes[classID] = classInfo; 307 classes[classID] = classInfo;
292 } 308 }
293 309
294 void register_property(TYPEID classID, const char* name, 310 void register_property(TYPEID classID, const char* name,
295 const FunctionInfo& getter, const FunctionInfo& setter, 311 const FunctionInfo& getter, const FunctionInfo& setter,
296 const char* jsValue = "") 312 const char* jsValue = "")
297 { 313 {
298 auto it = classes.find(classID); 314 auto it = classes.find(classID);
299 if (it == classes.end()) 315 if (it == classes.end())
300 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 21 matching lines...) Expand all
322 338
323 void register_initializer(TYPEID classID, const FunctionInfo& call) 339 void register_initializer(TYPEID classID, const FunctionInfo& call)
324 { 340 {
325 auto it = classes.find(classID); 341 auto it = classes.find(classID);
326 if (it == classes.end()) 342 if (it == classes.end())
327 throw std::runtime_error("Initializer defined on unknown class"); 343 throw std::runtime_error("Initializer defined on unknown class");
328 344
329 it->second.initializers.push_back(call); 345 it->second.initializers.push_back(call);
330 } 346 }
331 347
332 void register_differentiator(TYPEID classID, const FunctionInfo& call, 348 void register_differentiator(TYPEID classID, size_t offset,
333 std::vector<std::pair<int,std::string>>& mapping) 349 std::vector<std::pair<int, std::string>>& mapping)
334 { 350 {
335 auto it = classes.find(classID); 351 auto it = classes.find(classID);
336 if (it == classes.end()) 352 if (it == classes.end())
337 throw std::runtime_error("Subclass differentiator defined on unknown class "); 353 throw std::runtime_error("Subclass differentiator defined on unknown class ");
338 354
339 if (!it->second.subclass_differentiator.call.empty()) 355 if (it->second.subclass_differentiator.offset != SIZE_MAX)
340 throw std::runtime_error("More than one subclass differentiator defined fo r class " + it->second.name); 356 throw std::runtime_error("More than one subclass differentiator defined fo r class " + it->second.name);
341 357
342 DifferentiatorInfo differentiatorInfo; 358 DifferentiatorInfo differentiatorInfo;
343 differentiatorInfo.call = call; 359 differentiatorInfo.offset = offset;
344 differentiatorInfo.mapping = mapping; 360 differentiatorInfo.mapping = mapping;
345 it->second.subclass_differentiator = differentiatorInfo; 361 it->second.subclass_differentiator = differentiatorInfo;
346 } 362 }
347 363
348 const std::string generateCall(const FunctionInfo& call, 364 const std::string generateCall(const FunctionInfo& call,
349 std::vector<std::string>& params) 365 std::vector<std::string>& params)
350 { 366 {
351 if (call.returnType == TypeCategory::DEPENDENT_STRING || 367 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
352 call.returnType == TypeCategory::OWNED_STRING) 368 call.returnType == TypeCategory::OWNED_STRING)
353 { 369 {
(...skipping 13 matching lines...) Expand all
367 if (call.returnType == TypeCategory::VOID) 383 if (call.returnType == TypeCategory::VOID)
368 return " " + call_str + ";\n"; 384 return " " + call_str + ";\n";
369 else if (call.returnType == TypeCategory::INT) 385 else if (call.returnType == TypeCategory::INT)
370 return " var result = " + call_str + ";\n"; 386 return " var result = " + call_str + ";\n";
371 else if (call.returnType == TypeCategory::DEPENDENT_STRING || 387 else if (call.returnType == TypeCategory::DEPENDENT_STRING ||
372 call.returnType == TypeCategory::OWNED_STRING) 388 call.returnType == TypeCategory::OWNED_STRING)
373 { 389 {
374 std::string result; 390 std::string result;
375 result += " var string = createString();\n"; 391 result += " var string = createString();\n";
376 result += " " + call_str + ";\n"; 392 result += " " + call_str + ";\n";
377 result += " var result = getStringData(string);\n"; 393 result += " var result = readString(string);\n";
378 if (call.returnType == TypeCategory::OWNED_STRING) 394 if (call.returnType == TypeCategory::OWNED_STRING)
379 result += " Module._DestroyString(string);\n"; 395 result += " Module._DestroyString(string);\n";
380 return result; 396 return result;
381 } 397 }
382 else if (call.returnType == TypeCategory::STRING_REF) 398 else if (call.returnType == TypeCategory::STRING_REF)
383 { 399 {
384 return " var result = getStringData(" + call_str + ");\n"; 400 return " var result = readString(" + call_str + ");\n";
385 } 401 }
386 else if (call.returnType == TypeCategory::CLASS_PTR) 402 else if (call.returnType == TypeCategory::CLASS_PTR)
387 { 403 {
388 std::string result; 404 std::string result;
389 result += " var result = " + call_str + ";\n"; 405 result += " var result = " + call_str + ";\n";
390 result += " if (result)\n"; 406 result += " if (result)\n";
391 result += " {\n"; 407 result += " {\n";
392 result += " Module._AddRef(result);\n";
393 408
394 auto it = classes.find(call.pointerType); 409 auto it = classes.find(call.pointerType);
395 if (it == classes.end()) 410 if (it == classes.end())
396 throw std::runtime_error("Function " + std::string(call.name) + " return s pointer to unknown class"); 411 throw std::runtime_error("Function " + std::string(call.name) + " return s pointer to unknown class");
397 412
398 const ClassInfo& cls = it->second; 413 const ClassInfo& cls = it->second;
399 if (cls.subclass_differentiator.call.empty()) 414 auto offset = cls.subclass_differentiator.offset;
415 if (offset == SIZE_MAX)
400 result += " result = " + cls.name + "(result);\n"; 416 result += " result = " + cls.name + "(result);\n";
401 else 417 else
402 { 418 {
403 result += " var type = " + 419 result += " var type = HEAP32[result + " + std::to_string(offset)+ " >> 2];\n";
404 std::string(cls.subclass_differentiator.call.name) + "(result);\n";
405 result += " if (type in " + cls.name + "_mapping)\n"; 420 result += " if (type in " + cls.name + "_mapping)\n";
406 result += " result = new (exports[" + cls.name + "_mapping[type]])( result);\n"; 421 result += " result = new (exports[" + cls.name + "_mapping[type]])( result);\n";
407 result += " else\n"; 422 result += " else\n";
408 result += " throw new Error('Unexpected " + cls.name + " type: ' + type);\n"; 423 result += " throw new Error('Unexpected " + cls.name + " type: ' + type);\n";
409 } 424 }
410 425
411 result += " }\n"; 426 result += " }\n";
412 return result; 427 return result;
413 } 428 }
414 else 429 else
415 throw std::runtime_error("Unexpected return type for " + std::string(call. name)); 430 throw std::runtime_error("Unexpected return type for " + std::string(call. name));
416 } 431 }
417 432
418 const std::string wrapCall(const FunctionInfo& call) 433 const std::string wrapCall(const FunctionInfo& call)
419 { 434 {
420 char buffer[20]; 435 char buffer[20];
421 bool hasStringArgs = false; 436 bool hasStringArgs = false;
422 std::vector<std::string> params; 437 std::vector<std::string> params;
423 std::string prefix = "function("; 438 std::string prefix = "function(";
424 for (int i = 0; i < call.args.size(); i++) 439 for (int i = 0; i < call.args.size(); i++)
425 { 440 {
426 sprintf(buffer, "arg%i", i); 441 sprintf(buffer, "arg%i", i);
427 if (i > 0) 442 if (i > 0)
428 prefix += ", "; 443 prefix += ", ";
429 prefix += buffer; 444 prefix += buffer;
430
431 445
432 if (call.args[i] == TypeCategory::STRING_REF) 446 if (call.args[i] == TypeCategory::STRING_REF)
433 { 447 {
434 hasStringArgs = true; 448 hasStringArgs = true;
435 params.push_back(std::string("createString(") + buffer + ")"); 449 params.push_back(std::string("createString(") + buffer + ")");
436 } 450 }
437 else 451 else
438 params.push_back(buffer); 452 params.push_back(buffer);
439 } 453 }
440 prefix += ")\n{\n"; 454 prefix += ")\n{\n";
441 455
442 std::string suffix = "}"; 456 std::string suffix = "}";
443 if (call.returnType != TypeCategory::VOID) 457 if (call.returnType != TypeCategory::VOID)
444 suffix = " return result;\n" + suffix; 458 suffix = " return result;\n" + suffix;
445 459
446 if (call.returnType == TypeCategory::DEPENDENT_STRING || 460 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
447 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) 461 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
448 { 462 {
449 prefix += " var sp = Runtime.stackSave();\n"; 463 prefix += " var sp = Runtime.stackSave();\n";
450 suffix = " Runtime.stackRestore(sp);\n" + suffix; 464 suffix = " Runtime.stackRestore(sp);\n" + suffix;
451 } 465 }
452 466
453 if (call.instance_function) 467 if (call.instance_function)
454 params.insert(params.begin(), "this._pointer"); 468 params.insert(params.begin(), "this._pointer");
455 469
456 return prefix + generateCall(call, params) + suffix; 470 return prefix + generateCall(call, params) + suffix;
457 } 471 }
458 472
459 const std::string generatePropertyDescriptor(const PropertyInfo& property) 473 std::string generatePropertyDescriptor(const PropertyInfo& property)
460 { 474 {
461 if (!property.jsValue.empty()) 475 if (!property.jsValue.empty())
462 return "value: " + property.jsValue; 476 return "value: " + property.jsValue;
463 477
464 std::string result("get: " + wrapCall(property.getter)); 478 std::string result("get: " + wrapCall(property.getter));
465 if (!property.setter.empty()) 479 if (!property.setter.empty())
466 result += ", set: " + wrapCall(property.setter); 480 result += ", set: " + wrapCall(property.setter);
467 return result; 481 return result;
468 } 482 }
469 483
470 void printHelpers() 484 void printHelpers()
471 { 485 {
472 printf("var sizeofString = %i\n", sizeof(String)); 486 printf("var sizeofString = %i;\n", sizeof(String));
473 487
474 puts(R"( 488 puts(R"(
475 function copyString(str, buffer) 489 function copyString(str, buffer)
476 { 490 {
477 var length = str.length; 491 var length = str.length;
478 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++) 492 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++)
479 HEAP16[pointer] = str.charCodeAt(i); 493 HEAP16[pointer] = str.charCodeAt(i);
480 return length; 494 return length;
481 } 495 }
482 496
483 function createString(str) 497 function createString(str)
484 { 498 {
485 var length = 0; 499 var length = 0;
486 var buffer = 0; 500 var buffer = 0;
487 if (str) 501 if (str)
488 { 502 {
489 buffer = Runtime.stackAlloc(str.length * 2); 503 buffer = Runtime.stackAlloc(str.length * 2);
490 length = copyString(str, buffer); 504 length = copyString(str, buffer);
491 } 505 }
492 506
493 var result = Module.Runtime.stackAlloc(sizeofString); 507 var result = Module.Runtime.stackAlloc(sizeofString);
494 Module._InitString(result, buffer, length); 508 Module._InitString(result, buffer, length);
495 return result; 509 return result;
496 } 510 }
497 511
498 function getStringData(str) 512 function readString(str)
499 { 513 {
500 var length = Module._GetStringLength(str); 514 var length = Module._GetStringLength(str);
501 var pointer = Module._GetStringData(str) >> 1; 515 var pointer = Module._GetStringData(str) >> 1;
502 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len gth)); 516 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len gth));
503 } 517 }
504 518
505 function createClass(superclass) 519 function createClass(superclass, ref_counted_offset)
506 { 520 {
507 var result = function(pointer) 521 var result = function(pointer)
508 { 522 {
509 this._pointer = pointer; 523 this._pointer = pointer;
510 }; 524 };
511 if (superclass) 525 if (superclass)
512 result.prototype = Object.create(superclass.prototype); 526 result.prototype = Object.create(superclass.prototype);
513 result.prototype.delete = function() 527 result.prototype.delete = function()
514 { 528 {
515 Module._ReleaseRef(this._pointer); 529 Module._ReleaseRef(this._pointer + ref_counted_offset);
516 }; 530 };
517 return result; 531 return result;
518 })"); 532 })");
519 } 533 }
520 534
521 void printClass(ClassInfo& cls) 535 void printClass(const ClassInfo& cls)
522 { 536 {
523 DifferentiatorInfo differentiator = cls.subclass_differentiator; 537 DifferentiatorInfo differentiator = cls.subclass_differentiator;
524 if (!differentiator.call.empty()) 538 if (differentiator.offset != SIZE_MAX)
525 { 539 {
526 printf("var %s_mapping = \n", cls.name.c_str()); 540 printf("var %s_mapping = \n", cls.name.c_str());
527 puts("{"); 541 puts("{");
528 for (auto it = differentiator.mapping.begin(); it != differentiator.mappin g.end(); ++it) 542 for (const auto& item : differentiator.mapping)
529 printf(" %i: '%s',\n", it->first, it->second.c_str()); 543 printf(" %i: '%s',\n", item.first, item.second.c_str());
530 puts("};"); 544 puts("};");
531 } 545 }
532 546
533 printf("exports.%s = createClass(%s);\n", cls.name.c_str(), 547 printf("exports.%s = createClass(%s, %i);\n", cls.name.c_str(),
534 (cls.baseClass ? ("exports." + cls.baseClass->name).c_str() : "")); 548 (cls.baseClass ? ("exports." + cls.baseClass->name).c_str() : "null"),
535 549 cls.ref_counted_offset);
536 for (auto it = cls.properties.begin(); it != cls.properties.end(); ++it) 550
551 for (const auto& item : cls.properties)
537 { 552 {
538 printf("Object.defineProperty(exports.%s.prototype, '%s', {%s});\n", 553 printf("Object.defineProperty(exports.%s.prototype, '%s', {%s});\n",
539 cls.name.c_str(), it->name.c_str(), 554 cls.name.c_str(), item.name.c_str(),
540 generatePropertyDescriptor(*it).c_str()); 555 generatePropertyDescriptor(item).c_str());
541 } 556 }
542 557
543 for (auto it = cls.methods.begin(); it != cls.methods.end(); ++it) 558 for (const auto& item : cls.methods)
544 { 559 {
545 std::string obj("exports." + cls.name); 560 std::string obj("exports." + cls.name);
546 if (it->call.instance_function) 561 if (item.call.instance_function)
547 obj += ".prototype"; 562 obj += ".prototype";
548 printf("%s.%s = %s;\n", obj.c_str(), it->name.c_str(), 563 printf("%s.%s = %s;\n", obj.c_str(), item.name.c_str(),
549 wrapCall(it->call).c_str()); 564 wrapCall(item.call).c_str());
550 } 565 }
551 566
552 for (auto it = cls.initializers.begin(); it != cls.initializers.end(); ++it) 567 for (const auto& item : cls.initializers)
553 printf("%s()\n", it->name); 568 printf("%s()\n", item.name);
554 } 569 }
555 570
556 void printBindings() 571 void printBindings()
557 { 572 {
558 printHelpers(); 573 printHelpers();
559 574
560 for (auto it = classes.begin(); it != classes.end(); ++it) 575 for (const auto& item : classes)
561 printClass(it->second); 576 printClass(item.second);
562 } 577 }
563 } 578 }
564 579
565 #if defined(PRINT_BINDINGS) 580 #if defined(PRINT_BINDINGS)
566 // Bindings generation step: collect bindings information and print 581 // Bindings generation step: collect bindings information and print
567 // corresponding JS code. 582 // corresponding JS code.
568 #define EMSCRIPTEN_BINDINGS \ 583 #define EMSCRIPTEN_BINDINGS \
569 static struct BindingsInitializer {\ 584 struct BindingsInitializer {\
570 BindingsInitializer();\ 585 BindingsInitializer();\
571 BindingsInitializer(bool dummy)\ 586 BindingsInitializer(bool dummy)\
572 {\ 587 {\
573 try\ 588 try\
574 {\ 589 {\
575 BindingsInitializer();\ 590 BindingsInitializer();\
576 bindings_internal::printBindings();\ 591 bindings_internal::printBindings();\
577 }\ 592 }\
578 catch (const std::exception& e)\ 593 catch (const std::exception& e)\
579 {\ 594 {\
(...skipping 28 matching lines...) Expand all
608 String::size_type EMSCRIPTEN_KEEPALIVE GetStringLength(\ 623 String::size_type EMSCRIPTEN_KEEPALIVE GetStringLength(\
609 const String& str)\ 624 const String& str)\
610 {\ 625 {\
611 return str.length();\ 626 return str.length();\
612 }\ 627 }\
613 const String::value_type* EMSCRIPTEN_KEEPALIVE GetStringData(\ 628 const String::value_type* EMSCRIPTEN_KEEPALIVE GetStringData(\
614 const String& str)\ 629 const String& str)\
615 {\ 630 {\
616 return str.data();\ 631 return str.data();\
617 }\ 632 }\
618 void EMSCRIPTEN_KEEPALIVE AddRef(ref_counted* ptr)\
619 {\
620 ptr->AddRef();\
621 }\
622 void EMSCRIPTEN_KEEPALIVE ReleaseRef(ref_counted* ptr)\ 633 void EMSCRIPTEN_KEEPALIVE ReleaseRef(ref_counted* ptr)\
623 {\ 634 {\
624 ptr->ReleaseRef();\ 635 ptr->ReleaseRef();\
625 }\ 636 }\
626 }\ 637 }\
627 void BindingsInitializer_dummy() 638 void BindingsInitializer_dummy()
628 #endif 639 #endif
629 640
630 template<typename ClassType, 641 template<typename ClassType,
631 typename BaseClass = bindings_internal::NoBaseClass, 642 typename BaseClass = bindings_internal::NoBaseClass,
632 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>
633 class class_ 644 class class_
634 { 645 {
635 public: 646 public:
636 class_(const char* name) 647 class_(const char* name)
637 { 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);
638 bindings_internal::register_class(name, 653 bindings_internal::register_class(name,
639 bindings_internal::TypeInfo<ClassType>(), 654 bindings_internal::TypeInfo<ClassType>(),
640 bindings_internal::TypeInfo<BaseClass>()); 655 bindings_internal::TypeInfo<BaseClass>(),
656 ref_counted_offset
657 );
641 } 658 }
642 659
643 template<typename FieldType> 660 template<typename FieldType>
644 const class_& property(const char* name, 661 const class_& property(const char* name,
645 FieldType (ClassType::*getter)() const, 662 FieldType (ClassType::*getter)() const,
646 void (ClassType::*setter)(FieldType) = 0) const 663 void (ClassType::*setter)(FieldType) = nullptr) const
647 { 664 {
648 bindings_internal::register_property( 665 bindings_internal::register_property(
649 bindings_internal::TypeInfo<ClassType>(), name, getter, setter); 666 bindings_internal::TypeInfo<ClassType>(), name, getter, setter);
650 return *this; 667 return *this;
651 } 668 }
652 669
653 const class_& class_property(const char* name, 670 const class_& class_property(const char* name,
654 const char* jsValue) const 671 const char* jsValue) const
655 { 672 {
656 bindings_internal::register_property( 673 bindings_internal::register_property(
(...skipping 28 matching lines...) Expand all
685 } 702 }
686 703
687 const class_& class_initializer(void (*function)()) const 704 const class_& class_initializer(void (*function)()) const
688 { 705 {
689 bindings_internal::register_initializer( 706 bindings_internal::register_initializer(
690 bindings_internal::TypeInfo<ClassType>(), function); 707 bindings_internal::TypeInfo<ClassType>(), function);
691 return *this; 708 return *this;
692 } 709 }
693 710
694 template<typename ReturnType, 711 template<typename ReturnType,
695 typename std::enable_if<std::is_convertible<ReturnType, int>::value>::type * = nullptr> 712 typename std::enable_if<std::is_convertible<ReturnType, int32_t>::value>:: type* = nullptr>
696 const class_& subclass_differentiator(ReturnType (*function)(ClassType*), 713 const class_& subclass_differentiator(ReturnType ClassType::* member,
697 std::initializer_list<std::pair<ReturnType,const char*>> list) const 714 std::initializer_list<std::pair<ReturnType, const char*>> list) const
698 { 715 {
699 std::vector<std::pair<int,std::string>> mapping; 716 ClassType* instance = nullptr;
700 for (auto it = list.begin(); it != list.end(); ++it) 717 size_t offset = (char*)&(instance->*member) - (char*)instance;
701 mapping.push_back(std::pair<int,std::string>(it->first, it->second)); 718
719 std::vector<std::pair<int, std::string>> mapping;
720 for (const auto& item : list)
721 mapping.emplace_back(item.first, item.second);
702 722
703 bindings_internal::register_differentiator( 723 bindings_internal::register_differentiator(
704 bindings_internal::TypeInfo<ClassType>(), function, mapping); 724 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
705 return *this; 725 return *this;
706 } 726 }
707 }; 727 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld