浏览代码

[as3] generate complex static inits at the bottom of each type (closes #3563)

Simon Krajewski 10 年之前
父节点
当前提交
12bfb1655b
共有 4 个文件被更改,包括 46 次插入6 次删除
  1. 1 0
      extra/CHANGES.txt
  2. 22 6
      genas3.ml
  3. 0 0
      tests/unit/src/unit/issues/Issue2061.hx
  4. 23 0
      tests/unit/src/unit/issues/Issue3563.hx

+ 1 - 0
extra/CHANGES.txt

@@ -16,6 +16,7 @@
 	php : fixed argument passing to closures (#2587)
 	php : fixed argument passing to closures (#2587)
 	neko/cpp : fixed various sys.Filesystem issues with Windows drive paths (#3266)
 	neko/cpp : fixed various sys.Filesystem issues with Windows drive paths (#3266)
 	as3 : fixed problem with covariant return types (#4222)
 	as3 : fixed problem with covariant return types (#4222)
+	as3 : fixed rare problem with static initialization order (#3563)
 
 
 	General improvements and optimizations:
 	General improvements and optimizations:
 
 

+ 22 - 6
genas3.ml

@@ -1046,8 +1046,11 @@ let generate_field ctx static f =
 		let gen_init () = match f.cf_expr with
 		let gen_init () = match f.cf_expr with
 			| None -> ()
 			| None -> ()
 			| Some e ->
 			| Some e ->
-				print ctx " = ";
-				gen_value ctx e
+				if not static || (match e.eexpr with | TConst _ | TFunction _ | TTypeExpr _ -> true | _ -> false) then begin
+					print ctx " = ";
+					gen_value ctx e
+				end else
+					Codegen.ExtClass.add_static_init ctx.curclass f e e.epos
 		in
 		in
 		if is_getset then begin
 		if is_getset then begin
 			let t = type_str ctx f.cf_type p in
 			let t = type_str ctx f.cf_type p in
@@ -1122,12 +1125,26 @@ let generate_class ctx c =
 	);
 	);
 	List.iter (generate_field ctx false) c.cl_ordered_fields;
 	List.iter (generate_field ctx false) c.cl_ordered_fields;
 	List.iter (generate_field ctx true) c.cl_ordered_statics;
 	List.iter (generate_field ctx true) c.cl_ordered_statics;
+	let has_init = match c.cl_init with
+		| None -> false
+		| Some e ->
+			newline ctx;
+			spr ctx "static static_init function init() : void";
+			gen_expr ctx (mk_block e);
+			true;
+	in
 	cl();
 	cl();
 	newline ctx;
 	newline ctx;
 	print ctx "}";
 	print ctx "}";
 	pack();
 	pack();
 	newline ctx;
 	newline ctx;
 	print ctx "}";
 	print ctx "}";
+	if has_init then begin
+		newline ctx;
+		spr ctx "namespace static_init";
+		newline ctx;
+		print ctx "%s.static_init::init()" (s_path ctx true ctx.curclass.cl_path Ast.null_pos);
+	end;
 	newline ctx;
 	newline ctx;
 	if c.cl_interface && Ast.Meta.has (Ast.Meta.Custom ":hasMetadata") c.cl_meta then begin
 	if c.cl_interface && Ast.Meta.has (Ast.Meta.Custom ":hasMetadata") c.cl_meta then begin
 		(* we have to reference the metadata class in order for it to be compiled *)
 		(* we have to reference the metadata class in order for it to be compiled *)
@@ -1242,11 +1259,10 @@ let generate com =
 				| ["flash"],"FlashXml__" -> { c with cl_path = [],"Xml" }
 				| ["flash"],"FlashXml__" -> { c with cl_path = [],"Xml" }
 				| (pack,name) -> { c with cl_path = (pack,protect name) }
 				| (pack,name) -> { c with cl_path = (pack,protect name) }
 			) in
 			) in
-			(match c.cl_init with
-			| None -> ()
-			| Some e -> inits := e :: !inits);
 			if c.cl_extern then
 			if c.cl_extern then
-				()
+				(match c.cl_init with
+				| None -> ()
+				| Some e -> inits := e :: !inits)
 			else
 			else
 				let ctx = init infos c.cl_path in
 				let ctx = init infos c.cl_path in
 				generate_class ctx c;
 				generate_class ctx c;

+ 0 - 0
tests/unit/src/unit/issues/Issue2061.hx.disabled → tests/unit/src/unit/issues/Issue2061.hx


+ 23 - 0
tests/unit/src/unit/issues/Issue3563.hx

@@ -0,0 +1,23 @@
+package unit.issues;
+
+private class FinalTest {
+	public static var hello = "Hello";
+	public static var someValue = getSomeValue();
+	public static var someValue2 = getSomeValue2();
+
+	static public function getSomeValue() {
+		return hello;
+	}
+
+    static public function getSomeValue2() {
+        return someValue;
+    }
+}
+
+class Issue3563 extends Test {
+	function test() {
+		eq("Hello", FinalTest.someValue);
+		eq("Hello", FinalTest.getSomeValue());
+		eq("Hello", FinalTest.getSomeValue2());
+	}
+}