Jelajahi Sumber

[cs/java] throw nice-ish target-specific exceptions for bad dynamic field access

Dan Korostelev 8 tahun lalu
induk
melakukan
a64b125d39

+ 12 - 7
src/generators/gencommon/reflectionCFs.ml

@@ -129,6 +129,8 @@ type rcf_ctx =
 
 	rcf_hash_conflict_ctx : rcf_hash_conflict_ctx option;
 
+	rcf_mk_exception : string -> pos -> texpr;
+
 	(*
 		main expr -> field expr -> field string -> possible hash int (if optimize) -> possible set expr -> should_throw_exceptions -> changed expression
 
@@ -139,7 +141,7 @@ type rcf_ctx =
 	rcf_on_call_field : texpr->texpr->string->int32 option->texpr list->texpr;
 }
 
-let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx =
+let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx rcf_mk_exception =
 	{
 		rcf_gen = gen;
 		rcf_ft = ft;
@@ -162,6 +164,7 @@ let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field
 		rcf_on_getset_field = dynamic_getset_field;
 		rcf_on_call_field = dynamic_call_field;
 		rcf_hash_conflict_ctx = hash_conflict_ctx;
+		rcf_mk_exception = rcf_mk_exception;
 	}
 
 (*
@@ -249,9 +252,6 @@ let call_super ctx fn_args ret_t cf cl this_t pos =
 	}
 
 
-let mk_throw com str pos =
-	ExprBuilder.make_throw (ExprBuilder.make_string com str pos) pos
-
 let enumerate_dynamic_fields ctx cl when_found base_arr =
 	let gen = ctx.rcf_gen in
 	let basic = gen.gcon.basic in
@@ -835,6 +835,11 @@ let implement_final_lookup ctx cl =
 
 	let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in
 
+	let mk_throw str pos =
+		let e = ctx.rcf_mk_exception str pos in
+		ExprBuilder.make_throw e pos
+	in
+
 	(*
 		this function will create the class fields and call callback for each version
 
@@ -874,7 +879,7 @@ let implement_final_lookup ctx cl =
 				let throw_errors_local = mk_local (get throw_errors_opt) pos in
 				let mk_check_throw msg =
 				{
-					eexpr = TIf(throw_errors_local, mk_throw ctx.rcf_gen.gcon msg pos, Some (mk_return (null ret_t pos)));
+					eexpr = TIf(throw_errors_local, mk_throw msg pos, Some (mk_return (null ret_t pos)));
 					etype = ret_t;
 					epos = pos
 				} in
@@ -937,9 +942,9 @@ let implement_final_lookup ctx cl =
 					[]
 				| Some _ -> (* is set *)
 					if is_float then
-						[ mk_throw ctx.rcf_gen.gcon "Cannot access field for writing or incompatible type." pos ]
+						[ mk_throw "Cannot access field for writing or incompatible type." pos ]
 					else
-						[ mk_throw ctx.rcf_gen.gcon "Cannot access field for writing." pos ]
+						[ mk_throw "Cannot access field for writing." pos ]
 		)
 	end
 

+ 5 - 0
src/generators/gencs.ml

@@ -2822,6 +2822,10 @@ let generate con =
 
 		let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in
 
+		let cl_field_exc = get_cl (get_type gen (["System"],"MemberAccessException")) in
+		let cl_field_exc_t = TInst (cl_field_exc, []) in
+		let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in
+
 		let rcf_ctx =
 			ReflectionCFs.new_ctx
 				gen
@@ -2854,6 +2858,7 @@ let generate con =
 						add_names = (fun ehead earr -> mk (TCall (add, [ehead; earr])) basic.tvoid ehead.epos);
 					}
 				)
+				mk_field_exception
 		in
 
 		ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object;

+ 5 - 0
src/generators/genjava.ml

@@ -2186,6 +2186,10 @@ let generate con =
 		mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args); etype = t_dynamic }
 	in
 
+	let cl_field_exc = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in
+	let cl_field_exc_t = TInst (cl_field_exc, []) in
+	let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in
+
 	let rcf_ctx =
 		ReflectionCFs.new_ctx
 			gen
@@ -2207,6 +2211,7 @@ let generate con =
 				{ hash_array with eexpr = TCall(rcf_static_remove t, [hash_array; length; pos]); etype = gen.gcon.basic.tvoid }
 			)
 			None
+			mk_field_exception
 		in
 
 	ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object;