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 |