Explorar el Código

[js] use Array.prototype.slice.call(arguments, offset) for rest args and still generate non-rest args normally in ES5 (closes #9992)

Dan Korostelev hace 4 años
padre
commit
0956a28e7f
Se han modificado 1 ficheros con 20 adiciones y 32 borrados
  1. 20 32
      src/generators/genjs.ml

+ 20 - 32
src/generators/genjs.ml

@@ -336,31 +336,15 @@ let rec concat ctx s f = function
 	It's the only way to avoid disabling javascript VM optimizations of functions
 	It's the only way to avoid disabling javascript VM optimizations of functions
 	with rest arguments.
 	with rest arguments.
 *)
 *)
-let declare_rest_args_legacy com args rest_arg =
-	let arguments = mk (TIdent "arguments") t_dynamic null_pos
-	and index i = mk (TConst (TInt (Int32.of_int i))) com.basic.tint null_pos in
-	let rec loop args i =
-		match args with
-		| [] -> []
-		| (v,e_opt) :: rest ->
-			(* var v = arguments[i]; *)
-			let value = mk (TArray (arguments,index i)) v.v_type null_pos in
-			let decl = mk (TVar (v,Some value)) com.basic.tvoid v.v_pos in
-
-			match e_opt with
-			| None -> decl :: loop rest (i + 1)
-			| Some e -> decl :: Texpr.set_default com.basic v e v.v_pos :: loop rest (i + 1)
-	in
-	let i = string_of_int (List.length args) in
-	let new_array = mk (TIdent ("new Array($l-"^ i ^")")) t_dynamic rest_arg.v_pos
-	and populate = mk (TIdent ("for(var $i=" ^ i ^ ";$i<$l;++$i){" ^ (ident rest_arg.v_name) ^ "[$i-" ^ i ^ "]=arguments[$i];}")) com.basic.tvoid rest_arg.v_pos
+let declare_rest_args_legacy com offset rest_arg =
+	let arguments = mk (TIdent "arguments") t_dynamic null_pos in
+	let array_slice = mk (TIdent ("Array.prototype.slice.call")) t_dynamic null_pos in
+	let array_slice_call = mk (TCall (
+		array_slice,
+		if offset = 0 then [arguments] else [arguments; Texpr.Builder.make_int com.basic offset null_pos]
+	)) rest_arg.v_type null_pos
 	in
 	in
-	loop args 0
-	@ [
-		mk (TIdent ("var $l=arguments.length")) com.basic.tvoid rest_arg.v_pos;
-		mk (TVar (rest_arg,Some new_array)) com.basic.tvoid rest_arg.v_pos;
-		populate
-	]
+	mk (TVar (rest_arg,Some array_slice_call)) com.basic.tvoid rest_arg.v_pos
 
 
 let fun_block ctx f p =
 let fun_block ctx f p =
 	let e = List.fold_left (fun e (a,c) ->
 	let e = List.fold_left (fun e (a,c) ->
@@ -902,6 +886,12 @@ and gen_function ?(keyword="function") ctx f pos =
 	let old = ctx.in_value, ctx.in_loop in
 	let old = ctx.in_value, ctx.in_loop in
 	ctx.in_value <- None;
 	ctx.in_value <- None;
 	ctx.in_loop <- false;
 	ctx.in_loop <- false;
+	let mk_non_rest_arg_names arg_list =
+		List.map (fun (v,_) ->
+			check_var_declaration v;
+			ident v.v_name
+		) arg_list
+	in
 	let f,args =
 	let f,args =
 		match List.rev f.tf_args with
 		match List.rev f.tf_args with
 		| (v,None) :: args_rev when ExtType.is_rest (follow v.v_type) ->
 		| (v,None) :: args_rev when ExtType.is_rest (follow v.v_type) ->
@@ -914,21 +904,19 @@ and gen_function ?(keyword="function") ctx f pos =
 				) f.tf_args
 				) f.tf_args
 			(* Resort to `arguments` special object for ES < 6 *)
 			(* Resort to `arguments` special object for ES < 6 *)
 			else
 			else
-				let args_decl = declare_rest_args_legacy ctx.com (List.rev args_rev) v in
+				let non_rest_args = List.rev args_rev in
+				let rest_args_decl = declare_rest_args_legacy ctx.com (List.length non_rest_args) v in
 				let body =
 				let body =
 					let el =
 					let el =
 						match f.tf_expr.eexpr with
 						match f.tf_expr.eexpr with
-						| TBlock el -> args_decl @ el
-						| _ -> args_decl @ [f.tf_expr]
+						| TBlock el -> rest_args_decl :: el
+						| _ -> [rest_args_decl; f.tf_expr]
 					in
 					in
 					mk (TBlock el) f.tf_expr.etype f.tf_expr.epos
 					mk (TBlock el) f.tf_expr.etype f.tf_expr.epos
 				in
 				in
-				{ f with tf_args = []; tf_expr = body }, []
+				{ f with tf_args = non_rest_args; tf_expr = body }, mk_non_rest_arg_names non_rest_args
 		| _ ->
 		| _ ->
-			f, List.map (fun (v,_) ->
-				check_var_declaration v;
-				ident v.v_name
-			) f.tf_args
+			f, mk_non_rest_arg_names f.tf_args
 	in
 	in
 	print ctx "%s(%s) " keyword (String.concat "," args);
 	print ctx "%s(%s) " keyword (String.concat "," args);
 	gen_expr ctx (fun_block ctx f pos);
 	gen_expr ctx (fun_block ctx f pos);