Browse Source

[eval] try different approach to fix eval static init persistence

see #8640
Simon Krajewski 6 years ago
parent
commit
ddca25fdd2

+ 12 - 10
src/macro/eval/evalContext.ml

@@ -205,7 +205,8 @@ end
 
 
 class static_prototypes = object(self)
 class static_prototypes = object(self)
 	val mutable prototypes : vprototype IntMap.t = IntMap.empty
 	val mutable prototypes : vprototype IntMap.t = IntMap.empty
-	val mutable inits : (bool ref * vprototype * (vprototype -> unit) list) IntMap.t = IntMap.empty
+	val mutable inits : (vprototype * (vprototype -> unit) list) IntMap.t = IntMap.empty
+	val mutable needs_reset = true
 
 
 	method add proto =
 	method add proto =
 		prototypes <- IntMap.add proto.ppath proto prototypes
 		prototypes <- IntMap.add proto.ppath proto prototypes
@@ -215,20 +216,21 @@ class static_prototypes = object(self)
 		prototypes <- IntMap.remove path prototypes
 		prototypes <- IntMap.remove path prototypes
 
 
 	method set_needs_reset =
 	method set_needs_reset =
-		IntMap.iter (fun path (needs_reset, _, _) -> needs_reset := true) inits
+		needs_reset <- true
 
 
 	method add_init proto delays =
 	method add_init proto delays =
-		inits <- IntMap.add proto.ppath (ref false, proto, delays) inits
+		inits <- IntMap.add proto.ppath (proto, delays) inits
 
 
 	method get path =
 	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
 		IntMap.find path prototypes
+
+	method init_all =
+		if needs_reset then begin
+			needs_reset <- false;
+			IntMap.iter (fun _ (proto,delays) ->
+				List.iter (fun f -> f proto) delays;
+			) inits;
+		end
 end
 end
 
 
 type exception_mode =
 type exception_mode =

+ 8 - 1
src/macro/eval/evalMain.ml

@@ -163,6 +163,7 @@ let call_path ctx path f vl api =
 			let vtype = get_static_prototype_as_value ctx (path_hash path) api.pos in
 			let vtype = get_static_prototype_as_value ctx (path_hash path) api.pos in
 			let vfield = field vtype (hash f) in
 			let vfield = field vtype (hash f) in
 			let p = api.pos in
 			let p = api.pos in
+			ctx.static_prototypes#init_all;
 			let info = create_env_info true p.pfile EKEntrypoint (Hashtbl.create 0) in
 			let info = create_env_info true p.pfile EKEntrypoint (Hashtbl.create 0) in
 			let env = push_environment ctx info 0 0 in
 			let env = push_environment ctx info 0 0 in
 			env.env_leave_pmin <- p.pmin;
 			env.env_leave_pmin <- p.pmin;
@@ -450,7 +451,13 @@ let value_string = value_string
 
 
 let exc_string = exc_string
 let exc_string = exc_string
 
 
-let eval_expr ctx e = if ctx.had_error then None else eval_expr ctx EKEntrypoint e
+let eval_expr ctx e =
+	if ctx.had_error then
+		None
+	else begin
+		ctx.static_prototypes#init_all;
+		eval_expr ctx EKEntrypoint e
+	end
 
 
 let handle_decoding_error f v t =
 let handle_decoding_error f v t =
 	let line = ref 1 in
 	let line = ref 1 in

+ 11 - 0
tests/server/src/Main.hx

@@ -192,6 +192,17 @@ class ServerTests extends HaxeServerTestCase {
 		}
 		}
 		utest.Assert.equals("function() {_Vector.Vector_Impl_.toIntVector(null);}", moreHack(type.args.statics[0].expr.testHack)); // lmao
 		utest.Assert.equals("function() {_Vector.Vector_Impl_.toIntVector(null);}", moreHack(type.args.statics[0].expr.testHack)); // lmao
 	}
 	}
+
+	function testMacroStaticsReset() {
+		vfs.putContent("Main.hx", getTemplate("issues/Issue8631/Main.hx"));
+		vfs.putContent("Init.hx", getTemplate("issues/Issue8631/Init.hx"));
+		vfs.putContent("Macro.hx", getTemplate("issues/Issue8631/Macro.hx"));
+		var hxml = ["-main", "Main", "--macro", "Init.callMacro()", "--interp"];
+		runHaxe(hxml);
+		runHaxe(hxml);
+		var counter = vfs.getContent("counter.txt");
+		utest.Assert.equals('2', counter);
+	}
 }
 }
 
 
 class Main {
 class Main {

+ 6 - 0
tests/server/src/Vfs.hx

@@ -39,6 +39,12 @@ class Vfs {
 		Fs.writeFileSync(path.toString(), content);
 		Fs.writeFileSync(path.toString(), content);
 	}
 	}
 
 
+	public function getContent(path:String) {
+		var path = getPhysicalPath(path);
+		FileSystem.createDirectory(path.dir);
+		return Fs.readFileSync(path.toString());
+	}
+
 	public function close() {
 	public function close() {
 		removeDir(physicalPath);
 		removeDir(physicalPath);
 	}
 	}

+ 5 - 0
tests/server/test/templates/issues/Issue8631/Init.hx

@@ -0,0 +1,5 @@
+class Init {
+	static public function callMacro() {
+		Macro.call();
+	}
+}

+ 15 - 0
tests/server/test/templates/issues/Issue8631/Macro.hx

@@ -0,0 +1,15 @@
+using sys.FileSystem;
+using sys.io.File;
+
+
+class Macro {
+	static var called:Bool = false;
+	static inline var FILE = 'counter.txt';
+
+	static public function call() {
+		if(called) return;
+		called = true;
+		var cnt = FILE.exists() ? Std.parseInt(FILE.getContent()) + 1 : 1;
+		FILE.saveContent('$cnt');
+	}
+}

+ 3 - 0
tests/server/test/templates/issues/Issue8631/Main.hx

@@ -0,0 +1,3 @@
+class Main {
+	static function main() {}
+}