Преглед на файлове

[js] use abstract's own type path for generating its impl class (closes #9003) (#9006)

Dan Korostelev преди 5 години
родител
ревизия
6b7934b5be
променени са 1 файла, в които са добавени 51 реда и са изтрити 34 реда
  1. 51 34
      src/generators/genjs.ml

+ 51 - 34
src/generators/genjs.ml

@@ -1019,20 +1019,20 @@ let path_to_brackets path =
 	let parts = ExtString.String.nsplit path "." in
 	let parts = ExtString.String.nsplit path "." in
 	"[\"" ^ (String.concat "\"][\"" parts) ^ "\"]"
 	"[\"" ^ (String.concat "\"][\"" parts) ^ "\"]"
 
 
-let gen_class_static_field ctx c f =
+let gen_class_static_field ctx c cl_path f =
 	match f.cf_expr with
 	match f.cf_expr with
 	| None | Some { eexpr = TConst TNull } when not (has_feature ctx "Type.getClassFields") ->
 	| None | Some { eexpr = TConst TNull } when not (has_feature ctx "Type.getClassFields") ->
 		()
 		()
 	| None when not (is_physical_field f) ->
 	| None when not (is_physical_field f) ->
 		()
 		()
 	| None ->
 	| None ->
-		print ctx "%s%s = null" (s_path ctx c.cl_path) (static_field ctx c f.cf_name);
+		print ctx "%s%s = null" (s_path ctx cl_path) (static_field ctx c f.cf_name);
 		newline ctx
 		newline ctx
 	| Some e ->
 	| Some e ->
 		match e.eexpr with
 		match e.eexpr with
 		| TFunction _ ->
 		| TFunction _ ->
-			let path = (s_path ctx c.cl_path) ^ (static_field ctx c f.cf_name) in
-			let dot_path = (dot_path c.cl_path) ^ (static_field ctx c f.cf_name) in
+			let path = (s_path ctx cl_path) ^ (static_field ctx c f.cf_name) in
+			let dot_path = (dot_path cl_path) ^ (static_field ctx c f.cf_name) in
 			ctx.id_counter <- 0;
 			ctx.id_counter <- 0;
 			print ctx "%s = " path;
 			print ctx "%s = " path;
 			(match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
 			(match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
@@ -1061,14 +1061,14 @@ let gen_class_field ctx c f =
 		gen_value ctx e;
 		gen_value ctx e;
 		ctx.separator <- false
 		ctx.separator <- false
 
 
-let generate_class___name__ ctx c =
+let generate_class___name__ ctx cl_path =
 	if has_feature ctx "js.Boot.isClass" then begin
 	if has_feature ctx "js.Boot.isClass" then begin
-		let p = s_path ctx c.cl_path in
+		let p = s_path ctx cl_path in
 		print ctx "%s.__name__ = " p;
 		print ctx "%s.__name__ = " p;
-		(match has_feature ctx "Type.getClassName", c.cl_path with
+		(match has_feature ctx "Type.getClassName", cl_path with
 			| true, _
 			| true, _
 			| _, ([], ("Array" | "String")) ->
 			| _, ([], ("Array" | "String")) ->
-				print ctx "\"%s\"" (dot_path c.cl_path)
+				print ctx "\"%s\"" (dot_path cl_path)
 			| _ ->
 			| _ ->
 				print ctx "true"
 				print ctx "true"
 		);
 		);
@@ -1082,17 +1082,26 @@ let generate_class___isInterface__ ctx c =
 		newline ctx;
 		newline ctx;
 	end
 	end
 
 
+let get_generated_class_path = function
+	(* we want to generate abstract implementations with the path of the abstract itself, unless there is @:native involved *)
+	| { cl_kind = KAbstractImpl a; cl_meta = m } when not (Meta.has Meta.Native m) ->
+		a.a_path
+	| { cl_path = p } ->
+		p
+
 let generate_class_es3 ctx c =
 let generate_class_es3 ctx c =
-	let p = s_path ctx c.cl_path in
+	let cl_path = get_generated_class_path c in
+
+	let p = s_path ctx cl_path in
 	if ctx.js_flatten then
 	if ctx.js_flatten then
 		print ctx "var "
 		print ctx "var "
 	else
 	else
-		generate_package_create ctx c.cl_path;
+		generate_package_create ctx cl_path;
 	if ctx.js_modern || not ctx.has_resolveClass then
 	if ctx.js_modern || not ctx.has_resolveClass then
 		print ctx "%s = " p
 		print ctx "%s = " p
 	else
 	else
-		print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path c.cl_path);
-	(match (get_exposed ctx (dot_path c.cl_path) c.cl_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
+		print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path cl_path);
+	(match (get_exposed ctx (dot_path cl_path) c.cl_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
 	(match c.cl_kind with
 	(match c.cl_kind with
 		| KAbstractImpl _ ->
 		| KAbstractImpl _ ->
 			(* abstract implementations only contain static members and don't need to have constructor functions *)
 			(* abstract implementations only contain static members and don't need to have constructor functions *)
@@ -1104,10 +1113,10 @@ let generate_class_es3 ctx c =
 	);
 	);
 	newline ctx;
 	newline ctx;
 	if ctx.js_modern && ctx.has_resolveClass then begin
 	if ctx.js_modern && ctx.has_resolveClass then begin
-		print ctx "$hxClasses[\"%s\"] = %s" (dot_path c.cl_path) p;
+		print ctx "$hxClasses[\"%s\"] = %s" (dot_path cl_path) p;
 		newline ctx;
 		newline ctx;
 	end;
 	end;
-	generate_class___name__ ctx c;
+	generate_class___name__ ctx cl_path;
 	generate_class___isInterface__ ctx c;
 	generate_class___isInterface__ ctx c;
 
 
 	if ctx.has_interface_check then
 	if ctx.has_interface_check then
@@ -1132,7 +1141,7 @@ let generate_class_es3 ctx c =
 			newline ctx);
 			newline ctx);
 	end;
 	end;
 
 
-	List.iter (gen_class_static_field ctx c) c.cl_ordered_statics;
+	List.iter (gen_class_static_field ctx c cl_path) c.cl_ordered_statics;
 
 
 	let has_class = has_feature ctx "js.Boot.getClass" && (c.cl_super <> None || c.cl_ordered_fields <> [] || c.cl_constructor <> None) in
 	let has_class = has_feature ctx "js.Boot.getClass" && (c.cl_super <> None || c.cl_ordered_fields <> [] || c.cl_constructor <> None) in
 	let has_prototype = c.cl_super <> None || has_class || List.exists (can_gen_class_field ctx) c.cl_ordered_fields in
 	let has_prototype = c.cl_super <> None || has_class || List.exists (can_gen_class_field ctx) c.cl_ordered_fields in
@@ -1174,13 +1183,14 @@ let generate_class_es3 ctx c =
 	flush ctx
 	flush ctx
 
 
 let generate_class_es6 ctx c =
 let generate_class_es6 ctx c =
-	let p = s_path ctx c.cl_path in
+	let cl_path = get_generated_class_path c in
+	let p = s_path ctx cl_path in
 
 
 	let cls_name =
 	let cls_name =
-		if not ctx.js_flatten && (fst c.cl_path) <> [] then begin
-			generate_package_create ctx c.cl_path;
+		if not ctx.js_flatten && (fst cl_path) <> [] then begin
+			generate_package_create ctx cl_path;
 			print ctx "%s = " p;
 			print ctx "%s = " p;
-			Path.flat_path c.cl_path
+			Path.flat_path cl_path
 		end else
 		end else
 			p
 			p
 	in
 	in
@@ -1229,7 +1239,7 @@ let generate_class_es6 ctx c =
 				gen_function ~keyword:("static " ^ (method_def_name cf)) ctx f pos;
 				gen_function ~keyword:("static " ^ (method_def_name cf)) ctx f pos;
 				ctx.separator <- false;
 				ctx.separator <- false;
 
 
-				(match get_exposed ctx ((dot_path c.cl_path) ^ (static_field ctx c cf.cf_name)) cf.cf_meta with
+				(match get_exposed ctx ((dot_path cl_path) ^ (static_field ctx c cf.cf_name)) cf.cf_meta with
 				| [s] -> exposed_static_methods := (s,cf.cf_name) :: !exposed_static_methods;
 				| [s] -> exposed_static_methods := (s,cf.cf_name) :: !exposed_static_methods;
 				| _ -> ());
 				| _ -> ());
 
 
@@ -1248,12 +1258,12 @@ let generate_class_es6 ctx c =
 		newline ctx
 		newline ctx
 	) !exposed_static_methods;
 	) !exposed_static_methods;
 
 
-	List.iter (gen_class_static_field ctx c) nonmethod_statics;
+	List.iter (gen_class_static_field ctx c cl_path) nonmethod_statics;
 
 
-	let expose = (match get_exposed ctx (dot_path c.cl_path) c.cl_meta with [s] -> "$hx_exports" ^ (path_to_brackets s) | _ -> "") in
+	let expose = (match get_exposed ctx (dot_path cl_path) c.cl_meta with [s] -> "$hx_exports" ^ (path_to_brackets s) | _ -> "") in
 	if expose <> "" || ctx.has_resolveClass then begin
 	if expose <> "" || ctx.has_resolveClass then begin
 		if ctx.has_resolveClass then begin
 		if ctx.has_resolveClass then begin
-			print ctx "$hxClasses[\"%s\"] = " (dot_path c.cl_path)
+			print ctx "$hxClasses[\"%s\"] = " (dot_path cl_path)
 		end;
 		end;
 		if expose <> "" then begin
 		if expose <> "" then begin
 			print ctx "%s = " expose
 			print ctx "%s = " expose
@@ -1262,7 +1272,7 @@ let generate_class_es6 ctx c =
 		newline ctx;
 		newline ctx;
 	end;
 	end;
 
 
-	generate_class___name__ ctx c;
+	generate_class___name__ ctx cl_path;
 	generate_class___isInterface__ ctx c;
 	generate_class___isInterface__ ctx c;
 
 
 	if ctx.has_interface_check then
 	if ctx.has_interface_check then
@@ -1443,9 +1453,10 @@ let generate_enum ctx e =
 	flush ctx
 	flush ctx
 
 
 let generate_static ctx (c,f,e) =
 let generate_static ctx (c,f,e) =
-	let dot_path = (dot_path c.cl_path) ^ (static_field ctx c f.cf_name) in
+	let cl_path = get_generated_class_path c in
+	let dot_path = (dot_path cl_path) ^ (static_field ctx c f.cf_name) in
 	(match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
 	(match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ());
-	print ctx "%s%s = " (s_path ctx c.cl_path) (static_field ctx c f.cf_name);
+	print ctx "%s%s = " (s_path ctx cl_path) (static_field ctx c f.cf_name);
 	gen_value ctx e;
 	gen_value ctx e;
 	newline ctx
 	newline ctx
 
 
@@ -1481,7 +1492,7 @@ let generate_type ctx = function
 			ctx.inits <- e :: ctx.inits);
 			ctx.inits <- e :: ctx.inits);
 		(* Special case, want to add Math.__name__ only when required, handle here since Math is extern *)
 		(* Special case, want to add Math.__name__ only when required, handle here since Math is extern *)
 		let p = s_path ctx c.cl_path in
 		let p = s_path ctx c.cl_path in
-		if p = "Math" then generate_class___name__ ctx c;
+		if p = "Math" then generate_class___name__ ctx c.cl_path;
 		(* Another special case for Std because we do not want to generate it if it's empty. *)
 		(* Another special case for Std because we do not want to generate it if it's empty. *)
 		if p = "Std" && c.cl_ordered_statics = [] then
 		if p = "Std" && c.cl_ordered_statics = [] then
 			()
 			()
@@ -1489,7 +1500,7 @@ let generate_type ctx = function
 			if (not c.cl_interface) || (need_to_generate_interface ctx c) then
 			if (not c.cl_interface) || (need_to_generate_interface ctx c) then
 				generate_class ctx c
 				generate_class ctx c
 		end else if Meta.has Meta.JsRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
 		end else if Meta.has Meta.JsRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
-			generate_require ctx c.cl_path c.cl_meta
+			generate_require ctx (get_generated_class_path c) c.cl_meta
 		else if not ctx.js_flatten && Meta.has Meta.InitPackage c.cl_meta then
 		else if not ctx.js_flatten && Meta.has Meta.InitPackage c.cl_meta then
 			(match c.cl_path with
 			(match c.cl_path with
 			| ([],_) -> ()
 			| ([],_) -> ()
@@ -1541,14 +1552,20 @@ let alloc_ctx com es_version =
 		separator = false;
 		separator = false;
 		found_expose = false;
 		found_expose = false;
 	} in
 	} in
+
 	ctx.type_accessor <- (fun t ->
 	ctx.type_accessor <- (fun t ->
-		let p = t_path t in
 		match t with
 		match t with
-		| TClassDecl ({ cl_extern = true } as c) when not (Meta.has Meta.JsRequire c.cl_meta)
-			-> dot_path p
-		| TEnumDecl ({ e_extern = true } as e) when not (Meta.has Meta.JsRequire e.e_meta)
-			-> dot_path p
-		| _ -> s_path ctx p);
+		| TEnumDecl ({ e_extern = true } as e) when not (Meta.has Meta.JsRequire e.e_meta) ->
+			dot_path e.e_path
+		| TClassDecl c ->
+			let p = get_generated_class_path c in
+			if c.cl_extern && not (Meta.has Meta.JsRequire c.cl_meta) then
+				dot_path p
+			else
+				s_path ctx p
+		| _ ->
+			s_path ctx (t_path t)
+	);
 	ctx
 	ctx
 
 
 let gen_single_expr ctx e expr =
 let gen_single_expr ctx e expr =