Browse Source

Fix "X is redefined from X" (#8571)

* don't reset macro statics immediately on ctx reuse

* avoid suppressing unrelated exceptions

* refactor away `reset_static_inits` field

* encapsulate static proto handling in a module

* make it a class
Aleksandr Kuzmenko 6 years ago
parent
commit
3a2371a8f2

+ 29 - 3
src/macro/eval/evalContext.ml

@@ -203,6 +203,33 @@ class eval_debug_context = object(self)
 
 end
 
+class static_prototypes = object(self)
+	val mutable prototypes : vprototype IntMap.t = IntMap.empty
+	val mutable inits : (bool ref * vprototype * (vprototype -> unit) list) IntMap.t = IntMap.empty
+
+	method add proto =
+		prototypes <- IntMap.add proto.ppath proto prototypes
+
+	method remove path =
+		prototypes <- IntMap.remove path prototypes
+
+	method set_needs_reset =
+		IntMap.iter (fun path (needs_reset, _, _) -> needs_reset := true) inits
+
+	method add_init proto delays =
+		inits <- IntMap.add proto.ppath (ref false, proto, delays) inits
+
+	method get path =
+		(try
+			let (needs_reset, proto, delays) = IntMap.find path inits in
+			if !needs_reset then begin
+				needs_reset := false;
+				List.iter (fun f -> f proto) delays
+			end
+		with Not_found -> ());
+		IntMap.find path prototypes
+end
+
 type exception_mode =
 	| CatchAll
 	| CatchUncaught
@@ -251,10 +278,9 @@ and context = {
 	mutable string_prototype : vprototype;
 	mutable vector_prototype : vprototype;
 	mutable instance_prototypes : vprototype IntMap.t;
-	mutable static_prototypes : vprototype IntMap.t;
+	mutable static_prototypes : static_prototypes;
 	mutable constructors : value Lazy.t IntMap.t;
 	get_object_prototype : 'a . context -> (int * 'a) list -> vprototype * (int * 'a) list;
-	mutable static_inits : (vprototype * (vprototype -> unit) list) IntMap.t;
 	(* eval *)
 	toplevel : value;
 	eval : eval;
@@ -440,7 +466,7 @@ let pop_environment ctx env =
 (* Prototypes *)
 
 let get_static_prototype_raise ctx path =
-	IntMap.find path ctx.static_prototypes
+	ctx.static_prototypes#get path
 
 let get_static_prototype ctx path p =
 	try get_static_prototype_raise ctx path

+ 1 - 1
src/macro/eval/evalDebugMisc.ml

@@ -164,7 +164,7 @@ let resolve_ident ctx env s =
 		end
 	with Not_found -> try
 		(* 4. Type *)
-		VPrototype (IntMap.find key ctx.static_prototypes)
+		VPrototype (get_static_prototype_raise ctx key)
 	with Not_found -> try
 		(* 5. Toplevel *)
 		EvalField.field_raise ctx.toplevel key

+ 2 - 3
src/macro/eval/evalMain.ml

@@ -120,11 +120,10 @@ let create com api is_macro =
 		string_prototype = fake_proto key_String;
 		array_prototype = fake_proto key_Array;
 		vector_prototype = fake_proto key_eval_Vector;
-		static_prototypes = IntMap.empty;
+		static_prototypes = new static_prototypes;
 		instance_prototypes = IntMap.empty;
 		constructors = IntMap.empty;
 		get_object_prototype = get_object_prototype;
-		static_inits = IntMap.empty;
 		(* eval *)
 		toplevel = 	vobject {
 			ofields = [||];
@@ -375,7 +374,7 @@ let setup get_api =
 
 let do_reuse ctx api =
 	ctx.curapi <- api;
-	IntMap.iter (fun _ (proto,delays) -> List.iter (fun f -> f proto) delays) ctx.static_inits
+	ctx.static_prototypes#set_needs_reset
 
 let set_error ctx b =
 	(* TODO: Have to reset this somewhere if running compilation server. But where... *)

+ 3 - 3
src/macro/eval/evalPrototype.ml

@@ -159,7 +159,7 @@ module PrototypeBuilder = struct
 		proto.pvalue <- vprototype proto;
 		(* Register the prototype. *)
 		if pctx.is_static then
-			ctx.static_prototypes <- IntMap.add pctx.key proto ctx.static_prototypes
+			ctx.static_prototypes#add proto
 		else begin
 			ctx.instance_prototypes <- IntMap.add pctx.key proto ctx.instance_prototypes;
 			if pctx.key = key_String then ctx.string_prototype <- proto
@@ -307,7 +307,7 @@ let add_types ctx types ready =
 			false
 		with Not_found ->
 			ctx.instance_prototypes <- IntMap.remove key ctx.instance_prototypes;
-			ctx.static_prototypes <- IntMap.remove key ctx.static_prototypes;
+			ctx.static_prototypes#remove key;
 			ctx.constructors <- IntMap.remove key ctx.constructors;
 			ready mt;
 			ctx.type_cache <- IntMap.add key mt ctx.type_cache;
@@ -355,7 +355,7 @@ let add_types ctx types ready =
 		| _ ->
 			DynArray.add fl_static_init (proto,delays);
 			let non_persistent_delays = ExtList.List.filter_map (fun (persistent,f) -> if not persistent then Some f else None) delays in
-			ctx.static_inits <- IntMap.add proto.ppath (proto,non_persistent_delays) ctx.static_inits;
+			ctx.static_prototypes#add_init proto non_persistent_delays;
 	) fl_static;
 	(* 4. Initialize static fields. *)
 	DynArray.iter (fun (proto,delays) -> List.iter (fun (_,f) -> f proto) delays) fl_static_init;