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()); |