swfLoader.ml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2019 Haxe Foundation
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *)
  16. open Swf
  17. open As3
  18. open As3hl
  19. open Common
  20. open Globals
  21. open Ast
  22. open NativeLibraries
  23. let lowercase_pack pack =
  24. let rec loop acc pack =
  25. match pack with
  26. | [] -> List.rev acc
  27. | name :: rest ->
  28. let name =
  29. let fchar = String.get name 0 in
  30. if fchar >= 'A' && fchar <= 'Z' then
  31. (String.make 1 (Char.lowercase fchar)) ^ String.sub name 1 (String.length name - 1)
  32. else
  33. name
  34. in
  35. loop (name :: acc) rest
  36. in
  37. loop [] pack
  38. let tp_dyn = { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; }
  39. let ct_dyn = CTPath tp_dyn
  40. let ct_rest = CTPath {
  41. tpackage = ["haxe"; "extern"];
  42. tname = "Rest";
  43. tparams = [TPType (ct_dyn,null_pos)];
  44. tsub = None;
  45. }
  46. let rec make_tpath = function
  47. | HMPath (pack,name) ->
  48. let pdyn = ref false in
  49. let pack, name = match pack, name with
  50. | [], "void" -> [], "Void"
  51. | [], "int" -> [], "Int"
  52. | [], "uint" -> [], "UInt"
  53. | [], "Number" -> [], "Float"
  54. | [], "Boolean" -> [], "Bool"
  55. | [], "Object" -> ["flash";"utils"], "Object"
  56. | [], "Function" -> ["flash";"utils"], "Function"
  57. | [], "Class" | [],"Array" -> pdyn := true; pack, name
  58. | [], "Error" -> ["flash";"errors"], "Error"
  59. | [] , "XML" -> ["flash";"xml"], "XML"
  60. | [] , "XMLList" -> ["flash";"xml"], "XMLList"
  61. | [] , "QName" -> ["flash";"utils"], "QName"
  62. | [] , "Namespace" -> ["flash";"utils"], "Namespace"
  63. | [] , "RegExp" -> ["flash";"utils"], "RegExp"
  64. | ["__AS3__";"vec"] , "Vector" -> ["flash"], "Vector"
  65. | _ -> lowercase_pack pack, name
  66. in
  67. {
  68. tpackage = pack;
  69. tname = name;
  70. tparams = if !pdyn then [TPType (ct_dyn,null_pos)] else[];
  71. tsub = None;
  72. }
  73. | HMName (id,ns) ->
  74. {
  75. tpackage = (match ns with
  76. | HNInternal (Some ns) -> ExtString.String.nsplit ns "."
  77. | HNPrivate (Some ns) ->
  78. (try
  79. let file, line = ExtString.String.split ns ".as$" in
  80. [file ^ "_" ^ line]
  81. with _ ->
  82. [])
  83. | _ -> []);
  84. tname = id;
  85. tparams = [];
  86. tsub = None;
  87. }
  88. | HMNSAny (id) ->
  89. {
  90. tpackage = [];
  91. tname = id;
  92. tparams = [];
  93. tsub = None;
  94. }
  95. | HMMultiName _ ->
  96. die "" __LOC__
  97. | HMRuntimeName _ ->
  98. die "" __LOC__
  99. | HMRuntimeNameLate ->
  100. die "" __LOC__
  101. | HMMultiNameLate _ ->
  102. die "" __LOC__
  103. | HMAttrib _ ->
  104. die "" __LOC__
  105. | HMAny ->
  106. die "" __LOC__
  107. | HMParams (t,params) ->
  108. let params = List.map (fun t -> TPType (CTPath (make_tpath t),null_pos)) params in
  109. { (make_tpath t) with tparams = params }
  110. let make_topt = function
  111. | None -> tp_dyn
  112. | Some t -> make_tpath t
  113. let make_type t = CTPath (make_topt t)
  114. let make_dyn_type t =
  115. match make_topt t with
  116. | { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") } -> make_type None
  117. | o -> CTPath o
  118. let is_valid_path com pack name =
  119. let rec loop = function
  120. | [] ->
  121. false
  122. | (file,load) :: l ->
  123. match load (pack,name) null_pos with
  124. | None -> loop l
  125. | Some (_,a) -> true
  126. in
  127. let file = Printf.sprintf "%s/%s.hx" (String.concat "/" pack) name in
  128. loop com.load_extern_type || (try ignore(Common.find_file com file); true with Not_found -> false)
  129. let build_class com c file =
  130. let path = make_tpath c.hlc_name in
  131. let pos = { pfile = file ^ "@" ^ s_type_path (path.tpackage,path.tname); pmin = 0; pmax = 0 } in
  132. match path with
  133. | { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") } ->
  134. let inf = {
  135. d_name = path.tname,null_pos;
  136. d_doc = None;
  137. d_params = [];
  138. d_meta = [];
  139. d_flags = [];
  140. d_data = ct_dyn,null_pos;
  141. } in
  142. (path.tpackage, [(ETypedef inf,pos)])
  143. | _ ->
  144. (* make flags *)
  145. let flags = [HExtern] in
  146. let flags = if c.hlc_interface then HInterface :: flags else flags in
  147. let flags = (match c.hlc_super with
  148. | None | Some (HMPath ([],"Object")) -> flags
  149. | Some (HMPath ([],"Function")) -> flags (* found in AIR SDK *)
  150. | Some s -> HExtends (make_tpath s,null_pos) :: flags
  151. ) in
  152. let flags = List.map (fun i ->
  153. let i = (match i with
  154. | HMMultiName (Some id,ns) ->
  155. let rec loop = function
  156. | [] -> HMPath ([],id)
  157. | HNPublic (Some ns) :: _ when is_valid_path com (ExtString.String.nsplit ns ".") id -> HMPath (ExtString.String.nsplit ns ".",id)
  158. | _ :: l -> loop l
  159. in
  160. loop ns
  161. | HMPath _ -> i
  162. | _ -> die "" __LOC__
  163. ) in
  164. if c.hlc_interface then HExtends (make_tpath i,null_pos) else HImplements (make_tpath i,null_pos)
  165. ) (Array.to_list c.hlc_implements) @ flags in
  166. let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (tp_dyn,null_pos) :: flags in
  167. (* make fields *)
  168. let getters = Hashtbl.create 0 in
  169. let setters = Hashtbl.create 0 in
  170. let override = Hashtbl.create 0 in
  171. let is_xml = (match path.tpackage, path.tname with
  172. | ["flash";"xml"], ("XML" | "XMLList") -> true
  173. | _ -> false
  174. ) in
  175. let make_field stat acc f =
  176. let meta = ref [] in
  177. let flags = (match f.hlf_name with
  178. | HMPath _ -> [APublic,null_pos]
  179. | HMName (_,ns) ->
  180. (match ns with
  181. | HNPrivate _ | HNNamespace "http://www.adobe.com/2006/flex/mx/internal" -> []
  182. | HNNamespace ns ->
  183. if not (c.hlc_interface || is_xml) then meta := (Meta.Ns,[String(ns,SDoubleQuotes)]) :: !meta;
  184. [APublic,null_pos]
  185. | HNInternal (Some ns) ->
  186. if not (c.hlc_interface || is_xml) then meta := (Meta.Ns,[String(ns,SDoubleQuotes); Ident "internal"]) :: !meta;
  187. [APublic,null_pos]
  188. | HNExplicit _ | HNInternal _ | HNPublic _ ->
  189. [APublic,null_pos]
  190. | HNStaticProtected _ | HNProtected _ ->
  191. meta := (Meta.Protected,[]) :: !meta;
  192. [APrivate,null_pos])
  193. | _ -> []
  194. ) in
  195. if flags = [] then acc else
  196. let flags = if stat then (AStatic,null_pos) :: flags else flags in
  197. let name = (make_tpath f.hlf_name).tname in
  198. let mk_meta() =
  199. List.map (fun (s,cl) -> s, List.map (fun c -> EConst c,pos) cl, pos) (!meta)
  200. in
  201. let cf = {
  202. cff_name = name,null_pos;
  203. cff_doc = None;
  204. cff_pos = pos;
  205. cff_meta = [];
  206. cff_access = flags;
  207. cff_kind = FVar (None,None);
  208. } in
  209. match f.hlf_kind with
  210. | HFVar v ->
  211. cf.cff_meta <- mk_meta();
  212. cf.cff_kind <- FVar (Some (make_dyn_type v.hlv_type,null_pos),None);
  213. if v.hlv_const then begin
  214. cf.cff_access <- (AFinal,null_pos) :: cf.cff_access;
  215. end;
  216. cf :: acc
  217. | HFMethod m when m.hlm_override ->
  218. Hashtbl.add override (name,stat) ();
  219. acc
  220. | HFMethod m ->
  221. (match m.hlm_kind with
  222. | MK3Normal ->
  223. let t = m.hlm_type in
  224. let p = ref 0 and pn = ref 0 in
  225. let make_type = if stat || name = "new" then make_dyn_type else make_type in
  226. let args = List.map (fun at ->
  227. let aname = (match t.hlmt_pnames with
  228. | None -> incr pn; "p" ^ string_of_int !pn
  229. | Some l ->
  230. match List.nth l !p with
  231. | None -> incr pn; "p" ^ string_of_int !pn
  232. | Some i -> i
  233. ) in
  234. let opt_val = (match t.hlmt_dparams with
  235. | None -> None
  236. | Some l ->
  237. try
  238. Some (List.nth l (!p - List.length t.hlmt_args + List.length l))
  239. with
  240. _ -> None
  241. ) in
  242. incr p;
  243. let t = make_type at in
  244. let is_opt = ref false in
  245. let def_val = match opt_val with
  246. | None -> None
  247. | Some v ->
  248. let v = (match v with
  249. | HVNone | HVNull | HVNamespace _ ->
  250. is_opt := true;
  251. None
  252. | HVString s ->
  253. is_opt := true;
  254. Some (String (s,SDoubleQuotes))
  255. | HVBool b ->
  256. Some (Ident (if b then "true" else "false"))
  257. | HVInt i | HVUInt i ->
  258. Some (Int (Int32.to_string i))
  259. | HVFloat f ->
  260. Some (Float (Numeric.float_repres f))
  261. ) in
  262. match v with
  263. | None -> None
  264. | Some v ->
  265. (* add for -D gen-hx-classes generation *)
  266. meta := (Meta.DefParam,[String(aname,SDoubleQuotes);v]) :: !meta;
  267. Some (EConst v,pos)
  268. in
  269. ((aname,null_pos),!is_opt,[],Some (t,null_pos),def_val)
  270. ) t.hlmt_args in
  271. let args = if t.hlmt_var_args then
  272. args @ [("restArgs",null_pos),false,[],Some (ct_rest,null_pos),None]
  273. else args in
  274. let f = {
  275. f_params = [];
  276. f_args = args;
  277. f_type = Some (make_type t.hlmt_ret,null_pos);
  278. f_expr = None;
  279. } in
  280. cf.cff_meta <- mk_meta();
  281. cf.cff_kind <- FFun f;
  282. cf :: acc
  283. | MK3Getter ->
  284. Hashtbl.add getters (name,stat) (m.hlm_type.hlmt_ret,mk_meta());
  285. acc
  286. | MK3Setter ->
  287. Hashtbl.add setters (name,stat) ((match m.hlm_type.hlmt_args with [t] -> t | _ -> die "" __LOC__),mk_meta());
  288. acc
  289. )
  290. | _ -> acc
  291. in
  292. let fields = if c.hlc_interface then [] else make_field false [] {
  293. hlf_name = HMPath ([],"new");
  294. hlf_slot = 0;
  295. hlf_metas = None;
  296. hlf_kind = HFMethod {
  297. hlm_type = { c.hlc_construct with hlmt_ret = Some (HMPath ([],"void")) };
  298. hlm_final = false;
  299. hlm_override = false;
  300. hlm_kind = MK3Normal
  301. }
  302. } in
  303. let fields = Array.fold_left (make_field false) fields c.hlc_fields in
  304. let fields = Array.fold_left (make_field true) fields c.hlc_static_fields in
  305. let make_get_set name stat tget tset =
  306. let get, set, t, meta = (match tget, tset with
  307. | None, None -> die "" __LOC__
  308. | Some (t,meta), None -> true, false, t, meta
  309. | None, Some (t,meta) -> false, true, t, meta
  310. | Some (t1,meta1), Some (t2,meta2) -> true, true, (if t1 <> t2 then None else t1), meta1 @ (List.filter (fun m -> not (List.mem m meta1)) meta2)
  311. ) in
  312. let t = if name = "endian" then Some (HMPath (["flash";"utils"],"Endian")) else t in
  313. let flags, accessor_flags = [APublic,null_pos], [APrivate,null_pos] in
  314. let flags, accessor_flags = if stat then (AStatic,null_pos) :: flags, (AStatic,null_pos) :: accessor_flags else flags, accessor_flags in
  315. let property_typehint = Some (make_dyn_type t,null_pos) in
  316. let fields = [] in
  317. let read_access, fields =
  318. if get then
  319. let getter = {
  320. cff_name = "get_" ^ name,null_pos;
  321. cff_pos = pos;
  322. cff_doc = None;
  323. cff_access = accessor_flags;
  324. cff_meta = [];
  325. cff_kind = FFun {
  326. f_params = [];
  327. f_args = [];
  328. f_type = property_typehint;
  329. f_expr = None;
  330. };
  331. } in
  332. ("get",null_pos), getter :: fields
  333. else
  334. ("never",null_pos), fields
  335. in
  336. let write_access, fields =
  337. if set then
  338. let setter = {
  339. cff_name = "set_" ^ name,null_pos;
  340. cff_pos = pos;
  341. cff_doc = None;
  342. cff_access = accessor_flags;
  343. cff_meta = [];
  344. cff_kind = FFun {
  345. f_params = [];
  346. f_args = [(("value",null_pos),false,[],property_typehint,None)];
  347. f_type = property_typehint;
  348. f_expr = None;
  349. };
  350. } in
  351. ("set",null_pos), setter :: fields
  352. else
  353. ("never",null_pos), fields
  354. in
  355. {
  356. cff_name = name,null_pos;
  357. cff_pos = pos;
  358. cff_doc = None;
  359. cff_access = flags;
  360. cff_meta = (Meta.FlashProperty,[],pos) :: meta;
  361. cff_kind = FProp (read_access,write_access,property_typehint,None);
  362. } :: fields
  363. in
  364. let fields = Hashtbl.fold (fun (name,stat) t acc ->
  365. if Hashtbl.mem override (name,stat) then acc else
  366. make_get_set name stat (Some t) (try Some (Hashtbl.find setters (name,stat)) with Not_found -> None) @ acc
  367. ) getters fields in
  368. let fields = Hashtbl.fold (fun (name,stat) t acc ->
  369. if Hashtbl.mem getters (name,stat) || Hashtbl.mem override (name,stat) then
  370. acc
  371. else
  372. make_get_set name stat None (Some t) @ acc
  373. ) setters fields in
  374. try
  375. (*
  376. If the class only contains static String constants, make it an enum
  377. *)
  378. let real_type = ref None in
  379. let rec loop = function
  380. | [] -> []
  381. | f :: l ->
  382. match f.cff_kind with
  383. | FVar (Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")} as real_t),_),None)
  384. | FProp (("default",_),("never",_),Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")}) as real_t,_),None) when List.mem_assoc AStatic f.cff_access ->
  385. (match !real_type with
  386. | None ->
  387. real_type := Some real_t
  388. | Some t ->
  389. if t <> real_t then raise Exit);
  390. {
  391. cff_name = f.cff_name;
  392. cff_doc = None;
  393. cff_pos = pos;
  394. cff_meta = [];
  395. cff_access = [];
  396. cff_kind = FVar (Some (real_t,null_pos), None);
  397. } :: loop l
  398. | FFun { f_args = [] } when fst f.cff_name = "new" -> loop l
  399. | _ -> raise Exit
  400. in
  401. List.iter (function HExtends _ | HImplements _ -> raise Exit | _ -> ()) flags;
  402. let constr = loop fields in
  403. let name = "enumAbstract:" ^ String.concat "." (path.tpackage @ [path.tname]) in
  404. if not (Common.raw_defined com name) then raise Exit;
  405. let native_path = s_type_path (path.tpackage, path.tname) in
  406. let real_type = Option.get !real_type in
  407. let abstract_data = {
  408. d_name = path.tname,null_pos;
  409. d_doc = None;
  410. d_params = [];
  411. d_meta = [(Meta.Enum,[],null_pos);(Meta.Native,[(EConst (String(native_path,SDoubleQuotes)),null_pos)],null_pos)];
  412. d_flags = [AbExtern; AbOver (real_type,pos); AbFrom (real_type,pos)];
  413. d_data = constr;
  414. } in
  415. (path.tpackage, [(EAbstract abstract_data,pos)])
  416. with Exit ->
  417. let flags = if c.hlc_final && List.exists (fun f -> fst f.cff_name <> "new" && not (List.mem_assoc AStatic f.cff_access)) fields then HFinal :: flags else flags in
  418. let meta =
  419. (* if the package was lowercased, add @:native("Original.Path") meta *)
  420. match c.hlc_name with
  421. | HMPath (pack,name) when (pack <> [] && pack <> path.tpackage) ->
  422. let native_path = (String.concat "." pack) ^ "." ^ name in
  423. [(Meta.Native,[(EConst (String(native_path,SDoubleQuotes)), pos)],pos)]
  424. | _ ->
  425. []
  426. in
  427. let class_data = {
  428. d_name = path.tname,null_pos;
  429. d_doc = None;
  430. d_params = [];
  431. d_meta = meta;
  432. d_flags = flags;
  433. d_data = fields;
  434. } in
  435. (path.tpackage, [(EClass class_data,pos)])
  436. let extract_data (_,tags) =
  437. let t = Timer.timer ["read";"swf"] in
  438. let h = Hashtbl.create 0 in
  439. let rec loop_field f =
  440. match f.hlf_kind with
  441. | HFClass c ->
  442. let path = make_tpath f.hlf_name in
  443. (match path with
  444. | { tpackage = []; tname = "Float" | "Bool" | "Int" | "UInt" | "Dynamic" } -> ()
  445. | { tpackage = _; tname = "MethodClosure" } -> ()
  446. | _ -> Hashtbl.add h (path.tpackage,path.tname) c)
  447. | _ -> ()
  448. in
  449. List.iter (fun t ->
  450. match t.tdata with
  451. | TActionScript3 (_,as3) ->
  452. List.iter (fun i -> Array.iter loop_field i.hls_fields) (As3hlparse.parse as3)
  453. | _ -> ()
  454. ) tags;
  455. t();
  456. h
  457. let remove_debug_infos as3 =
  458. let hl = As3hlparse.parse as3 in
  459. let methods = Hashtbl.create 0 in
  460. let rec loop_field f =
  461. { f with hlf_kind = (match f.hlf_kind with
  462. | HFMethod m -> HFMethod { m with hlm_type = loop_method m.hlm_type }
  463. | HFFunction f -> HFFunction (loop_method f)
  464. | HFVar v -> HFVar v
  465. | HFClass c -> HFClass (loop_class c))
  466. }
  467. and loop_class c =
  468. (* mutate in order to preserve sharing *)
  469. c.hlc_construct <- loop_method c.hlc_construct;
  470. c.hlc_fields <- Array.map loop_field c.hlc_fields;
  471. c.hlc_static_construct <- loop_method c.hlc_static_construct;
  472. c.hlc_static_fields <- Array.map loop_field c.hlc_static_fields;
  473. c
  474. and loop_static s =
  475. {
  476. hls_method = loop_method s.hls_method;
  477. hls_fields = Array.map loop_field s.hls_fields;
  478. }
  479. and loop_method m =
  480. try
  481. Hashtbl.find methods m.hlmt_index
  482. with Not_found ->
  483. let m2 = { m with hlmt_debug_name = None; hlmt_pnames = None } in
  484. Hashtbl.add methods m.hlmt_index m2;
  485. m2.hlmt_function <- (match m.hlmt_function with None -> None | Some f -> Some (loop_function f));
  486. m2
  487. and loop_function f =
  488. let cur = ref 0 in
  489. let positions = MultiArray.map (fun op ->
  490. let p = !cur in
  491. (match op with
  492. | HDebugReg _ | HDebugLine _ | HDebugFile _ | HBreakPointLine _ | HTimestamp -> ()
  493. | _ -> incr cur);
  494. p
  495. ) f.hlf_code in
  496. MultiArray.add positions (!cur);
  497. let code = MultiArray.create() in
  498. MultiArray.iteri (fun pos op ->
  499. match op with
  500. | HDebugReg _ | HDebugLine _ | HDebugFile _ | HBreakPointLine _ | HTimestamp -> ()
  501. | _ ->
  502. let p delta =
  503. MultiArray.get positions (pos + delta) - MultiArray.length code
  504. in
  505. let op = (match op with
  506. | HJump (j,delta) -> HJump (j, p delta)
  507. | HSwitch (d,deltas) -> HSwitch (p d,List.map p deltas)
  508. | HFunction m -> HFunction (loop_method m)
  509. | HCallStatic (m,args) -> HCallStatic (loop_method m,args)
  510. | HClassDef c -> HClassDef c (* mutated *)
  511. | _ -> op) in
  512. MultiArray.add code op
  513. ) f.hlf_code;
  514. f.hlf_code <- code;
  515. f.hlf_trys <- Array.map (fun t ->
  516. {
  517. t with
  518. hltc_start = MultiArray.get positions t.hltc_start;
  519. hltc_end = MultiArray.get positions t.hltc_end;
  520. hltc_handle = MultiArray.get positions t.hltc_handle;
  521. }
  522. ) f.hlf_trys;
  523. f
  524. in
  525. As3hlparse.flatten (List.map loop_static hl)
  526. let parse_swf com file =
  527. let t = Timer.timer ["read";"swf"] in
  528. let is_swc = file_extension file = "swc" || file_extension file = "ane" in
  529. let ch = if is_swc then begin
  530. let zip = Zip.open_in file in
  531. try
  532. let entry = Zip.find_entry zip "library.swf" in
  533. let ch = IO.input_string (Zip.read_entry zip entry) in
  534. Zip.close_in zip;
  535. ch
  536. with _ ->
  537. Zip.close_in zip;
  538. failwith ("The input swc " ^ file ^ " is corrupted")
  539. end else
  540. IO.input_channel (open_in_bin file)
  541. in
  542. let h, tags = try
  543. Swf.parse ch
  544. with Out_of_memory ->
  545. failwith ("Out of memory while parsing " ^ file)
  546. | _ ->
  547. failwith ("The input swf " ^ file ^ " is corrupted")
  548. in
  549. IO.close_in ch;
  550. List.iter (fun t ->
  551. match t.tdata with
  552. | TActionScript3 (id,as3) when not com.debug && not com.display.DisplayTypes.DisplayMode.dms_display ->
  553. t.tdata <- TActionScript3 (id,remove_debug_infos as3)
  554. | _ -> ()
  555. ) tags;
  556. t();
  557. (h,tags)
  558. class swf_library com name file_path = object(self)
  559. inherit [swf_lib_type,Swf.swf] native_library name file_path
  560. val mutable swf_data = None
  561. val mutable swf_classes = None
  562. val haxe_classes = Hashtbl.create 0
  563. method load =
  564. ignore(self#get_swf)
  565. method get_swf = match swf_data with
  566. | None ->
  567. let d = parse_swf com file_path in
  568. swf_data <- Some d;
  569. d
  570. | Some d ->
  571. d
  572. method extract = match swf_classes with
  573. | None ->
  574. let d = extract_data self#get_swf in
  575. swf_classes <- Some d;
  576. d
  577. | Some d ->
  578. d
  579. method lookup path =
  580. try Some (Hashtbl.find (self#extract) path)
  581. with Not_found -> None
  582. method list_modules =
  583. Hashtbl.fold (fun path _ acc -> path :: acc) (self#extract) []
  584. method close =
  585. ()
  586. method build (path : path) (p : pos) : Ast.package option =
  587. try
  588. Some (Hashtbl.find haxe_classes path)
  589. with Not_found -> try
  590. let c = Hashtbl.find (self#extract) path in
  591. let c = build_class com c file_path in
  592. Hashtbl.add haxe_classes path c;
  593. Some c
  594. with Not_found ->
  595. None
  596. method get_data = self#get_swf
  597. end
  598. let add_swf_lib com file extern =
  599. let real_file = (try Common.find_file com file with Not_found -> failwith (" Library not found : " ^ file)) in
  600. let swf_lib = new swf_library com file real_file in
  601. if not extern then com.native_libs.swf_libs <- (swf_lib :> (swf_lib_type,Swf.swf) native_library) :: com.native_libs.swf_libs;
  602. CommonCache.handle_native_lib com swf_lib
  603. let remove_classes toremove lib l =
  604. match !toremove with
  605. | [] -> lib
  606. | _ ->
  607. let hcl = Hashtbl.create 0 in
  608. List.iter (fun path -> Hashtbl.add hcl path ()) l;
  609. match List.filter (fun c -> Hashtbl.mem hcl c) (!toremove) with
  610. | [] -> lib
  611. | classes ->
  612. let rec tags = function
  613. | [] -> []
  614. | t :: l ->
  615. match t.tdata with
  616. | TActionScript3 (h,data) ->
  617. let data = As3hlparse.parse data in
  618. let rec loop f =
  619. match f.hlf_kind with
  620. | HFClass _ ->
  621. let path = make_tpath f.hlf_name in
  622. not (List.mem (path.tpackage,path.tname) classes)
  623. | _ -> true
  624. in
  625. let data = List.map (fun s -> { s with hls_fields = Array.of_list (List.filter loop (Array.to_list s.hls_fields)) }) data in
  626. let data = List.filter (fun s -> Array.length s.hls_fields > 0) data in
  627. (if data = [] then
  628. tags l
  629. else
  630. { t with tdata = TActionScript3 (h,As3hlparse.flatten data) } :: tags l)
  631. | _ ->
  632. t :: tags l
  633. in
  634. toremove := List.filter (fun p -> not (List.mem p classes)) !toremove;
  635. fst lib, tags (snd lib)