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