OLD | NEW |
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 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 121 |
122 ClassInfo* find_class(TYPEID classID) | 122 ClassInfo* find_class(TYPEID classID) |
123 { | 123 { |
124 for (auto& classInfo : classes) | 124 for (auto& classInfo : classes) |
125 if (classInfo.id == classID) | 125 if (classInfo.id == classID) |
126 return &classInfo; | 126 return &classInfo; |
127 return nullptr; | 127 return nullptr; |
128 } | 128 } |
129 | 129 |
130 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, | 130 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, |
131 ptrdiff_t ref_counted_offset) | 131 ptrdiff_t ref_counted_offset, |
| 132 const FunctionInfo& instanceGetter) |
132 { | 133 { |
133 if (find_class(classID)) | 134 if (find_class(classID)) |
134 throw std::runtime_error(std::string("Duplicate definition for class ") +
name); | 135 throw std::runtime_error(std::string("Duplicate definition for class ") +
name); |
135 | 136 |
136 if (baseClassID != TypeInfo<NoBaseClass>() && !find_class(baseClassID)) | 137 if (baseClassID != TypeInfo<NoBaseClass>() && !find_class(baseClassID)) |
137 throw std::runtime_error(std::string("Unknown base class defined for class
") + name); | 138 throw std::runtime_error(std::string("Unknown base class defined for class
") + name); |
138 | 139 |
139 ClassInfo classInfo; | 140 ClassInfo classInfo; |
140 classInfo.id = classID; | 141 classInfo.id = classID; |
141 classInfo.baseClass = baseClassID; | 142 classInfo.baseClass = baseClassID; |
142 classInfo.name = name; | 143 classInfo.name = name; |
143 classInfo.subclass_differentiator.offset = SIZE_MAX; | 144 classInfo.subclass_differentiator.offset = SIZE_MAX; |
144 classInfo.ref_counted_offset = ref_counted_offset; | 145 classInfo.ref_counted_offset = ref_counted_offset; |
| 146 classInfo.instanceGetter = instanceGetter; |
145 classes.push_back(classInfo); | 147 classes.push_back(classInfo); |
146 } | 148 } |
147 | 149 |
148 void register_property(TYPEID classID, const char* name, | 150 void register_property(TYPEID classID, const char* name, |
149 const FunctionInfo& getter, const FunctionInfo& setter, | 151 const FunctionInfo& getter, const FunctionInfo& setter, |
150 const char* jsValue) | 152 const char* jsValue) |
151 { | 153 { |
152 ClassInfo* classInfo = find_class(classID); | 154 ClassInfo* classInfo = find_class(classID); |
153 if (!classInfo) | 155 if (!classInfo) |
154 throw std::runtime_error(std::string("Property defined on unknown class: "
) + name); | 156 throw std::runtime_error(std::string("Property defined on unknown class: "
) + name); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 result += " Module._DestroyString(string);\n"; | 240 result += " Module._DestroyString(string);\n"; |
239 return result; | 241 return result; |
240 } | 242 } |
241 case TypeCategory::STRING_REF: | 243 case TypeCategory::STRING_REF: |
242 return " var result = readString(" + call_str + ");\n"; | 244 return " var result = readString(" + call_str + ");\n"; |
243 case TypeCategory::CLASS_PTR: | 245 case TypeCategory::CLASS_PTR: |
244 { | 246 { |
245 std::string result; | 247 std::string result; |
246 result += " var result = " + call_str + ";\n"; | 248 result += " var result = " + call_str + ";\n"; |
247 result += " if (result)\n"; | 249 result += " if (result)\n"; |
248 result += " {\n"; | |
249 | 250 |
250 const ClassInfo* cls = find_class(call.pointerType); | 251 const ClassInfo* cls = find_class(call.pointerType); |
251 if (!cls) | 252 if (!cls) |
252 throw std::runtime_error("Function " + call.name + " returns pointer t
o unknown class"); | 253 throw std::runtime_error("Function " + call.name + " returns pointer t
o unknown class"); |
253 | 254 |
254 auto offset = cls->subclass_differentiator.offset; | 255 auto offset = cls->subclass_differentiator.offset; |
255 if (offset == SIZE_MAX) | 256 if (offset == SIZE_MAX) |
256 result += " result = exports." + cls->name + "(result);\n"; | 257 result += " result = exports." + cls->name + "(result);\n"; |
257 else | 258 else |
258 result += " result = exports." + cls->name + ".fromPointer(result);
\n"; | 259 result += " result = exports." + cls->name + ".fromPointer(result);
\n"; |
259 | 260 |
260 result += " }\n"; | |
261 result += " else\n"; | 261 result += " else\n"; |
262 result += " result = null;\n"; | 262 result += " result = null;\n"; |
263 return result; | 263 return result; |
264 } | 264 } |
265 default: | 265 default: |
266 throw std::runtime_error("Unexpected return type for " + call.name); | 266 throw std::runtime_error("Unexpected return type for " + call.name); |
267 } | 267 } |
268 } | 268 } |
269 | 269 |
270 std::string wrapCall(const FunctionInfo& call, bool isFunction) | 270 std::string wrapCall(const FunctionInfo& call, bool isFunction, |
| 271 const FunctionInfo& instanceGetter) |
271 { | 272 { |
272 bool hasStringArgs = false; | 273 bool hasStringArgs = false; |
273 std::vector<std::string> params; | 274 std::vector<std::string> params; |
274 std::string prefix; | 275 std::string prefix; |
275 | 276 |
276 if (isFunction) | 277 if (isFunction) |
277 prefix += "function"; | 278 prefix += "function"; |
278 prefix += "("; | 279 prefix += "("; |
279 for (int i = 0; i < call.args.size(); i++) | 280 for (int i = 0; i < call.args.size(); i++) |
280 { | 281 { |
281 std::string argName("arg" + std::to_string(i)); | 282 std::string argName("arg" + std::to_string(i)); |
282 if (i > 0) | 283 if (i > 0) |
283 prefix += ", "; | 284 prefix += ", "; |
284 prefix += argName; | 285 prefix += argName; |
285 | 286 |
286 if (call.args[i] == TypeCategory::STRING_REF) | 287 if (call.args[i] == TypeCategory::STRING_REF) |
287 { | 288 { |
288 hasStringArgs = true; | 289 hasStringArgs = true; |
289 params.push_back(std::string("createString(") + argName + ")"); | 290 params.push_back(std::string("createString(") + argName + ")"); |
290 } | 291 } |
291 else if (call.args[i] == TypeCategory::CLASS_PTR) | 292 else if (call.args[i] == TypeCategory::CLASS_PTR) |
292 params.push_back(argName + "._pointer"); | 293 params.push_back(argName + " ? " + argName + "._pointer : 0"); |
293 else if (call.args[i] == TypeCategory::INT64) | 294 else if (call.args[i] == TypeCategory::INT64) |
294 { | 295 { |
295 // 64-bit integers are passed as two integer parameters | 296 // 64-bit integers are passed as two integer parameters |
296 params.push_back(argName + " >>> 0"); | 297 params.push_back(argName + " >>> 0"); |
297 params.push_back(argName + " / 0x100000000 >>> 0"); | 298 params.push_back(argName + " / 0x100000000 >>> 0"); |
298 } | 299 } |
299 else | 300 else |
300 params.push_back(argName); | 301 params.push_back(argName); |
301 } | 302 } |
302 prefix += ")\n{\n"; | 303 prefix += ")\n{\n"; |
303 | 304 |
304 std::string suffix = "}"; | 305 std::string suffix = "}"; |
305 if (call.returnType != TypeCategory::VOID) | 306 if (call.returnType != TypeCategory::VOID) |
306 suffix = " return result;\n" + suffix; | 307 suffix = " return result;\n" + suffix; |
307 | 308 |
308 if (call.returnType == TypeCategory::DEPENDENT_STRING || | 309 if (call.returnType == TypeCategory::DEPENDENT_STRING || |
309 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) | 310 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) |
310 { | 311 { |
311 prefix += " var sp = Runtime.stackSave();\n"; | 312 prefix += " var sp = Runtime.stackSave();\n"; |
312 suffix = " Runtime.stackRestore(sp);\n" + suffix; | 313 suffix = " Runtime.stackRestore(sp);\n" + suffix; |
313 } | 314 } |
314 | 315 |
315 if (call.instance_function) | 316 if (call.instance_function) |
316 params.insert(params.begin(), "this._pointer"); | 317 { |
| 318 if (instanceGetter.empty()) |
| 319 params.insert(params.begin(), "this._pointer"); |
| 320 else |
| 321 params.insert(params.begin(), instanceGetter.name + "()"); |
| 322 } |
317 | 323 |
318 return prefix + generateCall(call, params) + suffix; | 324 return prefix + generateCall(call, params) + suffix; |
319 } | 325 } |
320 | 326 |
321 void printHelpers() | 327 void printHelpers() |
322 { | 328 { |
323 printf("var sizeofString = %i;\n", sizeof(String)); | 329 printf("var sizeofString = %i;\n", sizeof(String)); |
324 | 330 |
325 puts(R"( | 331 puts(R"( |
326 function copyString(str, buffer) | 332 function copyString(str, buffer) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 Module._ReleaseRef(this._pointer + ref_counted_offset); | 379 Module._ReleaseRef(this._pointer + ref_counted_offset); |
374 }; | 380 }; |
375 return result; | 381 return result; |
376 } | 382 } |
377 )"); | 383 )"); |
378 } | 384 } |
379 | 385 |
380 void printClass(const ClassInfo& cls) | 386 void printClass(const ClassInfo& cls) |
381 { | 387 { |
382 // Begin class definition | 388 // Begin class definition |
383 | 389 bool singleton = !cls.instanceGetter.empty(); |
384 ClassInfo* baseClass = find_class(cls.baseClass); | 390 if (singleton) |
385 printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), | 391 printf("exports.%s = {\n", cls.name.c_str()); |
386 (baseClass ? ("exports." + baseClass->name).c_str() : "null"), | 392 else |
387 cls.ref_counted_offset); | 393 { |
| 394 ClassInfo* baseClass = find_class(cls.baseClass); |
| 395 printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), |
| 396 (baseClass ? ("exports." + baseClass->name).c_str() : "null"), |
| 397 cls.ref_counted_offset); |
| 398 } |
388 | 399 |
389 // Print prototype members | 400 // Print prototype members |
390 | |
391 for (const auto& property : cls.properties) | 401 for (const auto& property : cls.properties) |
392 { | 402 { |
393 if (property.jsValue.empty()) | 403 if (property.jsValue.empty()) |
394 { | 404 { |
395 printf("get %s%s,\n", property.name.c_str(), | 405 printf("get %s%s,\n", property.name.c_str(), |
396 wrapCall(property.getter, false).c_str()); | 406 wrapCall(property.getter, false, cls.instanceGetter).c_str()); |
397 if (!property.setter.empty()) | 407 if (!property.setter.empty()) |
398 { | 408 { |
399 printf("set %s%s,\n", property.name.c_str(), | 409 printf("set %s%s,\n", property.name.c_str(), |
400 wrapCall(property.setter, false).c_str()); | 410 wrapCall(property.setter, false, cls.instanceGetter).c_str()); |
401 } | 411 } |
402 } | 412 } |
403 else | 413 else |
404 printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str()); | 414 printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str()); |
405 } | 415 } |
406 | 416 |
407 for (const auto& method : cls.methods) | 417 for (const auto& method : cls.methods) |
| 418 { |
408 if (method.call.instance_function) | 419 if (method.call.instance_function) |
409 printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str()); | 420 { |
| 421 printf("%s: %s,\n", |
| 422 method.name.c_str(), |
| 423 wrapCall(method.call, true, cls.instanceGetter).c_str()); |
| 424 } |
| 425 } |
410 | 426 |
411 // End class definition | 427 // End class definition |
412 | 428 if (singleton) |
413 printf("});\n"); | 429 printf("};\n"); |
| 430 else |
| 431 printf("});\n"); |
414 | 432 |
415 // Print static members | 433 // Print static members |
416 | |
417 DifferentiatorInfo differentiator = cls.subclass_differentiator; | 434 DifferentiatorInfo differentiator = cls.subclass_differentiator; |
418 if (differentiator.offset != SIZE_MAX) | 435 if (differentiator.offset != SIZE_MAX) |
419 { | 436 { |
420 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); | 437 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); |
421 puts("{"); | 438 puts("{"); |
422 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset); | 439 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset); |
423 printf(" if (type in %s_mapping)\n", cls.name.c_str()); | 440 printf(" if (type in %s_mapping)\n", cls.name.c_str()); |
424 printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str()); | 441 printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str()); |
425 printf(" throw new Error('Unexpected %s type: ' + type);\n", cls.name.c_s
tr()); | 442 printf(" throw new Error('Unexpected %s type: ' + type);\n", cls.name.c_s
tr()); |
426 puts("};"); | 443 puts("};"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 | 476 |
460 void printBindings() | 477 void printBindings() |
461 { | 478 { |
462 bindings_internal::printHelpers(); | 479 bindings_internal::printHelpers(); |
463 | 480 |
464 for (const auto& cls : classes) | 481 for (const auto& cls : classes) |
465 bindings_internal::printClass(cls); | 482 bindings_internal::printClass(cls); |
466 for (const auto& cls : classes) | 483 for (const auto& cls : classes) |
467 bindings_internal::printClassMapping(cls); | 484 bindings_internal::printClassMapping(cls); |
468 } | 485 } |
OLD | NEW |