From 6fd82c1b987893a8c6ffd7979743196ab60e20fc Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 7 Jan 2022 06:27:54 +0000 Subject: [PATCH] Make struct pointer loading language-specific and reliable for TS --- gen_type_mapping.py | 20 ++++++++++---------- java_strings.py | 5 +++++ typescript_strings.py | 16 +++++++++++++++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/gen_type_mapping.py b/gen_type_mapping.py index c291b82d..f4d6b380 100644 --- a/gen_type_mapping.py +++ b/gen_type_mapping.py @@ -257,7 +257,7 @@ class TypeMappingGenerator: ty_info.var_name = "ret" if ty_info.rust_obj in self.opaque_structs: - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", self.consts.add_ref("this", ty_info.var_name)) + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name) + " & ~1", self.consts.add_ref("this", ty_info.var_name)) opaque_arg_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv;\n" opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.inner = (void*)(" + ty_info.var_name + " & (~1));\n" if ty_info.is_ptr and holds_ref: @@ -287,7 +287,7 @@ class TypeMappingGenerator: "// at the FFI layer, creating a new object which Rust can claim ownership of\n" + "// However, in some cases (eg here), there is no way to clone an object, and thus\n" + "// we actually have to pass full ownership to Rust.\n" + - "// Thus, after this call, " + ty_info.var_name + " is reset to null and is now a dummy object.\n" + ty_info.var_name + ".ptr = 0") + "// Thus, after this call, " + ty_info.var_name + " is reset to null and is now a dummy object.\n" + self.consts.set_null_skip_free(ty_info.var_name)) opaque_ret_conv_suf = ";\n" opaque_ret_conv_suf += "uint64_t " + ty_info.var_name + "_ref = 0;\n" @@ -375,7 +375,7 @@ class TypeMappingGenerator: else: base_conv = base_conv + "\n" + "FREE((void*)" + ty_info.var_name + ");" if from_hu_conv is None: - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "") + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name), "") from_hu_conv = (from_hu_conv[0], self.consts.add_ref("this", ty_info.var_name)) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, @@ -424,7 +424,7 @@ class TypeMappingGenerator: ret_conv = (ret_conv[0] + "*" + ty_info.var_name + "_copy = ", "") ret_conv = (ret_conv[0], ";\nuint64_t " + ty_info.var_name + "_ref = (uint64_t)" + ty_info.var_name + "_copy;") if from_hu_conv is None: - from_hu_conv = (ty_info.var_name + ".ptr", "") + from_hu_conv = (self.consts.get_ptr(ty_info.var_name), "") from_hu_conv = (from_hu_conv[0], to_hu_conv_sfx) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, @@ -440,7 +440,7 @@ class TypeMappingGenerator: else: ret_conv = (ty_info.rust_obj + "* " + ty_info.var_name + "_conv = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*" + ty_info.var_name + "_conv = ", ";") if from_hu_conv is None: - from_hu_conv = (ty_info.var_name + " != null ? " + ty_info.var_name + ".ptr : 0", "") + from_hu_conv = (ty_info.var_name + " != null ? " + self.consts.get_ptr(ty_info.var_name) + " : 0", "") return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, ret_conv = ret_conv, ret_conv_name = "(uint64_t)" + ty_info.var_name + "_conv", @@ -464,7 +464,7 @@ class TypeMappingGenerator: else: to_hu_conv_sfx = "" if from_hu_conv is None: - from_hu_conv = (ty_info.var_name + " != null ? " + ty_info.var_name + ".ptr : 0", "") + from_hu_conv = (ty_info.var_name + " != null ? " + self.consts.get_ptr(ty_info.var_name) + " : 0", "") return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, ret_conv = ret_conv, ret_conv_name = ret_conv_name, @@ -489,7 +489,7 @@ class TypeMappingGenerator: arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, ret_conv = ret_conv, ret_conv_name = "(uint64_t)" + ty_info.var_name + "_ref", to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, ty_info.var_name + "_conv", "new " +ty_info.java_hu_ty + "(null, " + ty_info.var_name + ")") + ";", - to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (ty_info.var_name + ".ptr", "")) + to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (self.consts.get_ptr(ty_info.var_name), "")) elif ty_info.is_ptr: assert(not is_free) if ty_info.rust_obj in self.complex_enums: @@ -506,7 +506,7 @@ class TypeMappingGenerator: ret_conv = ret_conv, ret_conv_name = "(uint64_t)ret_" + ty_info.var_name, to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, ty_info.var_name + "_hu_conv", ty_info.java_hu_ty + ".constr_from_ptr(" + ty_info.var_name + ")") + ";", to_hu_conv_name = ty_info.var_name + "_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr & ~1", from_hu_sfx)) + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name) + " & ~1", from_hu_sfx)) elif ty_info.rust_obj in self.trait_structs: if ty_info.nonnull_ptr: arg_conv = "void* " + ty_info.var_name + "_ptr = (void*)(((uint64_t)" + ty_info.var_name + ") & ~1);\n" @@ -535,7 +535,7 @@ class TypeMappingGenerator: ret_conv_name = "(uint64_t)" + ty_info.var_name + "_clone", to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, "ret_hu_conv", "new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ")") + ";\n" + self.consts.add_ref("ret_hu_conv", "this") + ";", to_hu_conv_name = "ret_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "")) + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name), "")) else: return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = arg_conv, arg_conv_name = arg_conv_name, arg_conv_cleanup = None, @@ -543,7 +543,7 @@ class TypeMappingGenerator: ret_conv_name = "ret_" + ty_info.var_name, to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, "ret_hu_conv", "new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ")") + ";\n" + self.consts.add_ref("ret_hu_conv", "this") + ";", to_hu_conv_name = "ret_hu_conv", - from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", self.consts.add_ref("this", ty_info.var_name))) + from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name), self.consts.add_ref("this", ty_info.var_name))) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)(" + ty_info.var_name + " & ~1);", arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, diff --git a/java_strings.py b/java_strings.py index 5a416a95..ada526fc 100644 --- a/java_strings.py +++ b/java_strings.py @@ -620,6 +620,11 @@ import javax.annotation.Nullable; def var_decl_statement(self, ty_string, var_name, statement): return ty_string + " " + var_name + " = " + statement + def get_ptr(self, var): + return var + ".ptr" + def set_null_skip_free(self, var): + return var + ".ptr" + " = 0;" + def add_ref(self, holder, referent): return holder + ".ptrs_to.add(" + referent + ")" diff --git a/typescript_strings.py b/typescript_strings.py index 45ae6d1d..3ad59af5 100644 --- a/typescript_strings.py +++ b/typescript_strings.py @@ -97,10 +97,19 @@ export default class CommonBase { finalizer.register(this, get_freeer(ptr, free_fn)); } } + // In Java, protected means "any subclass can access fields on any other subclass'" + // In TypeScript, protected means "any subclass can access parent fields on instances of itself" + // To work around this, we add accessors for other instances' protected fields here. protected static add_ref_from(holder: CommonBase, referent: object) { holder.ptrs_to.push(referent); } - public _test_only_get_ptr(): number { return this.ptr; } + protected static get_ptr_of(o: CommonBase) { + return o.ptr; + } + protected static set_null_skip_free(o: CommonBase) { + o.ptr = 0; + finalizer.unregister(o); + } } """ @@ -526,6 +535,11 @@ const decodeString = (stringPointer, free = true) => { def var_decl_statement(self, ty_string, var_name, statement): return "const " + var_name + ": " + ty_string + " = " + statement + def get_ptr(self, var): + return "CommonBase.get_ptr_of(" + var + ")" + def set_null_skip_free(self, var): + return "CommonBase.set_null_skip_free(" + var + ");" + def add_ref(self, holder, referent): return "CommonBase.add_ref_from(" + holder + ", " + referent + ")" -- 2.30.2