| Index: compiled/bindings/generator.cpp |
| =================================================================== |
| --- a/compiled/bindings/generator.cpp |
| +++ b/compiled/bindings/generator.cpp |
| @@ -123,30 +123,32 @@ namespace bindings_internal |
| { |
| for (auto& classInfo : classes) |
| if (classInfo.id == classID) |
| return &classInfo; |
| return nullptr; |
| } |
| void register_class(const char* name, TYPEID classID, TYPEID baseClassID, |
| - ptrdiff_t ref_counted_offset) |
| + ptrdiff_t ref_counted_offset, |
| + const FunctionInfo& instanceGetter) |
| { |
| if (find_class(classID)) |
| throw std::runtime_error(std::string("Duplicate definition for class ") + name); |
| if (baseClassID != TypeInfo<NoBaseClass>() && !find_class(baseClassID)) |
| throw std::runtime_error(std::string("Unknown base class defined for class ") + name); |
| ClassInfo classInfo; |
| classInfo.id = classID; |
| classInfo.baseClass = baseClassID; |
| classInfo.name = name; |
| classInfo.subclass_differentiator.offset = SIZE_MAX; |
| classInfo.ref_counted_offset = ref_counted_offset; |
| + classInfo.instanceGetter = instanceGetter; |
| classes.push_back(classInfo); |
| } |
| void register_property(TYPEID classID, const char* name, |
| const FunctionInfo& getter, const FunctionInfo& setter, |
| const char* jsValue) |
| { |
| ClassInfo* classInfo = find_class(classID); |
| @@ -240,39 +242,38 @@ namespace bindings_internal |
| } |
| case TypeCategory::STRING_REF: |
| return " var result = readString(" + call_str + ");\n"; |
| case TypeCategory::CLASS_PTR: |
| { |
| std::string result; |
| result += " var result = " + call_str + ";\n"; |
| result += " if (result)\n"; |
| - result += " {\n"; |
| const ClassInfo* cls = find_class(call.pointerType); |
| if (!cls) |
| throw std::runtime_error("Function " + call.name + " returns pointer to unknown class"); |
| auto offset = cls->subclass_differentiator.offset; |
| if (offset == SIZE_MAX) |
| result += " result = exports." + cls->name + "(result);\n"; |
| else |
| result += " result = exports." + cls->name + ".fromPointer(result);\n"; |
| - result += " }\n"; |
| result += " else\n"; |
| result += " result = null;\n"; |
| return result; |
| } |
| default: |
| throw std::runtime_error("Unexpected return type for " + call.name); |
| } |
| } |
| - std::string wrapCall(const FunctionInfo& call, bool isFunction) |
| + std::string wrapCall(const FunctionInfo& call, bool isFunction, |
| + const FunctionInfo& instanceGetter) |
| { |
| bool hasStringArgs = false; |
| std::vector<std::string> params; |
| std::string prefix; |
| if (isFunction) |
| prefix += "function"; |
| prefix += "("; |
| @@ -284,17 +285,17 @@ namespace bindings_internal |
| prefix += argName; |
| if (call.args[i] == TypeCategory::STRING_REF) |
| { |
| hasStringArgs = true; |
| params.push_back(std::string("createString(") + argName + ")"); |
| } |
| else if (call.args[i] == TypeCategory::CLASS_PTR) |
| - params.push_back(argName + "._pointer"); |
| + params.push_back(argName + " ? " + argName + "._pointer : 0"); |
| else if (call.args[i] == TypeCategory::INT64) |
| { |
| // 64-bit integers are passed as two integer parameters |
| params.push_back(argName + " >>> 0"); |
| params.push_back(argName + " / 0x100000000 >>> 0"); |
| } |
| else |
| params.push_back(argName); |
| @@ -308,17 +309,22 @@ namespace bindings_internal |
| if (call.returnType == TypeCategory::DEPENDENT_STRING || |
| call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) |
| { |
| prefix += " var sp = Runtime.stackSave();\n"; |
| suffix = " Runtime.stackRestore(sp);\n" + suffix; |
| } |
| if (call.instance_function) |
| - params.insert(params.begin(), "this._pointer"); |
| + { |
| + if (instanceGetter.empty()) |
| + params.insert(params.begin(), "this._pointer"); |
| + else |
| + params.insert(params.begin(), instanceGetter.name + "()"); |
| + } |
| return prefix + generateCall(call, params) + suffix; |
| } |
| void printHelpers() |
| { |
| printf("var sizeofString = %i;\n", sizeof(String)); |
| @@ -375,50 +381,61 @@ namespace bindings_internal |
| return result; |
| } |
| )"); |
| } |
| void printClass(const ClassInfo& cls) |
| { |
| // Begin class definition |
| - |
| - ClassInfo* baseClass = find_class(cls.baseClass); |
| - printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), |
| - (baseClass ? ("exports." + baseClass->name).c_str() : "null"), |
| - cls.ref_counted_offset); |
| + bool singleton = !cls.instanceGetter.empty(); |
| + if (singleton) |
| + printf("exports.%s = {\n", cls.name.c_str()); |
| + else |
| + { |
| + ClassInfo* baseClass = find_class(cls.baseClass); |
| + printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), |
| + (baseClass ? ("exports." + baseClass->name).c_str() : "null"), |
| + cls.ref_counted_offset); |
| + } |
| // Print prototype members |
| - |
| for (const auto& property : cls.properties) |
| { |
| if (property.jsValue.empty()) |
| { |
| printf("get %s%s,\n", property.name.c_str(), |
| - wrapCall(property.getter, false).c_str()); |
| + wrapCall(property.getter, false, cls.instanceGetter).c_str()); |
| if (!property.setter.empty()) |
| { |
| printf("set %s%s,\n", property.name.c_str(), |
| - wrapCall(property.setter, false).c_str()); |
| + wrapCall(property.setter, false, cls.instanceGetter).c_str()); |
| } |
| } |
| else |
| printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str()); |
| } |
| for (const auto& method : cls.methods) |
| + { |
| if (method.call.instance_function) |
| - printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str()); |
| + { |
| + printf("%s: %s,\n", |
| + method.name.c_str(), |
| + wrapCall(method.call, true, cls.instanceGetter).c_str()); |
| + } |
| + } |
| // End class definition |
| - |
| - printf("});\n"); |
| + if (singleton) |
| + printf("};\n"); |
| + else |
| + printf("});\n"); |
| // Print static members |
| - |
| DifferentiatorInfo differentiator = cls.subclass_differentiator; |
| if (differentiator.offset != SIZE_MAX) |
| { |
| printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); |
| puts("{"); |
| printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset); |
| printf(" if (type in %s_mapping)\n", cls.name.c_str()); |
| printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str()); |