| 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 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 |