|
@@ -41,8 +41,9 @@ type ctx = {
|
|
|
packages : (string list,unit) Hashtbl.t;
|
|
|
smap : sourcemap;
|
|
|
js_modern : bool;
|
|
|
+ all_features : bool;
|
|
|
mutable features : (string, bool) PMap.t;
|
|
|
-
|
|
|
+ mutable boot_init : texpr option;
|
|
|
mutable current : tclass;
|
|
|
mutable statics : (tclass * string * texpr) list;
|
|
|
mutable inits : texpr list;
|
|
@@ -87,6 +88,7 @@ let ident s = if Hashtbl.mem kwds s then "$" ^ s else s
|
|
|
let anon_field s = if Hashtbl.mem kwds s || not (valid_js_ident s) then "'" ^ s ^ "'" else s
|
|
|
|
|
|
let has_feature ctx f =
|
|
|
+ if ctx.all_features then true else
|
|
|
try
|
|
|
PMap.find f ctx.features
|
|
|
with Not_found ->
|
|
@@ -96,13 +98,17 @@ let has_feature ctx f =
|
|
|
let r = (try
|
|
|
let path = List.rev pack, cl in
|
|
|
(match List.find (fun t -> t_path t = path) ctx.com.types with
|
|
|
+ | t when meth = "*" -> (not ctx.com.dead_code_elimination) || has_meta ":?used" (t_infos t).mt_meta
|
|
|
| TClassDecl c -> PMap.exists meth c.cl_statics || PMap.exists meth c.cl_fields
|
|
|
| _ -> false)
|
|
|
with Not_found ->
|
|
|
false
|
|
|
) in
|
|
|
ctx.features <- PMap.add f r ctx.features;
|
|
|
- r
|
|
|
+ r
|
|
|
+
|
|
|
+let add_feature ctx f =
|
|
|
+ ctx.features <- PMap.add f true ctx.features
|
|
|
|
|
|
let handle_newlines ctx str =
|
|
|
if ctx.com.debug then
|
|
@@ -133,7 +139,9 @@ let print ctx =
|
|
|
|
|
|
let unsupported p = error "This expression cannot be compiled to Javascript" p
|
|
|
|
|
|
-let add_mapping ctx pos =
|
|
|
+let add_mapping ctx e =
|
|
|
+ if not ctx.com.debug || e.epos.pmin < 0 then () else
|
|
|
+ let pos = e.epos in
|
|
|
let smap = ctx.smap in
|
|
|
let file = try
|
|
|
Hashtbl.find smap.sources_hash pos.pfile
|
|
@@ -324,7 +332,7 @@ let gen_constant ctx p = function
|
|
|
| TThis -> spr ctx (this ctx)
|
|
|
| TSuper -> assert false
|
|
|
|
|
|
-let rec gen_call ctx e el =
|
|
|
+let rec gen_call ctx e el in_value =
|
|
|
match e.eexpr , el with
|
|
|
| TConst TSuper , params ->
|
|
|
(match ctx.current.cl_super with
|
|
@@ -378,6 +386,20 @@ let rec gen_call ctx e el =
|
|
|
spr ctx "}"
|
|
|
) (Hashtbl.fold (fun name data acc -> (name,data) :: acc) ctx.com.resources []);
|
|
|
spr ctx "]";
|
|
|
+ | TLocal { v_name = "`trace" }, [e;infos] ->
|
|
|
+ if has_feature (if ctx.all_features then { ctx with all_features = false } else ctx) "haxe.Log.trace" then begin
|
|
|
+ let t = (try List.find (fun t -> t_path t = (["haxe"],"Log")) ctx.com.types with _ -> assert false) in
|
|
|
+ spr ctx (ctx.type_accessor t);
|
|
|
+ spr ctx ".trace(";
|
|
|
+ gen_value ctx e;
|
|
|
+ spr ctx ",";
|
|
|
+ gen_value ctx infos;
|
|
|
+ spr ctx ")";
|
|
|
+ end else begin
|
|
|
+ spr ctx "console.log(";
|
|
|
+ gen_value ctx e;
|
|
|
+ spr ctx ")";
|
|
|
+ end
|
|
|
| _ ->
|
|
|
gen_value ctx e;
|
|
|
spr ctx "(";
|
|
@@ -385,6 +407,7 @@ let rec gen_call ctx e el =
|
|
|
spr ctx ")"
|
|
|
|
|
|
and gen_expr ctx e =
|
|
|
+ add_mapping ctx e;
|
|
|
match e.eexpr with
|
|
|
| TConst c -> gen_constant ctx e.epos c
|
|
|
| TLocal v -> spr ctx (ident v.v_name)
|
|
@@ -399,10 +422,16 @@ and gen_expr ctx e =
|
|
|
gen_value ctx e1;
|
|
|
print ctx " %s " (Ast.s_binop op);
|
|
|
gen_value ctx e2;
|
|
|
- | TField (x,"iterator") when Common.defined ctx.com "js-iterator-wrap" ->
|
|
|
- print ctx "$iterator(";
|
|
|
- gen_value ctx x;
|
|
|
- print ctx ")";
|
|
|
+ | TField (x,"iterator") when has_feature ctx "HxOverrides.iter" ->
|
|
|
+ (match follow x.etype with
|
|
|
+ | TAnon _ | TDynamic _ | TMono _ ->
|
|
|
+ add_feature ctx "use.$iterator";
|
|
|
+ print ctx "$iterator(";
|
|
|
+ gen_value ctx x;
|
|
|
+ print ctx ")";
|
|
|
+ | _ ->
|
|
|
+ gen_value ctx x;
|
|
|
+ spr ctx (field "iterator"))
|
|
|
| TField (x,s) ->
|
|
|
gen_value ctx x;
|
|
|
spr ctx (field s)
|
|
@@ -410,6 +439,7 @@ and gen_expr ctx e =
|
|
|
gen_value ctx x;
|
|
|
spr ctx (field s)
|
|
|
| TClosure (x,s) ->
|
|
|
+ add_feature ctx "use.$bind";
|
|
|
(match x.eexpr with
|
|
|
| TConst _ | TLocal _ ->
|
|
|
gen_value ctx x;
|
|
@@ -457,7 +487,7 @@ and gen_expr ctx e =
|
|
|
ctx.in_loop <- snd old;
|
|
|
ctx.separator <- true
|
|
|
| TCall (e,el) ->
|
|
|
- gen_call ctx e el
|
|
|
+ gen_call ctx e el false
|
|
|
| TArrayDecl el ->
|
|
|
spr ctx "[";
|
|
|
concat ctx "," (gen_value ctx) el;
|
|
@@ -698,14 +728,24 @@ and gen_expr ctx e =
|
|
|
spr ctx ")"
|
|
|
|
|
|
|
|
|
-and gen_block ctx e =
|
|
|
+and gen_block ?(after=false) ctx e =
|
|
|
match e.eexpr with
|
|
|
- | TBlock el -> List.iter (gen_block ctx) el
|
|
|
- | _ -> newline ctx; gen_expr ctx e
|
|
|
+ | TBlock el ->
|
|
|
+ List.iter (gen_block ~after ctx) el
|
|
|
+ | TCall ({ eexpr = TLocal { v_name = "__feature__" } }, { eexpr = TConst (TString f) } :: eif :: eelse) ->
|
|
|
+ if has_feature ctx f then
|
|
|
+ gen_block ~after ctx eif
|
|
|
+ else (match eelse with
|
|
|
+ | [] -> ()
|
|
|
+ | [e] -> gen_block ~after ctx e
|
|
|
+ | _ -> assert false)
|
|
|
+ | _ ->
|
|
|
+ if not after then newline ctx;
|
|
|
+ gen_expr ctx e;
|
|
|
+ if after then newline ctx
|
|
|
|
|
|
and gen_value ctx e =
|
|
|
- if ctx.com.debug && e.epos.pmin >= 0 then
|
|
|
- add_mapping ctx e.epos;
|
|
|
+ add_mapping ctx e;
|
|
|
let assign e =
|
|
|
mk (TBinop (Ast.OpAssign,
|
|
|
mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos,
|
|
@@ -746,11 +786,12 @@ and gen_value ctx e =
|
|
|
| TParenthesis _
|
|
|
| TObjectDecl _
|
|
|
| TArrayDecl _
|
|
|
- | TCall _
|
|
|
| TNew _
|
|
|
| TUnop _
|
|
|
| TFunction _ ->
|
|
|
gen_expr ctx e
|
|
|
+ | TCall (e,el) ->
|
|
|
+ gen_call ctx e el true
|
|
|
| TReturn _
|
|
|
| TBreak
|
|
|
| TContinue ->
|
|
@@ -916,8 +957,14 @@ let generate_class ctx c =
|
|
|
newline ctx;
|
|
|
end;
|
|
|
handle_expose ctx p c.cl_meta;
|
|
|
- print ctx "%s.__name__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst c.cl_path @ [snd c.cl_path])));
|
|
|
- newline ctx;
|
|
|
+ if has_feature ctx "js.Boot.isClass" then begin
|
|
|
+ print ctx "%s.__name__ = " p;
|
|
|
+ if has_feature ctx "Type.getClassName" then
|
|
|
+ print ctx "[%s]" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst c.cl_path @ [snd c.cl_path])))
|
|
|
+ else
|
|
|
+ print ctx "true";
|
|
|
+ newline ctx;
|
|
|
+ end;
|
|
|
(match c.cl_implements with
|
|
|
| [] -> ()
|
|
|
| l ->
|
|
@@ -951,8 +998,10 @@ let generate_class ctx c =
|
|
|
|
|
|
let bend = open_block ctx in
|
|
|
List.iter (fun f -> match f.cf_kind with Var { v_read = AccResolve } -> () | _ -> gen_class_field ctx c f) c.cl_ordered_fields;
|
|
|
- newprop ctx;
|
|
|
- print ctx "__class__: %s" p;
|
|
|
+ if has_feature ctx "js.Boot.getClass" then begin
|
|
|
+ newprop ctx;
|
|
|
+ print ctx "__class__: %s" p;
|
|
|
+ end;
|
|
|
|
|
|
if has_property_reflection then begin
|
|
|
let props = Codegen.get_properties c.cl_ordered_fields in
|
|
@@ -978,7 +1027,9 @@ let generate_enum ctx e =
|
|
|
let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path]) in
|
|
|
print ctx "%s = " p;
|
|
|
if has_feature ctx "Type.resolveEnum" then print ctx "$hxClasses[\"%s\"] = " p;
|
|
|
- print ctx "{ __ename__ : [%s], __constructs__ : [%s] }" (String.concat "," ename) (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names));
|
|
|
+ print ctx "{";
|
|
|
+ if has_feature ctx "js.Boot.isEnum" then print ctx " __ename__ : %s," (if has_feature ctx "Type.getEnumName" then "[" ^ String.concat "," ename ^ "]" else "true");
|
|
|
+ print ctx " __constructs__ : [%s] }" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names));
|
|
|
newline ctx;
|
|
|
List.iter (fun n ->
|
|
|
let f = PMap.find n e.e_constrs in
|
|
@@ -1012,7 +1063,10 @@ let generate_type ctx = function
|
|
|
| TClassDecl c ->
|
|
|
(match c.cl_init with
|
|
|
| None -> ()
|
|
|
- | Some e -> ctx.inits <- e :: ctx.inits);
|
|
|
+ | Some e when c.cl_path = (["js"],"Boot") || List.exists (function (":real",[Ast.EConst (Ast.String "js.Boot"),_],_) -> true | _ -> false) c.cl_meta ->
|
|
|
+ ctx.boot_init <- Some e
|
|
|
+ | Some e ->
|
|
|
+ ctx.inits <- e :: ctx.inits);
|
|
|
if not c.cl_extern then generate_class ctx c
|
|
|
| TEnumDecl e when e.e_extern ->
|
|
|
()
|
|
@@ -1039,11 +1093,13 @@ let alloc_ctx com =
|
|
|
sources_hash = Hashtbl.create 0;
|
|
|
mappings = Buffer.create 16;
|
|
|
};
|
|
|
+ all_features = Common.defined com "all_features";
|
|
|
js_modern = Common.defined com "js_modern";
|
|
|
statics = [];
|
|
|
inits = [];
|
|
|
current = null_class;
|
|
|
tabs = "";
|
|
|
+ boot_init = None;
|
|
|
in_value = None;
|
|
|
in_loop = false;
|
|
|
handle_break = false;
|
|
@@ -1068,6 +1124,10 @@ let generate com =
|
|
|
| Some g -> g()
|
|
|
| None ->
|
|
|
let ctx = alloc_ctx com in
|
|
|
+
|
|
|
+ if has_feature ctx "Class.*" || has_feature ctx "Type.getClassName" then add_feature ctx "js.Boot.isClass";
|
|
|
+ if has_feature ctx "Enum.*" || has_feature ctx "Type.getEnumName" then add_feature ctx "js.Boot.isEnum";
|
|
|
+
|
|
|
if ctx.js_modern then begin
|
|
|
(* Additional ES5 strict mode keywords. *)
|
|
|
List.iter (fun s -> Hashtbl.replace kwds s ()) [ "arguments"; "eval" ];
|
|
@@ -1091,20 +1151,36 @@ let generate com =
|
|
|
end;
|
|
|
newline ctx;
|
|
|
List.iter (generate_type ctx) com.types;
|
|
|
- print ctx "js.Boot.__res = {}";
|
|
|
- newline ctx;
|
|
|
- print ctx "js.Boot.__init()";
|
|
|
- newline ctx;
|
|
|
- List.iter (fun e ->
|
|
|
- gen_expr ctx e;
|
|
|
+ if has_feature ctx "haxe.Resource.content" then begin
|
|
|
+ print ctx "js.Boot.__res = {}";
|
|
|
+ newline ctx;
|
|
|
+ end;
|
|
|
+ let rec chk_features e =
|
|
|
+ match e.eexpr with
|
|
|
+ | TClosure _ -> add_feature ctx "use.$bind"
|
|
|
+ | TField (x,"iterator") when has_feature ctx "HxOverrides.iter" ->
|
|
|
+ (match follow x.etype with
|
|
|
+ | TAnon _ | TMono _ | TDynamic _ -> add_feature ctx "use.$iterator"
|
|
|
+ | _ -> ())
|
|
|
+ | _ -> Type.iter chk_features e
|
|
|
+ in
|
|
|
+ List.iter chk_features ctx.inits;
|
|
|
+ List.iter (fun (_,_,e) -> chk_features e) ctx.statics;
|
|
|
+ if has_feature ctx "use.$iterator" then begin
|
|
|
+ add_feature ctx "use.$bind";
|
|
|
+ print ctx "var $iterator = function(o) { if( o instanceof Array ) return function() { return HxOverrides.iter(o); }; return typeof(o.iterator) == 'function' ? o.iterator.$bind(o) : o.iterator; }";
|
|
|
+ ctx.separator <- true;
|
|
|
newline ctx;
|
|
|
- ) (List.rev ctx.inits);
|
|
|
+ end;
|
|
|
+ (match ctx.boot_init with
|
|
|
+ | None -> ()
|
|
|
+ | Some e -> gen_block ~after:true ctx e);
|
|
|
+ List.iter (gen_block ~after:true ctx) (List.rev ctx.inits);
|
|
|
List.iter (generate_static ctx) (List.rev ctx.statics);
|
|
|
(match com.main with
|
|
|
| None -> ()
|
|
|
- | Some e -> gen_expr ctx e);
|
|
|
+ | Some e -> gen_expr ctx e; newline ctx);
|
|
|
if ctx.found_expose then begin
|
|
|
- newline ctx;
|
|
|
print ctx
|
|
|
"function $hxExpose(src, path) {
|
|
|
var o = window;
|
|
@@ -1116,10 +1192,11 @@ let generate com =
|
|
|
}
|
|
|
o[parts[parts.length-1]] = src;
|
|
|
}";
|
|
|
+ newline ctx;
|
|
|
end;
|
|
|
if ctx.js_modern then begin
|
|
|
- newline ctx;
|
|
|
print ctx "})()";
|
|
|
+ newline ctx;
|
|
|
end;
|
|
|
if com.debug then write_mappings ctx;
|
|
|
let ch = open_out_bin com.file in
|