ソースを参照

Merge branch 'development' of https://github.com/HaxeFoundation/haxe into development

Miha Lunar 11 年 前
コミット
55d661d562
100 ファイル変更1954 行追加1047 行削除
  1. 3 0
      .gitignore
  2. 16 12
      .travis.yml
  3. 2 2
      Makefile
  4. 2 0
      ast.ml
  5. 102 49
      codegen.ml
  6. 32 2
      common.ml
  7. 45 5
      dce.ml
  8. 40 18
      doc/CHANGES.txt
  9. 1 1
      doc/extract.hxml
  10. 4 2
      doc/extract.patch
  11. 10 3
      filters.ml
  12. 23 3
      genas3.ml
  13. 11 3
      gencommon.ml
  14. 28 8
      gencpp.ml
  15. 13 1
      gencs.ml
  16. 4 0
      genjava.ml
  17. 31 11
      genjs.ml
  18. 31 28
      genswf.ml
  19. 24 3
      genswf9.ml
  20. 2 2
      genxml.ml
  21. 2 0
      haxe.hxproj
  22. 40 9
      interp.ml
  23. 1 1
      libs
  24. 10 1
      main.ml
  25. 88 64
      matcher.ml
  26. 53 7
      optimizer.ml
  27. 24 11
      parser.ml
  28. 2 2
      std/Lambda.hx
  29. 2 2
      std/Map.hx
  30. 15 4
      std/Std.hx
  31. 70 69
      std/UInt.hx
  32. 3 0
      std/cpp/_std/Date.hx
  33. 2 2
      std/cpp/_std/Std.hx
  34. 3 1
      std/cpp/_std/haxe/Utf8.hx
  35. 2 2
      std/cpp/_std/sys/FileSystem.hx
  36. 202 0
      std/cpp/_std/sys/db/Mysql.hx
  37. 186 0
      std/cpp/_std/sys/db/Sqlite.hx
  38. 15 0
      std/cpp/vm/Debugger.hx
  39. 20 8
      std/cs/_std/Array.hx
  40. 2 2
      std/cs/_std/Std.hx
  41. 5 0
      std/cs/internal/StringExt.hx
  42. 2 2
      std/flash/_std/Std.hx
  43. 16 6
      std/flash/_std/haxe/Json.hx
  44. 1 0
      std/flash/display/DisplayObjectContainer.hx
  45. 1 0
      std/flash/display/Stage3D.hx
  46. 2 0
      std/flash/display3D/Context3D.hx
  47. 1 0
      std/flash/display3D/Context3DProfile.hx
  48. 1 0
      std/flash/events/AVStatusEvent.hx
  49. 10 0
      std/flash/events/DRMReturnVoucherCompleteEvent.hx
  50. 10 0
      std/flash/events/DRMReturnVoucherErrorEvent.hx
  51. 1 0
      std/flash/events/GameInputEvent.hx
  52. 2 1
      std/flash/events/HTTPStatusEvent.hx
  53. 1 0
      std/flash/events/StageVideoAvailabilityEvent.hx
  54. 2 1
      std/flash/media/AVPeriodInfo.hx
  55. 1 0
      std/flash/media/AVPlayState.hx
  56. 24 0
      std/flash/media/AVResult.hx
  57. 3 0
      std/flash/media/AVStream.hx
  58. 10 0
      std/flash/media/StageVideoAvailabilityReason.hx
  59. 1 0
      std/flash/net/NetStream.hx
  60. 1 0
      std/flash/net/URLRequest.hx
  61. 3 0
      std/flash/net/drm/DRMManager.hx
  62. 6 0
      std/flash/net/drm/DRMReturnVoucherContext.hx
  63. 3 0
      std/flash/net/drm/DRMVoucher.hx
  64. 1 0
      std/flash/net/drm/VoucherAccessInfo.hx
  65. 10 0
      std/flash/system/ConnexionsClient.hx
  66. 2 2
      std/flash8/_std/Std.hx
  67. 0 4
      std/flash8/display/BitmapData.hx
  68. 0 4
      std/flash8/filters/BitmapFilter.hx
  69. 0 4
      std/flash8/geom/ColorTransform.hx
  70. 0 4
      std/flash8/geom/Matrix.hx
  71. 0 4
      std/flash8/geom/Point.hx
  72. 0 4
      std/flash8/geom/Rectangle.hx
  73. 0 4
      std/flash8/geom/Transform.hx
  74. 0 4
      std/flash8/net/FileReference.hx
  75. 0 4
      std/flash8/net/FileReferenceList.hx
  76. 0 4
      std/flash8/text/TextRenderer.hx
  77. 42 5
      std/haxe/Http.hx
  78. 17 453
      std/haxe/Json.hx
  79. 2 2
      std/haxe/Resource.hx
  80. 1 1
      std/haxe/Template.hx
  81. 43 12
      std/haxe/Timer.hx
  82. 1 1
      std/haxe/crypto/Base64.hx
  83. 1 0
      std/haxe/ds/Vector.hx
  84. 210 0
      std/haxe/format/JsonParser.hx
  85. 168 0
      std/haxe/format/JsonPrinter.hx
  86. 10 7
      std/haxe/io/Path.hx
  87. 0 136
      std/haxe/macro/Build.hx
  88. 31 0
      std/haxe/macro/Context.hx
  89. 1 0
      std/haxe/macro/Expr.hx
  90. 34 19
      std/haxe/macro/Printer.hx
  91. 11 1
      std/haxe/macro/Type.hx
  92. 1 1
      std/haxe/web/Dispatch.hx
  93. 20 8
      std/java/_std/Array.hx
  94. 2 2
      std/java/_std/Std.hx
  95. 5 0
      std/java/internal/StringExt.hx
  96. 6 3
      std/js/Boot.hx
  97. 9 0
      std/js/Browser.hx
  98. 3 3
      std/js/_std/Std.hx
  99. 47 0
      std/js/_std/haxe/Json.hx
  100. 3 3
      std/js/_std/haxe/ds/ObjectMap.hx

+ 3 - 0
.gitignore

@@ -7,6 +7,9 @@
 *.exe
 .*.swp
 
+/doc/hxclasses
+/doc/*.swf
+/doc/*.swc
 
 /version.ml
 /haxe

+ 16 - 12
.travis.yml

@@ -1,26 +1,30 @@
 language: node_js
 
 env:
-  - TARGET=macro
-  - TARGET=neko
-  - TARGET=js
-  - TARGET=php
-  - TARGET=cpp
-  - TARGET=flash9
-  - TARGET=flash8
-  - TARGET=as3
-  - TARGET=java
-  - TARGET=cs
+  global:
+    # SAUCE_USERNAME
+    - secure: SjyKefmjUEXi0IKHGGpcbLAajU0mLHONg8aA8LoY7Q9nAkSN6Aql+fzS38Boq7w1jWn+2FOpr+4jy0l6wVd/bftsF+huFfYpFJmdh8BlKmE0K71zZAral0H1c7YxkuQpPiJCIFGXqtkvev7SWTy0z31u7kuuQeEyW27boXe5cDA=
+    # SAUCE_ACCESS_KEY
+    - secure: sUvWUjCyPuWht4seNa4f2VG9DkvXkhZyLZfjJO9TUAHB2JndS16E2j/qrvKEjycyH6w8tU/B9vnjDRvvGrYXxEXcBEwsJVfkorFnRl9uwGCGIYrzjMhssEl3fMYZK7P304f+gAp5ULrDBX2gIaKeSa8lUNRtz2PsZOieE4kMdhk=
+  matrix:
+    - TARGET=macro
+    - TARGET=neko
+    - TARGET=js
+    - TARGET=php
+    - TARGET=cpp
+    - TARGET=flash9
+    - TARGET=flash8
+    - TARGET=as3
+    - TARGET=java
+    - TARGET=cs
 
 matrix:
   allow_failures:
     - env: TARGET=flash8
-    - env: TARGET=as3
     - env: TARGET=java
     - env: TARGET=cs
 
 before_install:
-  - export TRAVIS_BUILD_DIR=$(pwd) #tmp fix, see https://github.com/travis-ci/travis-build/pull/182
   - sudo apt-get update
   - sudo apt-get install ocaml zlib1g-dev libgc-dev -y
   - git clone https://github.com/HaxeFoundation/neko.git ~/neko && cd ~/neko && make && sudo make install && cd $TRAVIS_BUILD_DIR

+ 2 - 2
Makefile

@@ -96,7 +96,7 @@ install_tools: tools
 	chmod a+rx $(INSTALL_DIR)/bin/haxelib $(INSTALL_DIR)/bin/haxedoc
 
 uninstall:
-	rm -rf $(INSTALL_DIR)/bin/haxe $(INSTALL_DIR)/bin/haxelib $(INSTALL_DIR)/lib/haxe
+	rm -rf $(INSTALL_DIR)/bin/haxe $(INSTALL_DIR)/bin/haxelib $(INSTALL_DIR)/lib/haxe $(INSTALL_DIR)/bin/haxedoc
 
 export:
 	cp haxe*.exe doc/CHANGES.txt $(EXPORT)
@@ -172,7 +172,7 @@ clean_libs:
 	make -C libs/ttflib clean
 
 clean_haxe:
-	rm -f $(MODULES:=.obj) $(MODULES:=.o) $(MODULES:=.cmx) $(MODULES:=.cmi) lexer.ml
+	rm -f $(MODULES:=.obj) $(MODULES:=.o) $(MODULES:=.cmx) $(MODULES:=.cmi) lexer.ml haxe.exe
 
 clean_tools:
 	rm -f $(OUTPUT) haxelib haxedoc

+ 2 - 0
ast.ml

@@ -30,6 +30,7 @@ module Meta = struct
 	type strict_meta =
 		| Abstract
 		| Access
+		| Accessor
 		| Allow
 		| Annotation
 		| ArrayAccess
@@ -70,6 +71,7 @@ module Meta = struct
 		| FunctionCode
 		| FunctionTailCode
 		| Generic
+		| GenericBuild
 		| Getter
 		| Hack
 		| HaxeGeneric

+ 102 - 49
codegen.ml

@@ -89,17 +89,21 @@ let rec has_properties c =
 		match f.cf_kind with
 		| Var { v_read = AccCall } -> true
 		| Var { v_write = AccCall } -> true
+		| _ when Meta.has Meta.Accessor f.cf_meta -> true
 		| _ -> false
 	) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
 
 let get_properties fields =
 	List.fold_left (fun acc f ->
-		let acc = (match f.cf_kind with
-		| Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
-		| _ -> acc) in
-		match f.cf_kind with
-		| Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
-		| _ -> acc
+		if Meta.has Meta.Accessor f.cf_meta then
+			(f.cf_name, f.cf_name) :: acc
+		else
+			let acc = (match f.cf_kind with
+			| Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
+			| _ -> acc) in
+			match f.cf_kind with
+			| Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
+			| _ -> acc
 	) [] fields
 
 let add_property_field com c =
@@ -222,16 +226,19 @@ let make_generic ctx ps pt p =
 	in
 	let name =
 		String.concat "_" (List.map2 (fun (s,_) t ->
-			let path = (match follow t with
-				| TInst (ct,_) -> ct.cl_path
-				| TEnum (e,_) -> e.e_path
-				| TAbstract (a,_) when Meta.has Meta.RuntimeValue a.a_meta -> a.a_path
+			let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
+			let rec loop top t = match follow t with
+				| TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl)
+				| TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl)
+				| TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl)
+				| _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *)
 				| TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
 				| t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
-			) in
-			match path with
-			| [] , name -> name
-			| l , name -> String.concat "_" l ^ "_" ^ name
+			and loop_tl tl = match tl with
+				| [] -> ""
+				| tl -> "_" ^ String.concat "_" (List.map (loop false) tl)
+			in
+			loop true t
 		) ps pt)
 	in
 	{
@@ -395,9 +402,9 @@ let rec build_generic ctx c p tl =
 		cg.cl_kind <- KGenericInstance (c,tl);
 		cg.cl_interface <- c.cl_interface;
 		cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with
+			| _, Some c, _ -> Some (build_field c)
 			| Some ctor, _, _ -> Some ctor
 			| None, None, None -> None
-			| None, Some c, _ -> Some (build_field c)
 			| _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
 		);
 		cg.cl_implements <- List.map (fun (i,tl) ->
@@ -507,19 +514,22 @@ let build_metadata com t =
 (* -------------------------------------------------------------------------- *)
 (* MACRO TYPE *)
 
+let get_macro_path e args p =
+	let rec loop e =
+		match fst e with
+		| EField (e,f) -> f :: loop e
+		| EConst (Ident i) -> [i]
+		| _ -> error "Invalid macro call" p
+	in
+	(match loop e with
+	| meth :: cl :: path -> (List.rev path,cl), meth, args
+	| _ -> error "Invalid macro call" p)
+
 let build_macro_type ctx pl p =
 	let path, field, args = (match pl with
 		| [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
 		| [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
-			let rec loop e =
-				match fst e with
-				| EField (e,f) -> f :: loop e
-				| EConst (Ident i) -> [i]
-				| _ -> error "Invalid macro call" p
-			in
-			(match loop e with
-			| meth :: cl :: path -> (List.rev path,cl), meth, args
-			| _ -> error "Invalid macro call" p)
+			get_macro_path e args p
 		| _ ->
 			error "MacroType require a single expression call parameter" p
 	) in
@@ -531,6 +541,21 @@ let build_macro_type ctx pl p =
 	ctx.ret <- old;
 	t
 
+let build_macro_build ctx c pl cfl p =
+	let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
+		| _,[ECall(e,args),_],_ -> get_macro_path e args p
+		| _ -> assert false
+	in
+	let old = ctx.ret,ctx.g.get_build_infos in
+	ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl));
+	let t = (match ctx.g.do_macro ctx MMacroType path field args p with
+		| None -> mk_mono()
+		| Some _ -> ctx.ret
+	) in
+	ctx.ret <- fst old;
+	ctx.g.get_build_infos <- snd old;
+	t
+
 (* -------------------------------------------------------------------------- *)
 (* API EVENTS *)
 
@@ -538,26 +563,24 @@ let build_instance ctx mtype p =
 	match mtype with
 	| TClassDecl c ->
 		if ctx.pass > PBuildClass then c.cl_build();
+		let build f s =
+			let r = exc_protect ctx (fun r ->
+				let t = mk_mono() in
+				r := (fun() -> t);
+				unify_raise ctx (f()) t p;
+				t
+			) s in
+			delay ctx PForce (fun() -> ignore ((!r)()));
+			TLazy r
+		in
 		let ft = (fun pl ->
 			match c.cl_kind with
 			| KGeneric ->
-				let r = exc_protect ctx (fun r ->
-					let t = mk_mono() in
-					r := (fun() -> t);
-					unify_raise ctx (build_generic ctx c p pl) t p;
-					t
-				) "build_generic" in
-				delay ctx PForce (fun() -> ignore ((!r)()));
-				TLazy r
+				build (fun () -> build_generic ctx c p pl) "build_generic"
 			| KMacroType ->
-				let r = exc_protect ctx (fun r ->
-					let t = mk_mono() in
-					r := (fun() -> t);
-					unify_raise ctx (build_macro_type ctx pl p) t p;
-					t
-				) "macro_type" in
-				delay ctx PForce (fun() -> ignore ((!r)()));
-				TLazy r
+				build (fun () -> build_macro_type ctx pl p) "macro_type"
+			| KGenericBuild cfl ->
+				build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
 			| _ ->
 				TInst (c,pl)
 		) in
@@ -610,15 +633,35 @@ module Abstract = struct
 	let find_from ab pl a b = List.find (Type.unify_from_field ab pl a b) ab.a_from
 
 	let cast_stack = ref []
-
-	let get_underlying_type a pl =
+	let underlying_type_stack = ref []
+
+	let rec get_underlying_type a pl =
+		let maybe_recurse t =
+			underlying_type_stack := a :: !underlying_type_stack;
+			let t = match follow t with
+				| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
+					if List.mem a !underlying_type_stack then begin
+						let s = String.concat " -> " (List.map (fun a -> s_type_path a.a_path) (List.rev (a :: !underlying_type_stack))) in
+						(* technically this should be done at type declaration level *)
+						error ("Abstract chain detected: " ^ s) a.a_pos
+					end;
+					get_underlying_type a tl
+				| _ ->
+					t
+			in
+			underlying_type_stack := List.tl !underlying_type_stack;
+			t
+		in
 		try
 			if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
 			let m = mk_mono() in
 			let _ = find_to a pl m in
-			follow m
+			maybe_recurse (follow m)
 		with Not_found ->
-			apply_params a.a_types pl a.a_this
+			if Meta.has Meta.CoreType a.a_meta then
+				t_dynamic
+			else
+				maybe_recurse (apply_params a.a_types pl a.a_this)
 
 	let make_static_call ctx c cf a pl args t p =
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
@@ -684,10 +727,21 @@ module Abstract = struct
 
 	let find_multitype_specialization a pl p =
 		let m = mk_mono() in
-		let at = apply_params a.a_types pl a.a_this in
+		let tl = match Meta.get Meta.MultiType a.a_meta with
+			| _,[],_ -> pl
+			| _,el,_ ->
+				let relevant = Hashtbl.create 0 in
+				List.iter (fun e -> match fst e with
+					| EConst(Ident s) -> Hashtbl.replace relevant s true
+					| _ -> error "Type parameter expected" (pos e)
+				) el;
+				let tl = List.map2 (fun (n,_) t -> if Hashtbl.mem relevant n || not (has_mono t) then t else t_dynamic) a.a_types pl in
+				tl
+		in
 		let _,cfo =
-			try find_to a pl m
+			try find_to a tl m
 			with Not_found ->
+				let at = apply_params a.a_types pl a.a_this in
 				let st = s_type (print_context()) at in
 				if has_mono at then
 					error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
@@ -1141,10 +1195,9 @@ let set_default ctx a c p =
 	mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p
 
 let bytes_serialize data =
-	let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:" in
+	let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
 	let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
-	let str = Base64.str_encode ~tbl data in
-	"s" ^ string_of_int (String.length str) ^ ":" ^ str
+	Base64.str_encode ~tbl data
 
 (*
 	Tells if the constructor might be called without any issue whatever its parameters

+ 32 - 2
common.ml

@@ -220,6 +220,7 @@ module Define = struct
 		| SwfPreloaderFrame
 		| SwfProtected
 		| SwfScriptTimeout
+		| SwfUseDoAbc
 		| Sys
 		| Unsafe
 		| UseNekoc
@@ -289,6 +290,7 @@ module Define = struct
 		| SwfPreloaderFrame -> ("swf_preloader_frame", "Insert empty first frame in swf")
 		| SwfProtected -> ("swf_protected","Compile Haxe private as protected in the SWF instead of public")
 		| SwfScriptTimeout -> ("swf_script_timeout", "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)")
+		| SwfUseDoAbc -> ("swf_use_doabc", "Use DoAbc swf-tag instead of DoAbcDefine")
 		| Sys -> ("sys","Defined for all system platforms")
 		| Unsafe -> ("unsafe","Allow unsafe code when targeting C#")
 		| UseNekoc -> ("use_nekoc","Use nekoc compiler instead of internal one")
@@ -320,6 +322,7 @@ module MetaInfo = struct
 	let to_string = function
 		| Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]])
 		| Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]])
+		| Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;Internal])
 		| Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]])
 		| Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass])
 		| ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]])
@@ -360,6 +363,7 @@ module MetaInfo = struct
 		| FunctionCode -> ":functionCode",("",[Platform Cpp])
 		| FunctionTailCode -> ":functionTailCode",("",[Platform Cpp])
 		| Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]])
+		| GenericBuild -> ":genericBuild",("Builds instances of a type using the specified macro",[UsedOn TClass])
 		| Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
 		| Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass])
 		| HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
@@ -381,7 +385,7 @@ module MetaInfo = struct
 		| Macro -> ":macro",("(deprecated)",[])
 		| MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[Internal])
 		| MergeBlock -> ":mergeBlock",("Internally used by typer to mark block that should be merged into the outer scope",[Internal])
-		| MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract])
+		| MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"])
 		| Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]])
 		| NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum]])
 		| NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
@@ -732,7 +736,33 @@ let flash_versions = List.map (fun v ->
 	let maj = int_of_float v in
 	let min = int_of_float (mod_float (v *. 10.) 10.) in
 	v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min)
-) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8]
+) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8;11.9;12.0;12.1;12.2;12.3;12.4;12.5]
+
+let flash_version_tag = function
+	| 6. -> 6
+	| 7. -> 7
+	| 8. -> 8
+	| 9. -> 9
+	| 10. | 10.1 -> 10
+	| 10.2 -> 11
+	| 10.3 -> 12
+	| 11. -> 13
+	| 11.1 -> 14
+	| 11.2 -> 15
+	| 11.3 -> 16
+	| 11.4 -> 17
+	| 11.5 -> 18
+	| 11.6 -> 19
+	| 11.7 -> 20
+	| 11.8 -> 21
+	| 11.9 -> 22
+	| 12.0 -> 23
+	| 12.1 -> 24
+	| 12.2 -> 25
+	| 12.3 -> 26
+	| 12.4 -> 27
+	| 12.5 -> 28
+	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
 
 let raw_defined ctx v =
 	PMap.mem v ctx.defines

+ 45 - 5
dce.ml

@@ -62,6 +62,10 @@ let keep_whole_class dce c =
 		| { cl_path = [],"Array" } -> not (dce.com.platform = Js)
 		| _ -> false)
 
+let keep_whole_enum dce en =
+	Meta.has Meta.Keep en.e_meta
+	|| not (dce.full || is_std_file dce en.e_module.m_extra.m_file || has_meta Meta.Dce en.e_meta)
+
 (* check if a field is kept *)
 let keep_field dce cf =
 	Meta.has Meta.Keep cf.cf_meta
@@ -157,7 +161,11 @@ and mark_t dce p t =
 			mark_enum dce e;
 			List.iter (mark_t dce p) pl
 		| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
-			mark_t dce p (snd (Codegen.Abstract.find_multitype_specialization a pl p))
+			begin try
+				mark_t dce p (snd (Codegen.Abstract.find_multitype_specialization a pl p))
+			with Typecore.Error _ ->
+				()
+			end
 		| TAbstract(a,pl) ->
 			mark_abstract dce a;
 			List.iter (mark_t dce p) pl
@@ -213,8 +221,11 @@ let rec to_string dce t = match t with
 			dce.ts_stack <- t :: dce.ts_stack;
 			to_string dce (apply_params tt.t_types tl tt.t_type)
 		end
-	| TAbstract(a,tl) ->
-		to_string dce (Codegen.Abstract.get_underlying_type a tl)
+	| TAbstract({a_impl = Some c} as a,tl) ->
+		if Meta.has Meta.CoreType a.a_meta then
+			field dce c "toString" false
+		else
+			to_string dce (Codegen.Abstract.get_underlying_type a tl)
 	| TMono r ->
 		(match !r with
 		| Some t -> to_string dce t
@@ -226,7 +237,7 @@ let rec to_string dce t = match t with
 			()
 		else
 			to_string dce t
-	| TEnum _ | TFun _ | TAnon _ ->
+	| TEnum _ | TFun _ | TAnon _ | TAbstract({a_impl = None},_) ->
 		(* if we to_string these it does not imply that we need all its sub-types *)
 		()
 
@@ -403,6 +414,8 @@ let run com main full =
 				| Some cf -> loop false cf
 				| None -> ()
 			end
+		| TEnumDecl en when keep_whole_enum dce en ->
+			mark_enum dce en
 		| _ ->
 			()
 	) com.types;
@@ -440,12 +453,38 @@ let run com main full =
 		| (TClassDecl c) as mt :: l when keep_whole_class dce c ->
 			loop (mt :: acc) l
 		| (TClassDecl c) as mt :: l ->
+			let check_property cf stat =
+				let add_accessor_metadata cf =
+					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],c.cl_pos) :: cf.cf_meta
+				in
+				begin match cf.cf_kind with
+				| Var {v_read = AccCall} ->
+					begin try
+						add_accessor_metadata (PMap.find ("get_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
+					with Not_found ->
+						()
+					end
+				| _ ->
+					()
+				end;
+				begin match cf.cf_kind with
+				| Var {v_write = AccCall} ->
+					begin try
+						add_accessor_metadata (PMap.find ("set_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
+					with Not_found ->
+						()
+					end
+				| _ ->
+					()
+				end;
+			in
 			(* add :keep so subsequent filter calls do not process class fields again *)
 			c.cl_meta <- (Meta.Keep,[],c.cl_pos) :: c.cl_meta;
  			c.cl_ordered_statics <- List.filter (fun cf ->
 				let b = keep_field dce cf in
 				if not b then begin
 					if dce.debug then print_endline ("[DCE] Removed field " ^ (s_type_path c.cl_path) ^ "." ^ (cf.cf_name));
+					check_property cf true;
 					c.cl_statics <- PMap.remove cf.cf_name c.cl_statics;
 				end;
 				b
@@ -454,6 +493,7 @@ let run com main full =
 				let b = keep_field dce cf in
 				if not b then begin
 					if dce.debug then print_endline ("[DCE] Removed field " ^ (s_type_path c.cl_path) ^ "." ^ (cf.cf_name));
+					check_property cf false;
 					c.cl_fields <- PMap.remove cf.cf_name c.cl_fields;
 				end;
 				b
@@ -470,7 +510,7 @@ let run com main full =
 					if dce.debug then print_endline ("[DCE] Removed class " ^ (s_type_path c.cl_path));
 					loop acc l)
 			end
- 		| (TEnumDecl e) as mt :: l when Meta.has Meta.Used e.e_meta || Meta.has Meta.Keep e.e_meta || e.e_extern || not (dce.full || is_std_file dce e.e_module.m_extra.m_file || has_meta Meta.Dce e.e_meta) ->
+ 		| (TEnumDecl en) as mt :: l when Meta.has Meta.Used en.e_meta || en.e_extern || keep_whole_enum dce en ->
 			loop (mt :: acc) l
 		| TEnumDecl e :: l ->
 			if dce.debug then print_endline ("[DCE] Removed enum " ^ (s_type_path e.e_path));

+ 40 - 18
doc/CHANGES.txt

@@ -1,42 +1,64 @@
 2013-??-??: 3.1.0
+
+	New features:
+
 	all : allowed null-patterns in pattern matching
-	all : optimized pattern matching output
 	all : allowed extractors in pattern matching using => syntax
-	all : added length field to BytesBuffer, BytesOutput, BytesInput and StringBuf
-	all : evaluate conditional expressions in @:require
-	all : allowed (expr : type) syntax (ECheckType)
-	all : support abstract types in haxe.rtti.XmlParser
 	all : allowed extending generic type parameters
-	all : added EnumValue.match
-	all : added Std.instance
-	all : allowed recursive type parameter constraints
+	all : allowed (expr : type) syntax (ECheckType)
 	all : allowed @:enum and @:forward on abstracts
-	all : improved support of custom @:coreType abstracts
 	all : allowed using abstracts as static extension
 	all : allowed Class.new
-	all : inlining a parameter which has side effects will not remove it even if not used
-	all : implemented constraints check on enum and enum field type parameters
-	all : fixed memory leak in compilation server and optimized caching in general
+	all : added EnumValue.match
+	all : allow multiple structural extension using { > T1, > T2, fields }
+	all : inline array and structure declarations if possible
+	cs : added -net-lib
+	js : added -D js-flatten
+
+	Standard Library:
+
+	all : support abstract types in haxe.rtti.XmlParser
+	all : added Std.instance
+	all : added length field to BytesBuffer, BytesOutput, BytesInput and StringBuf
 	all : added UInt for all targets
 	all : added Array.indexOf and Array.lastIndexOf
 	all : added haxe.xml.Printer
 	all : added haxe.Int32 as abstract type
+	all : added haxe.format.JsonParser/Printer
+
+	General improvements and optimizations:
+
+	all : optimized pattern matching output
+	all : allowed recursive type parameter constraints
+	all : improved support of custom @:coreType abstracts
+	all : evaluate conditional expressions in @:require
 	all : improved inline constructors by detecting more cases where it can be applied
-	all : allow multiple structural extension using { > T1, > T2, fields }
-	js : window and console are reserved words. Access them with __js__ instead of untyped.
-	js : added -D js-flatten
 	js : improved inlining
 	js : always use JSON extern (compile with -D old-browser to disable)
 	cpp : improved side-effect detection
-	cs : added -net-lib
+
+	Bugfixes:
+
+	all : inlining a parameter which has side effects will not remove it even if not used
+	all : implemented constraints check on enum and enum field type parameters
+	all : fixed memory leak in compilation server and optimized caching in general
+	all : fixed issue with invalid lowercase class name in Windows completion
+	js : window and console are reserved words. Access them with __js__ instead of untyped.
+	flash : fixed font embedding with UTF8 chars
+	flash : give error if non-nullable basic types are skipped in a call
+
+	Macro features and changes:
+
 	macro : add Context.onAfterGenerate
+	macro : add Context.typeExpr
+	macro : add Context.getExpectedType
 	macro : allowed $v{(c:Float|Int|String)}
 	macro : resolve error line number in external files
 	macro : rewrote macros used as static extension
 	macro : exposed typed AST
+	macro : added @:genericBuild
 	macro : [breaking] first argument of ComplexType.TExtend is now Array<TypePath> instead of TypePath
-	flash : fixed font embedding with UTF8 chars
-	flash : give error if non-nullable basic types are skipped in a call
+	macro : improved expression printing
 
 2013-09-25: 3.0.1
 	all : minor DCE bug fix

+ 1 - 1
doc/extract.hxml

@@ -1,6 +1,6 @@
 -debug
 -swf-lib library.swf
 -swf test.swf
--swf-version 11.7
+-swf-version 11.8
 --macro patchTypes("../doc/extract.patch")
 --gen-hx-classes

+ 4 - 2
doc/extract.patch

@@ -879,7 +879,7 @@ flash.globalization.StringTools.lastOperationStatus : LastOperationStatus;
 @:require(flash10_2) flash.media.Microphone.enhancedOptions;
 @:require(flash10_2) static flash.media.Microphone.getEnhancedMicrophone;
 
-@:require(flash10_2) static flash.system.Capabilities.allowsFullScreen;
+@:require(flash11) static flash.system.Capabilities.allowsFullScreen;
 
 @:require(flash10_2) static flash.ui.Keyboard.AUDIO;
 @:require(flash10_2) static flash.ui.Keyboard.BACK;
@@ -1149,7 +1149,6 @@ flash.display.JPEGXREncoderOptions.colorSpace : BitmapEncodingColorSpace;
 
 // 11.4
 
-@:require(flash11_4) flash.display3D.Context3D.createRectangleTexture
 @:require(flash11_4) flash.display.BitmapData.copyPixelsToByteArray;
 
 @:require(flash11_4) flash.concurrent.Mutex;
@@ -1222,3 +1221,6 @@ flash.display3D.Context3D.$mipfilter : Context3DMipFilter;
 @:require(flash11_7) flash.system.AuthorizedFeaturesLoader.loadAuthorizedFeaturesFromData;
 
 
+@:require(flash11_8) flash.display.DisplayObjectContainer.stopAllMovieClips
+@:require(flash11_8) flash.display3D.Context3D.createRectangleTexture
+

+ 10 - 3
filters.ml

@@ -71,6 +71,8 @@ let handle_side_effects com gen_temp e =
 		match e.eexpr with
 		| TBlock el ->
 			{e with eexpr = TBlock (block loop el)}
+		| TCall({eexpr = TLocal v},_) when Meta.has Meta.Unbound v.v_meta ->
+			e
 		| TCall(e1,el) ->
 			let e1 = loop e1 in
 			{e with eexpr = TCall(e1,ordered_list el)}
@@ -119,13 +121,18 @@ let handle_side_effects com gen_temp e =
 		let rec no_side_effect e = match e.eexpr with
 			| TNew _ | TCall _ | TArrayDecl _ | TObjectDecl _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) ->
 				bind e;
+			| TIf _ | TTry _ | TSwitch _ ->
+				(* Technically these are not side-effects, but we have to move them out anyway because their blocks code have side-effects.
+				   This also probably improves readability of the generated code. We can ignore TWhile and TFor because their type is Void,
+				   so they could never appear in a place where side-effects matter. *)
+				bind e
 			| TBinop(op,e1,e2) when Optimizer.has_side_effect e1 || Optimizer.has_side_effect e2 ->
 				bind e;
 			| TConst _ | TLocal _ | TTypeExpr _ | TFunction _
 			| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) ->
 				e
 			| TBlock _ ->
-				loop e
+				bind e
 			| _ ->
 				Type.map_expr no_side_effect e
 		in
@@ -203,7 +210,7 @@ let promote_complex_rhs ctx e =
 		List.rev !r
 	and find e = match e.eexpr with
 		| TReturn (Some e1) -> loop (fun e -> {e with eexpr = TReturn (Some e)}) e1
-		| TBinop(OpAssign, ({eexpr = TLocal _ | TField _ | TArray _} as e1), e2) -> loop (fun er -> {e with eexpr = TBinop(OpAssign, e1, er)}) e2
+		| TBinop(OpAssign | OpAssignOp _ as op, ({eexpr = TLocal _ | TField _ | TArray _} as e1), e2) -> loop (fun er -> {e with eexpr = TBinop(op, e1, er)}) e2
 		| TBlock(el) -> {e with eexpr = TBlock (block el)}
 		| _ -> Type.map_expr find e
 	in
@@ -672,7 +679,7 @@ let rename_local_vars com e =
 	in
 	let save() =
 		let old = !vars in
-		if cfg.pf_unique_locals then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old)
+		if cfg.pf_unique_locals || not cfg.pf_locals_scope then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old)
 	in
 	let rename vars v =
 		let count = ref 1 in

+ 23 - 3
genas3.ml

@@ -119,6 +119,22 @@ let reserved =
 let s_ident n =
 	if Hashtbl.mem reserved n then "_" ^ n else n
 
+let valid_as3_ident s =
+	try
+		for i = 0 to String.length s - 1 do
+			match String.unsafe_get s i with
+			| 'a'..'z' | 'A'..'Z' | '$' | '_' -> ()
+			| '0'..'9' when i > 0 -> ()
+			| _ -> raise Exit
+		done;
+		true
+	with Exit ->
+		false
+
+let anon_field s =
+	let s = s_ident s in
+	if not (valid_as3_ident s) then "\"" ^ s ^ "\"" else s
+
 let rec create_dir acc = function
 	| [] -> ()
 	| d :: l ->
@@ -246,7 +262,7 @@ let rec type_str ctx t p =
 	| TInst (c,_) ->
 		(match c.cl_kind with
 		| KNormal | KGeneric | KGenericInstance _ | KAbstractImpl _ -> s_path ctx false c.cl_path p
-		| KTypeParameter _ | KExtension _ | KExpr _ | KMacroType -> "*")
+		| KTypeParameter _ | KExtension _ | KExpr _ | KMacroType | KGenericBuild _ -> "*")
 	| TFun _ ->
 		"Function"
 	| TMono r ->
@@ -696,7 +712,7 @@ and gen_expr ctx e =
 		handle_break();
 	| TObjectDecl fields ->
 		spr ctx "{ ";
-		concat ctx ", " (fun (f,e) -> print ctx "%s : " (s_ident f); gen_value ctx e) fields;
+		concat ctx ", " (fun (f,e) -> print ctx "%s : " (anon_field f); gen_value ctx e) fields;
 		spr ctx "}"
 	| TFor (v,it,e) ->
 		let handle_break = handle_break ctx e in
@@ -930,7 +946,11 @@ let generate_field ctx static f =
 			print ctx "]";
 		| _ -> ()
 	) f.cf_meta;
-	let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static) || f.cf_name = "resolve" || Ast.Meta.has Ast.Meta.Public f.cf_meta in
+	let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static)
+	    || f.cf_name = "resolve" || Ast.Meta.has Ast.Meta.Public f.cf_meta
+	    (* consider all abstract methods public to avoid issues with inlined private access *)
+	    || (match ctx.curclass.cl_kind with KAbstractImpl _ -> true | _ -> false)
+	in
 	let rights = (if static then "static " else "") ^ (if public then "public" else "protected") in
 	let p = ctx.curclass.cl_pos in
 	match f.cf_expr, f.cf_kind with

+ 11 - 3
gencommon.ml

@@ -2766,7 +2766,7 @@ struct
 				| TArray ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _) } as v) }, _) -> (* captured transformation *)
 					(match tparam_anon_acc with
 					| None -> Type.map_expr run e
-					| Some tparam_anon_acc -> tparam_anon_acc v e)
+          | Some tparam_anon_acc -> tparam_anon_acc v e)
         | TCall( { eexpr = TField(_, FEnum _) }, _ ) ->
           Type.map_expr run e
         (* if a TClosure is being call immediately, there's no need to convert it to a TClosure *)
@@ -2878,7 +2878,8 @@ struct
   						check_params v.v_type);
 					Hashtbl.add ignored v.v_id v;
 					ignore(Option.map traverse opt)
-        | TLocal { v_extra = Some(_ :: _,_) } -> ()
+        | TLocal { v_extra = Some( (_ :: _ as tparams),_) } ->
+          ()
         | TLocal(( { v_capture = true } ) as v) ->
           (if not (Hashtbl.mem ignored v.v_id || Hashtbl.mem ret v.v_id) then begin check_params v.v_type; Hashtbl.replace ret v.v_id expr end);
         | _ -> Type.iter traverse expr
@@ -3074,6 +3075,8 @@ struct
 				let original = apply_params types monos vt in
 				unify et original;
 
+        let monos = List.map (fun t -> apply_params types (List.map (fun _ -> t_dynamic) types) t) monos in
+
 				let same_cl t1 t2 = match follow t1, follow t2 with
 					| TInst(c,_), TInst(c2,_) -> c == c2
 					| _ -> false
@@ -6578,6 +6581,11 @@ struct
 
         let res2 = alloc_var "res2" basic.tint in
         let res2_local = mk_local res2 pos in
+        let gte2 = {
+          eexpr = TBinop(Ast.OpGte, res2_local, { eexpr = TConst(TInt(Int32.zero)); etype = basic.tint; epos = pos });
+          etype = basic.tbool;
+          epos = pos;
+        } in
 
         let block =
         [
@@ -6588,7 +6596,7 @@ struct
               Some({ eexpr = TBlock([
                 { eexpr = TVar( res2, Some(ctx.rcf_hash_function hash_local snd_hash)); etype = basic.tvoid; epos = pos };
                 {
-                  eexpr = TIf(gte, { eexpr = TBlock([
+                  eexpr = TIf(gte2, { eexpr = TBlock([
                     mk_splice snd_hash res2_local;
                     mk_splice snd_dynamics res2_local
                   ]); etype = t_dynamic; epos = pos }, None);

+ 28 - 8
gencpp.ml

@@ -287,7 +287,7 @@ let keyword_remap name =
 	| "BIG_ENDIAN" | "LITTLE_ENDIAN" | "assert" | "NULL" | "wchar_t" | "EOF"
 	| "bool" | "const_cast" | "dynamic_cast" | "explicit" | "export" | "mutable" | "namespace"
 	| "reinterpret_cast" | "static_cast" | "typeid" | "typename" | "virtual"
-	| "_Complex"
+	| "_Complex" | "INFINITY"
 	| "struct" -> "_" ^ name
 	| "asm" -> "_asm_"
 	| x -> x
@@ -1446,8 +1446,22 @@ and gen_expression ctx retval expression =
 		if ( cast <> "") then output ")";
 		if (op <> "=") then output ")";
 	in
+	let rec is_const_string_term expr =
+		match expr.eexpr with
+		| TConst( TString _ ) -> true
+		| TBinop (OpAdd,e1,e2) -> (is_const_string_term e1) && (is_const_string_term e2 )
+		| _ -> false
+	in
+	let rec combine_string_terms expr =
+		match expr.eexpr with
+		| TConst( TString s ) -> s
+		| TBinop (OpAdd,e1,e2) -> (combine_string_terms e1) ^ (combine_string_terms e2 )
+		| _ -> ""
+	in
 	let rec gen_bin_op op expr1 expr2 =
 		match op with
+		| Ast.OpAdd when (is_const_string_term expr1) && (is_const_string_term expr2) ->
+			output (str ((combine_string_terms expr1) ^ (combine_string_terms expr2)) )
 		| Ast.OpAssign -> ctx.ctx_assigning <- true;
 								gen_bin_op_string expr1 "=" expr2
 		| Ast.OpUShr ->
@@ -3033,16 +3047,20 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 			| Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field
 			| _ -> true)
 		in
-      let is_readable field =
-			(match field.cf_kind with | Var { v_read = AccNever } | Var { v_read = AccInline } -> false
+		let is_readable field =
+			(match field.cf_kind with
+			| Var { v_read = AccNever } when (is_extern_field field) -> false
+			| Var { v_read = AccInline } -> false
 			| Var _ when is_abstract_impl -> false
 			| _ -> true) in
-      let is_writable field =
-			(match field.cf_kind with | Var { v_write = AccNever } | Var { v_read = AccInline } -> false
+		let is_writable field =
+			(match field.cf_kind with
+			| Var { v_write = AccNever } when (is_extern_field field) -> false
+			| Var { v_read = AccInline } -> false
 			| Var _ when is_abstract_impl -> false
 			| _ -> true) in
 
-      let reflective field = not (Meta.has Meta.Unreflective field.cf_meta) in
+		let reflective field = not (Meta.has Meta.Unreflective field.cf_meta) in
 		let reflect_fields = List.filter reflective (statics_except_meta @ class_def.cl_ordered_fields) in
 		let reflect_writable = List.filter is_writable reflect_fields in
 		let reflect_readable = List.filter is_readable reflect_fields in
@@ -3527,12 +3545,13 @@ let write_resources common_ctx =
 	let idx = ref 0 in
 	Hashtbl.iter (fun _ data ->
 		resource_file#write_i ("static unsigned char __res_" ^ (string_of_int !idx) ^ "[] = {\n");
+		resource_file#write_i "0xff, 0xff, 0xff, 0xff,\n";
 		for i = 0 to String.length data - 1 do
 		let code = Char.code (String.unsafe_get data i) in
 			resource_file#write  (Printf.sprintf "0x%.2x, " code);
 			if ( (i mod 10) = 9) then resource_file#write "\n";
 		done;
-		resource_file#write ("};\n");
+		resource_file#write ("0x00 };\n");
 		incr idx;
 	) common_ctx.resources;
 
@@ -3542,7 +3561,7 @@ let write_resources common_ctx =
 	Hashtbl.iter (fun name data ->
 		resource_file#write_i
 			("{ " ^ (str name) ^ "," ^ (string_of_int (String.length data)) ^ "," ^
-				"__res_" ^ (string_of_int !idx) ^ " },\n");
+				"__res_" ^ (string_of_int !idx) ^ " + 4 },\n");
 		incr idx;
 	) common_ctx.resources;
 
@@ -3572,6 +3591,7 @@ let write_build_data common_ctx filename classes main_deps build_extra exe_name
 	in
 
 	output_string buildfile "<xml>\n";
+	output_string buildfile "<set name=\"HXCPP_API_LEVEL\" value=\"1\" />\n";
 	output_string buildfile "<files id=\"haxe\">\n";
 	output_string buildfile "<compilerflag value=\"-Iinclude\"/>\n";
 	List.iter add_class_to_buildfile classes;

+ 13 - 1
gencs.ml

@@ -402,6 +402,8 @@ struct
         | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("substring" as field) })) }, args )
         | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("substr" as field) })) }, args ) ->
           { e with eexpr = TCall(mk_static_field_access_infer string_ext field e.epos [], [run ef] @ (List.map run args)) }
+        | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("toString" as field) })) }, [] ) ->
+          run ef
         | TNew( { cl_path = ([], "String") }, [], [p] ) -> run p (* new String(myString) -> myString *)
 
         | TCast(expr, _) when is_int_float e.etype && not (is_int_float expr.etype) && not (is_null e.etype) ->
@@ -2293,7 +2295,17 @@ let configure gen =
   DynamicOperators.configure gen
     (DynamicOperators.abstract_implementation gen (fun e -> match e.eexpr with
       | TBinop (Ast.OpEq, e1, e2)
-      | TBinop (Ast.OpNotEq, e1, e2) -> should_handle_opeq e1.etype or should_handle_opeq e2.etype
+      | TBinop (Ast.OpNotEq, e1, e2) ->
+        (
+          (* dont touch (v == null) and (null == v) comparisons because they are handled by HardNullableSynf later *)
+          match e1.eexpr, e2.eexpr with
+          | TConst(TNull), _ when is_null_expr e2 ->
+            false
+          | _, TConst(TNull) when is_null_expr e1 ->
+            false
+          | _ ->
+            should_handle_opeq e1.etype or should_handle_opeq e2.etype
+        )
       | TBinop (Ast.OpAssignOp Ast.OpAdd, e1, e2) ->
         is_dynamic_expr e1 || is_null_expr e1 || is_string e.etype
       | TBinop (Ast.OpAdd, e1, e2) -> is_dynamic e1.etype or is_dynamic e2.etype or is_type_param e1.etype or is_type_param e2.etype or is_string e1.etype or is_string e2.etype or is_string e.etype

+ 4 - 0
genjava.ml

@@ -562,6 +562,8 @@ struct
             | _ ->
               { e with eexpr = TCall(run efield, List.map run args) }
           )
+        | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("toString" as field) })) }, [] ) ->
+          run ef
 
         | TCast(expr, m) when is_boxed_type e.etype ->
           (* let unboxed_type gen t tbyte tshort tchar tfloat = match follow t with *)
@@ -1899,6 +1901,8 @@ let configure gen =
   TArrayTransform.configure gen (TArrayTransform.default_implementation gen (
   fun e ->
     match e.eexpr with
+      | TArray ({ eexpr = TLocal { v_extra = Some( _ :: _, _) } }, _) -> (* captured transformation *)
+        false
       | TArray(e1, e2) ->
         ( match run_follow gen e1.etype with
           | TInst({ cl_path = (["java"], "NativeArray") }, _) -> false

+ 31 - 11
genjs.ml

@@ -404,6 +404,24 @@ let rec gen_call ctx e el in_value =
 		print ctx " instanceof ";
 		gen_value ctx t;
 		spr ctx ")";
+	| TLocal { v_name = "__typeof__" },  [o] ->
+		spr ctx "typeof(";
+		gen_value ctx o;
+		spr ctx ")";
+	| TLocal { v_name = "__strict_eq__" } , [x;y] ->
+		(* add extra parenthesis here because of operator precedence *)
+		spr ctx "((";
+		gen_value ctx x;
+		spr ctx ") === ";
+		gen_value ctx y;
+		spr ctx ")";
+	| TLocal { v_name = "__strict_neq__" } , [x;y] ->
+		(* add extra parenthesis here because of operator precedence *)
+		spr ctx "((";
+		gen_value ctx x;
+		spr ctx ") !== ";
+		gen_value ctx y;
+		spr ctx ")";
 	| TLocal ({v_name = "__define_feature__"}), [_;e] ->
 		gen_expr ctx e
 	| TLocal { v_name = "__feature__" }, { eexpr = TConst (TString f) } :: eif :: eelse ->
@@ -517,7 +535,7 @@ and gen_expr ctx e =
 	| TBlock el ->
 		print ctx "{";
 		let bend = open_block ctx in
-		List.iter (gen_block ctx) el;
+		List.iter (gen_block_element ctx) el;
 		bend();
 		newline ctx;
 		print ctx "}";
@@ -611,7 +629,7 @@ and gen_expr ctx e =
 		let bend = open_block ctx in
 		newline ctx;
 		print ctx "var %s = %s.next()" (ident v.v_name) it;
-		gen_block ctx e;
+		gen_block_element ctx e;
 		bend();
 		newline ctx;
 		spr ctx "}";
@@ -651,7 +669,7 @@ and gen_expr ctx e =
 					newline ctx;
 					print ctx "var %s = %s" v.v_name vname;
 				end;
-				gen_block ctx e;
+				gen_block_element ctx e;
 				if !else_block then begin
 					newline ctx;
 					print ctx "}";
@@ -666,7 +684,7 @@ and gen_expr ctx e =
 					newline ctx;
 					print ctx "var %s = %s" v.v_name vname;
 				end;
-				gen_block ctx e;
+				gen_block_element ctx e;
 				bend();
 				newline ctx;
 				spr ctx "} else ";
@@ -693,7 +711,7 @@ and gen_expr ctx e =
 					spr ctx ":"
 			) el;
 			let bend = open_block ctx in
-			gen_block ctx e2;
+			gen_block_element ctx e2;
 			if not (has_return e2) then begin
 				newline ctx;
 				print ctx "break";
@@ -706,7 +724,7 @@ and gen_expr ctx e =
 		| Some e ->
 			spr ctx "default:";
 			let bend = open_block ctx in
-			gen_block ctx e;
+			gen_block_element ctx e;
 			bend();
 			newline ctx;
 		);
@@ -721,17 +739,19 @@ and gen_expr ctx e =
 		spr ctx ")"
 
 
-and gen_block ?(after=false) ctx e =
+and gen_block_element ?(after=false) ctx e =
 	match e.eexpr with
 	| TBlock el ->
-		List.iter (gen_block ~after ctx) el
+		List.iter (gen_block_element ~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
+			gen_block_element ~after ctx eif
 		else (match eelse with
 			| [] -> ()
-			| [e] -> gen_block ~after ctx e
+			| [e] -> gen_block_element ~after ctx e
 			| _ -> assert false)
+	| TFunction _ ->
+		gen_block_element ~after ctx (mk (TParenthesis e) e.etype e.epos)
 	| _ ->
 		if not after then newline ctx;
 		gen_expr ctx e;
@@ -1250,7 +1270,7 @@ let generate com =
 		print ctx "function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $fid++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }";
 		newline ctx;
 	end;
-	List.iter (gen_block ~after:true ctx) (List.rev ctx.inits);
+	List.iter (gen_block_element ~after:true ctx) (List.rev ctx.inits);
 	List.iter (generate_static ctx) (List.rev ctx.statics);
 	(match com.main with
 	| None -> ()

+ 31 - 28
genswf.ml

@@ -525,26 +525,6 @@ let tag ?(ext=false) d = {
 	tdata = d;
 }
 
-let swf_ver = function
-	| 6. -> 6
-	| 7. -> 7
-	| 8. -> 8
-	| 9. -> 9
-	| 10. | 10.1 -> 10
-	| 10.2 -> 11
-	| 10.3 -> 12
-	| 11. -> 13
-	| 11.1 -> 14
-	| 11.2 -> 15
-	| 11.3 -> 16
-	| 11.4 -> 17
-	| 11.5 -> 18
-	| 11.6 -> 19
-	| 11.7 -> 20
-	| 11.8 -> 21
-	| 11.9 -> 22
-	| v -> failwith ("Invalid SWF version " ^ float_repres v)
-
 let convert_header com (w,h,fps,bg) =
 	let high = (max w h) * 20 in
 	let rec loop b =
@@ -552,7 +532,7 @@ let convert_header com (w,h,fps,bg) =
 	in
 	let bits = loop 0 in
 	{
-		h_version = swf_ver com.flash_version;
+		h_version = Common.flash_version_tag com.flash_version;
 		h_size = {
 			rect_nbits = bits + 1;
 			left = 0;
@@ -588,7 +568,8 @@ let build_dependencies t =
 			(match c.cl_kind with KTypeParameter _ -> () | _ -> add_path c.cl_path DKType);
 			List.iter (add_type_rec (t::l)) pl;
 		| TAbstract (a,pl) ->
-			add_path a.a_path DKType;
+			if Meta.has Meta.CoreType a.a_meta then
+				add_path a.a_path DKType;
 			List.iter (add_type_rec (t::l)) pl;
 		| TFun (pl,t2) ->
 			List.iter (fun (_,_,t2) -> add_type_rec (t::l) t2) pl;
@@ -796,6 +777,8 @@ let detect_format data p =
 	| _ ->
 		error "Unknown file format" p
 
+open TTFData
+
 let build_swf9 com file swc =
 	let boot_name = if swc <> None || Common.defined com Define.HaxeBoot then "haxe" else "boot_" ^ (String.sub (Digest.to_hex (Digest.string (Filename.basename file))) 0 4) in
 	let code = Genswf9.generate com boot_name in
@@ -820,7 +803,7 @@ let build_swf9 com file swc =
 				hls_fields = [|f|];
 			}
 		) code in
-		[tag (TActionScript3 (None,As3hlparse.flatten inits))]
+		[tag (TActionScript3 ((if Common.defined com Define.SwfUseDoAbc then Some(1,boot_name) else None), As3hlparse.flatten inits))]
 	) in
 	let cid = ref 0 in
 	let classes = ref [{ f9_cid = None; f9_classname = boot_name }] in
@@ -846,11 +829,31 @@ let build_swf9 com file swc =
 					let ch = try open_in_bin file with _ -> error "File not found" p in
 					let ttf = try TTFParser.parse ch with e -> error ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in
 					close_in ch;
-					let range_str = match args with
-						| [EConst (String str),_] -> str
-						| _ -> ""
+					let get_string e = match fst e with
+						| EConst (String s) -> Some s
+						| _ -> raise Not_found
 					in
-					let ttf_swf = TTFSwfWriter.to_swf ttf range_str in
+					let ttf_config = {
+						ttfc_range_str = "";
+						ttfc_font_name = None;
+					} in
+					begin match args with
+						| (EConst (String str),_) :: _ -> ttf_config.ttfc_range_str <- str;
+						| _ -> ()
+					end;
+					begin match args with
+						| _ :: [e] ->
+							begin match fst e with
+								| EObjectDecl fl ->
+									begin try ttf_config.ttfc_font_name <- get_string (List.assoc "fontName" fl)
+									with Not_found -> () end
+								| _ ->
+									()
+							end
+						| _ ->
+							()
+					end;
+					let ttf_swf = TTFSwfWriter.to_swf ttf ttf_config in
 					let ch = IO.output_string () in
 					let b = IO.output_bits ch in
 					TTFSwfWriter.write_font2 ch b ttf_swf;
@@ -1031,7 +1034,7 @@ let build_swf9 com file swc =
 
 let merge com file priority (h1,tags1) (h2,tags2) =
   (* prioritize header+bgcolor for first swf *)
-	let header = if priority then { h2 with h_version = max h2.h_version (swf_ver com.flash_version) } else h1 in
+	let header = if priority then { h2 with h_version = max h2.h_version (Common.flash_version_tag com.flash_version) } else h1 in
 	let tags1 = if priority then List.filter (function { tdata = TSetBgColor _ } -> false | _ -> true) tags1 else tags1 in
   (* remove unused tags *)
 	let use_stage = priority && Common.defined com Define.FlashUseStage in

+ 24 - 3
genswf9.ml

@@ -205,7 +205,7 @@ let rec follow_basic t =
 		t
 	| TType (t,tl) ->
 		follow_basic (apply_params t.t_types tl t.t_type)
-	| TAbstract (a,pl) when a.a_impl <> None ->
+	| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 		follow_basic (apply_params a.a_types pl a.a_this)
 	| _ -> t
 
@@ -1626,7 +1626,10 @@ and gen_binop ctx retval op e1 e2 t p =
 			let k1 = classify ctx e1.etype in
 			let k2 = classify ctx e2.etype in
 			(match k1, k2 with
-			| KInt, KInt | KUInt, KUInt | KInt, KUInt | KUInt, KInt -> write ctx (HOp iop)
+			| KInt, KInt | KUInt, KUInt | KInt, KUInt | KUInt, KInt ->
+				write ctx (HOp iop);
+				let ret = classify ctx t in
+				if ret <> KInt then coerce ctx ret
 			| _ ->
 				write ctx (HOp op);
 				(* add is a generic operation, so let's make sure we don't loose our type in the process *)
@@ -2031,7 +2034,24 @@ let generate_field_kind ctx f c stat =
 			hlv_value = HVNone;
 			hlv_const = false;
 		})
-
+		
+let check_constructor ctx c f =
+	(*
+		check that we don't assign a super Float var before we call super() : will result in NaN
+	*)
+	let rec loop e =
+		Type.iter loop e;
+		match e.eexpr with
+		| TCall ({ eexpr = TConst TSuper },_) -> raise Exit
+		| TBinop (OpAssign,{ eexpr = TField({ eexpr = TConst TThis },FInstance (cc,cf)) },_) when c != cc && (match classify ctx cf.cf_type with KFloat | KDynamic -> true | _ -> false) ->
+			error "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos
+		| _ -> ()
+	in
+	try
+		loop f.tf_expr
+	with Exit ->
+		()
+		
 let generate_class ctx c =
 	let name = type_path ctx c.cl_path in
 	ctx.cur_class <- c;
@@ -2054,6 +2074,7 @@ let generate_class ctx c =
 			| Some { eexpr = TFunction fdata } ->
 				let old = do_debug ctx f.cf_meta in
 				let m = generate_construct ctx fdata c in
+				check_constructor ctx c fdata;
 				old();
 				m
 			| _ -> assert false

+ 2 - 2
genxml.ml

@@ -339,7 +339,7 @@ let generate_type com t =
 		| None ->
 			n ^ " : " ^ stype t
 		| Some (Ident "null") ->
-			if is_null t then
+			if is_nullable (notnull t) then
 				"?" ^ n ^ " : " ^ stype (notnull t)
 			else
 				(* we have not found a default value stored in metadata, let's generate it *)
@@ -353,7 +353,7 @@ let generate_type com t =
 	let print_meta ml =
 		List.iter (fun (m,pl,_) ->
 			match m with
-			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed -> ()
+			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum -> ()
 			| _ ->
 			match pl with
 			| [] -> p "@%s " (fst (MetaInfo.to_string m))

+ 2 - 0
haxe.hxproj

@@ -134,6 +134,8 @@
     <hidden path="haxe.exe.manifest" />
     <hidden path="obj" />
     <hidden path="filters.obj" />
+    <hidden path="filters.cmi" />
+    <hidden path="filters.cmx" />
   </hiddenPaths>
   <!-- Executed before build -->
   <preBuildCommand>make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe</preBuildCommand>

+ 40 - 9
interp.ml

@@ -110,6 +110,7 @@ type extern_api = {
 	meta_patch : string -> string -> string option -> bool -> unit;
 	set_js_generator : (value -> unit) -> unit;
 	get_local_type : unit -> t option;
+	get_expected_type : unit -> t option;
 	get_local_method : unit -> string;
 	get_local_using : unit -> tclass list;
 	get_local_vars : unit -> (string, Type.tvar) PMap.t;
@@ -182,6 +183,7 @@ exception Continue
 exception Break of value
 exception Return of value
 exception Invalid_expr
+exception Sys_exit of int
 
 (* ---------------------------------------------------------------------- *)
 (* UTILS *)
@@ -263,7 +265,7 @@ let constants =
 	"constructs";"names";"superClass";"interfaces";"fields";"statics";"constructor";"init";"t";
 	"gid";"uid";"atime";"mtime";"ctime";"dev";"ino";"nlink";"rdev";"size";"mode";"pos";"len";
 	"binops";"unops";"from";"to";"array";"op";"isPostfix";"impl";
-	"id";"capture";"extra";"v";"ids";"vars";"en";"overrides"];
+	"id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status"];
 	h
 
 let h_get = hash "__get" and h_set = hash "__set"
@@ -326,7 +328,7 @@ let parse_float s =
 		if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else
 		match String.unsafe_get s i with
 		| ' ' when sp = i -> loop (sp + 1) (i + 1)
-		| '0'..'9' | '-' | 'e' | 'E' | '.' -> loop sp (i + 1)
+		| '0'..'9' | '-' | '+' | 'e' | 'E' | '.' -> loop sp (i + 1)
 		| _ -> String.sub s sp (i - sp)
 	in
 	float_of_string (loop 0 0)
@@ -1648,7 +1650,7 @@ let std_lib =
 		);
 		"sys_exit", Fun1 (fun code ->
 			if (get_ctx()).curapi.use_cache() then raise (Typecore.Fatal_error ("",Ast.null_pos));
-			exit (vint code);
+			raise (Sys_exit(vint code));
 		);
 		"sys_exists", Fun1 (fun file ->
 			VBool (Sys.file_exists (vstring file))
@@ -1774,7 +1776,6 @@ let std_lib =
 				incr pos;
 				if !pos >= p && !pos < p + l then UTF8.Buf.add_char buf c;
 			) (vstring s);
-			if !pos < p + l then error();
 			VString (UTF8.Buf.contents buf)
 		);
 		"utf8_get", Fun2 (fun s p ->
@@ -2400,6 +2401,12 @@ let macro_lib =
 				VNull
 			| _ -> error()
 		);
+        "get_resources", Fun0 (fun() ->
+			let res = (ccom()).resources in
+			let h = Hashtbl.create 0 in
+			Hashtbl.iter (fun n v -> Hashtbl.replace h (VString n) (VString v)) res;
+			enc_hash h
+		);
 		"local_module", Fun0 (fun() ->
 			let m = (get_ctx()).curapi.current_module() in
 			VString (Ast.s_type_path m.m_path);
@@ -2409,6 +2416,11 @@ let macro_lib =
 			| None -> VNull
 			| Some t -> encode_type t
 		);
+		"expected_type", Fun0 (fun() ->
+			match (get_ctx()).curapi.get_expected_type() with
+			| None -> VNull
+			| Some t -> encode_type t
+		);
 		"local_method", Fun0 (fun() ->
 			VString ((get_ctx()).curapi.get_local_method())
 		);
@@ -3248,7 +3260,7 @@ and call ctx vthis vfun pl p =
 	ctx.vthis <- vthis;
 	ctx.callstack <- { cpos = p; cthis = oldthis; cstack = stackpos; cenv = oldenv } :: ctx.callstack;
 	ctx.callsize <- oldsize + 1;
-	if oldsize > 400 then exc (VString "Stack overflow");
+	if oldsize > 600 then exc (VString "Stack overflow");
 	let ret = (try
 		(match vfun with
 		| VClosure (vl,f) ->
@@ -3521,6 +3533,7 @@ type enum_index =
 	| ITConstant
 	| IModuleType
 	| IFieldAccess
+	| IAnonStatus
 
 let enum_name = function
 	| IExpr -> "ExprDef"
@@ -3540,9 +3553,10 @@ let enum_name = function
 	| ITConstant -> "TConstant"
 	| IModuleType -> "ModuleType"
 	| IFieldAccess -> "FieldAccess"
+	| IAnonStatus -> "AnonStatus"
 
 let init ctx =
-	let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind;ITypedExpr;ITConstant;IModuleType;IFieldAccess] in
+	let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind;ITypedExpr;ITConstant;IModuleType;IFieldAccess;IAnonStatus] in
 	let get_enum_proto e =
 		match get_path ctx ["haxe";"macro";enum_name e] null_pos with
 		| VObject e ->
@@ -4278,7 +4292,8 @@ and encode_class_kind k =
 		| KGeneric -> 4, []
 		| KGenericInstance (cl, params) -> 5, [encode_clref cl; encode_tparams params]
 		| KMacroType -> 6, []
-		| KAbstractImpl a -> 7, [encode_ref a encode_tabstract (fun() -> s_type_path a.a_path)]
+		| KAbstractImpl a -> 7, [encode_abref a]
+		| KGenericBuild cfl -> 8, []
 	) in
 	enc_enum IClassKind tag pl
 
@@ -4311,8 +4326,21 @@ and encode_ttype t =
 and encode_tanon a =
 	enc_obj [
 		"fields", encode_pmap_array encode_cfield a.a_fields;
+		"status", encode_anon_status !(a.a_status);
 	]
 
+and encode_anon_status s =
+	let tag, pl = (match s with
+		| Closed -> 0, []
+		| Opened -> 1, []
+		| Type.Const -> 2, []
+		| Statics cl -> 3, [encode_clref cl]
+		| EnumStatics en -> 4, [encode_enref en]
+		| AbstractStatics ab -> 5, [encode_abref ab]
+	)
+	in
+	enc_enum IAnonStatus tag pl
+
 and encode_tparams pl =
 	enc_array (List.map encode_type pl)
 
@@ -4325,6 +4353,9 @@ and encode_enref en =
 and encode_cfref cf =
 	encode_ref cf encode_cfield (fun() -> cf.cf_name)
 
+and encode_abref ab =
+	encode_ref ab encode_tabstract (fun() -> s_type_path ab.a_path)
+
 and encode_type t =
 	let rec loop = function
 		| TMono r ->
@@ -4356,7 +4387,7 @@ and encode_type t =
 		| TLazy f ->
 			loop (!f())
 		| TAbstract (a, pl) ->
-			8, [encode_ref a encode_tabstract (fun() -> s_type_path a.a_path); encode_tparams pl]
+			8, [encode_abref a; encode_tparams pl]
 	in
 	let tag, pl = loop t in
 	enc_enum IType tag pl
@@ -4436,7 +4467,7 @@ and encode_module_type mt =
 		| TClassDecl c -> 0,[encode_clref c]
 		| TEnumDecl e -> 1,[encode_enref e]
 		| TTypeDecl t -> 2,[encode_ref t encode_ttype (fun () -> s_type_path t.t_path)]
-		| TAbstractDecl a -> 3,[encode_ref a encode_tabstract (fun () -> s_type_path a.a_path)]
+		| TAbstractDecl a -> 3,[encode_abref a]
 	in
 	enc_enum IModuleType tag pl
 

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit 87a41172b0afb34df37adfee2c07c1b561e4de63
+Subproject commit 296f0edfa9a73c37b1ddfaec878985cf0a22ba56

+ 10 - 1
main.ml

@@ -927,6 +927,7 @@ try
 	let force_typing = ref false in
 	let pre_compilation = ref [] in
 	let interp = ref false in
+	let swf_version = ref false in
 	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 10000.));
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";
@@ -1037,7 +1038,8 @@ try
 			Common.define_value com Define.Dce mode
 		),"[std|full|no] : set the dead code elimination mode");
 		("-swf-version",Arg.Float (fun v ->
-			com.flash_version <- v;
+			if not !swf_version || com.flash_version < v then com.flash_version <- v;
+			swf_version := true;
 		),"<version> : change the SWF version (6 to 10)");
 		("-swf-header",Arg.String (fun h ->
 			try
@@ -1270,6 +1272,10 @@ try
 		com.error <- error ctx;
 		com.main_class <- None;
 		let real = get_real_path (!Parser.resume_display).Ast.pfile in
+		(* try to fix issue on windows when get_real_path fails (8.3 DOS names disabled) *)
+		let real = (match List.rev (ExtString.String.nsplit real "\\") with
+		| file :: path when String.length file > 0 && file.[0] >= 'a' && file.[1] <= 'z' -> file.[0] <- char_of_int (int_of_char file.[0] - int_of_char 'a' + int_of_char 'A'); String.concat "\\" (List.rev (file :: path))
+		| _ -> real) in
 		classes := lookup_classes com real;
 		if !classes = [] then begin
 			if not (Sys.file_exists real) then failwith "Display file does not exist";
@@ -1535,6 +1541,9 @@ with
 				raise (Completion c)
 			| _ ->
 				error ctx ("Could not load module " ^ (Ast.s_type_path (p,c))) Ast.null_pos)
+	| Interp.Sys_exit i ->
+		ctx.flush();
+		exit i
 	| e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || !global_cache <> None with _ -> true) && not (is_debug_run()) ->
 		error ctx (Printexc.to_string e) Ast.null_pos
 

+ 88 - 64
matcher.ml

@@ -79,9 +79,10 @@ and pat = {
 }
 
 type out = {
-	o_pos : pos;
+	mutable o_pos : pos;
 	o_id : int;
-	o_default : bool;
+	o_catch_all : bool;
+	mutable o_num_paths : int;
 }
 
 type pat_vec = pat array * out
@@ -102,9 +103,8 @@ type matcher = {
 	dt_lut : dt DynArray.t;
 	dt_cache : (dt,int) Hashtbl.t;
 	mutable dt_count : int;
-	mutable outcomes : (pat list,out) PMap.t;
+	mutable outcomes : out list;
 	mutable toplevel_or : bool;
-	mutable used_paths : (int,bool) Hashtbl.t;
 	mutable has_extractor : bool;
 	mutable expr_map : (int,texpr * texpr option) PMap.t;
 }
@@ -128,18 +128,20 @@ let mk_st def t p = {
 	st_pos = p;
 }
 
-let mk_out mctx id e eg pl is_default p =
+let mk_out mctx id e eg is_catch_all p =
 	let out = {
 		o_pos = p;
 		o_id = id;
-		o_default = is_default;
+		o_catch_all = is_catch_all;
+		o_num_paths = 0;
 	} in
-	mctx.outcomes <- PMap.add pl out mctx.outcomes;
+	mctx.outcomes <- out :: mctx.outcomes;
 	mctx.expr_map <- PMap.add id (e,eg) mctx.expr_map;
 	out
 
-let clone_out mctx out pl p =
-	let out = {out with o_pos = p; } in
+let clone_out mctx out p =
+ 	let out = {out with o_pos = p; } in
+ 	mctx.outcomes <- out :: mctx.outcomes;
 	out
 
 let get_guard mctx id =
@@ -160,17 +162,9 @@ let mk_con cdef t p = {
 	c_pos = p;
 }
 
-let mk_con_pat cdef pl t p = {
-	p_def = PCon(mk_con cdef t p,pl);
-	p_type = t;
-	p_pos = p;
-}
+let mk_con_pat cdef pl t p = mk_pat (PCon(mk_con cdef t p,pl)) t p
 
-let mk_any t p = {
-	p_def = PAny;
-	p_type = t;
-	p_pos = p;
-}
+let mk_any t p = mk_pat PAny t p
 
 let any = mk_any t_dynamic Ast.null_pos
 
@@ -384,11 +378,7 @@ let to_pattern ctx e t =
 			begin match get_tuple_types t with
 			| Some tl ->
 				let pl = List.map (fun (_,_,t) -> mk_any t p) tl in
-				{
-					p_def = PTuple (Array.of_list pl);
-					p_pos = p;
-					p_type = t_dynamic;
-				}
+				mk_pat (PTuple (Array.of_list pl)) t_dynamic p
 			| None ->
 				mk_any t p
 			end
@@ -519,11 +509,7 @@ let to_pattern ctx e t =
 					with Invalid_argument _ ->
 						error ("Invalid number of arguments: expected " ^ (string_of_int (List.length tl)) ^ ", found " ^ (string_of_int (List.length el))) p
 					in
-					{
-						p_def = PTuple (Array.of_list pl);
-						p_pos = p;
-						p_type = t_dynamic;
-					}
+					mk_pat (PTuple (Array.of_list pl)) t_dynamic p
 				| _ ->
 					error ((s_type t) ^ " should be Array") p
 			end
@@ -535,12 +521,6 @@ let to_pattern ctx e t =
 			loop pctx (EBinop(OpOr,e1,(EBinop(OpOr,e2,e3),p2)),p) t
 		| EBinop(OpOr,e1,e2) ->
 			let old = pctx.pc_locals in
-			let rec dup t = match t with
-				| TMono r -> (match !r with
-					| None -> mk_mono()
-					| Some t -> Type.map dup t)
-				| _ -> Type.map dup t
-			in
 			let pat1 = loop pctx e1 t in
 			begin match pat1.p_def with
 				| PAny | PVar _ ->
@@ -579,9 +559,17 @@ let get_pattern_locals ctx e t =
 
 (* Match compilation *)
 
+let expr_eq e1 e2 = e1 == e2 || match e1.eexpr,e2.eexpr with
+	| TConst ct1,TConst ct2 ->
+		ct1 = ct2
+	| TField(_,FStatic(c1,cf1)),TField(_,FStatic(c2,cf2)) ->
+		c1 == c2 && cf1.cf_name = cf2.cf_name
+	| _ ->
+		false
+
 let unify_con con1 con2 = match con1.c_def,con2.c_def with
 	| CExpr e1, CExpr e2 ->
-		e1 == e2
+		expr_eq e1 e2
 	| CConst c1,CConst c2 ->
 		c1 = c2
 	| CEnum(e1,ef1),CEnum(e2,ef2) ->
@@ -616,15 +604,12 @@ let spec mctx con pmat =
 			()
 		| PAny | PVar _->
 			add (Array.append (Array.make a (mk_any (pv.(0).p_type) (pv.(0).p_pos))) (array_tl pv)) out
- 		| POr(pat1,pat2) ->
-			let tl = array_tl pv in
-			let out2 = clone_out mctx out [pat2] pat2.p_pos in
-			loop2 (Array.append [|pat1|] tl) out;
-			loop2 (Array.append [|pat2|] tl) out2;
 		| PBind(_,pat) ->
 			loop2 (Array.append [|pat|] (array_tl pv)) out
 		| PTuple tl ->
 			loop2 tl out
+ 		| POr _ ->
+			assert false
 	in
 	let rec loop pmat = match pmat with
 		| (pv,out) :: pl ->
@@ -646,15 +631,12 @@ let default mctx pmat =
 			()
 		| PAny | PVar _->
 			add (array_tl pv) out
- 		| POr(pat1,pat2) ->
-			let tl = array_tl pv in
-			let out2 = clone_out mctx out [pat2] pat2.p_pos in
-			loop2 (Array.append [|pat1|] tl) out;
-			loop2 (Array.append [|pat2|] tl) out2;
 		| PBind(_,pat) ->
 			loop2 (Array.append [|pat|] (array_tl pv)) out
 		| PTuple tl ->
 			loop2 tl out
+ 		| POr _ ->
+			assert false
 	in
  	let rec loop pmat = match pmat with
 		| (pv,out) :: pl ->
@@ -700,6 +682,48 @@ let swap_columns i (row : 'a list) : 'a list =
 	| _ ->
 		[]
 
+let expand_or mctx pmat =
+	let rec loop pmat = match pmat with
+		| (pv,out) :: pmat ->
+			let acc = ref [] in
+			let rec loop2 pv out = match pv.(0) with
+				| {p_def = POr(pat1,pat2)} ->
+					out.o_pos <- pat1.p_pos;
+					let out2 = clone_out mctx out pat2.p_pos in
+					let tl = array_tl pv in
+					loop2 (Array.append [|pat2|] tl) out2;
+					loop2 (Array.append [|pat1|] tl) out;
+				| {p_def = PBind(v,{p_def = POr(pat1,pat2)})} as pat ->
+					out.o_pos <- pat1.p_pos;
+					let out2 = clone_out mctx out pat2.p_pos in
+					let tl = array_tl pv in
+					loop2 (Array.append [|{pat with p_def = PBind(v,pat2)}|] tl) out2;
+					loop2 (Array.append [|{pat with p_def = PBind(v,pat1)}|] tl) out;
+				| {p_def = PTuple tl} as pat ->
+					begin match tl.(0).p_def with
+					 	| POr(pat1,pat2) ->
+							let out2 = clone_out mctx out pat2.p_pos in
+							let a1 = Array.copy tl in
+							a1.(0) <- pat1;
+							let a2 = Array.copy tl in
+							a2.(0) <- pat2;
+							let tl = array_tl pv in
+							loop2 (Array.append [|{pat with p_def = PTuple a2}|] tl) out2;
+							loop2 (Array.append [|{pat with p_def = PTuple a1}|] tl) out;
+					 	| _ ->
+					 		acc := (pv,out) :: !acc
+					 end
+				| _ ->
+					acc := (pv,out) :: !acc
+			in
+			let r = loop pmat in
+			loop2 pv out;
+			!acc @ r
+		| [] ->
+			[]
+	in
+	loop pmat
+
 let column_sigma mctx st pmat =
 	let acc = ref [] in
 	let bindings = ref [] in
@@ -716,10 +740,6 @@ let column_sigma mctx st pmat =
 			let rec loop2 out = function
 				| PCon (c,_) ->
 					add c ((get_guard mctx out.o_id) <> None);
-				| POr(pat1,pat2) ->
-					let out2 = clone_out mctx out [pat2] pat2.p_pos in
-					loop2 out pat1.p_def;
-					loop2 out2 pat2.p_def;
 				| PVar v ->
 					bind_st out st v;
 				| PBind(v,pat) ->
@@ -729,6 +749,8 @@ let column_sigma mctx st pmat =
 					()
 				| PTuple tl ->
 					loop2 out tl.(0).p_def
+				| POr _ ->
+					assert false
 			in
 			loop2 out pv.(0).p_def;
 			loop pr
@@ -767,7 +789,7 @@ let rec all_ctors mctx t =
 				| _ -> ()
 		) c.cl_ordered_statics;
 		h,false
-	| TAbstract(a,pl) -> all_ctors mctx (Codegen.Abstract.get_underlying_type a pl)
+	| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> all_ctors mctx (Codegen.Abstract.get_underlying_type a pl)
 	| TInst({cl_path=[],"String"},_)
 	| TInst({cl_path=[],"Array"},_) ->
 		h,true
@@ -792,11 +814,7 @@ let rec collapse_pattern pl = match pl with
 		pat
 	| pat :: pl ->
 		let pat2 = collapse_pattern pl in
-		{
-			p_def = POr(pat,pat2);
-			p_pos = punion pat.p_pos pat2.p_pos;
-			p_type = pat.p_type
-		}
+		mk_pat (POr(pat,pat2)) pat.p_type (punion pat.p_pos pat2.p_pos)
 	| [] ->
 		assert false
 
@@ -854,7 +872,7 @@ let rec compile mctx stl pmat toplevel =
 	| (pv,out) :: pl ->
 		let i = pick_column pmat in
 		if i = -1 then begin
-			Hashtbl.replace mctx.used_paths out.o_id true;
+			out.o_num_paths <- out.o_num_paths + 1;
 			let bl = bind_remaining out pv stl in
 			let dt = match (get_guard mctx out.o_id) with
 				| None -> expr out.o_id
@@ -867,6 +885,7 @@ let rec compile mctx stl pmat toplevel =
 			compile mctx stls pmat toplevel
 		end else begin
 			let st_head,st_tail = match stl with st :: stl -> st,stl | _ -> assert false in
+			let pmat = expand_or mctx pmat in
 			let sigma,bl = column_sigma mctx st_head pmat in
 			let all,inf = all_ctors mctx st_head.st_type in
 			let cases = List.map (fun (c,g) ->
@@ -1095,9 +1114,8 @@ let match_expr ctx e cases def with_type p =
 	let mctx = {
 		ctx = ctx;
 		need_val = need_val;
-		outcomes = PMap.empty;
+		outcomes = [];
 		toplevel_or = false;
-		used_paths = Hashtbl.create 0;
 		dt_lut = DynArray.create ();
 		dt_cache = Hashtbl.create 0;
 		dt_count = 0;
@@ -1152,6 +1170,10 @@ let match_expr ctx e cases def with_type p =
 			with Unrecognized_pattern (e,p) ->
 				error "Case expression must be a constant value or a pattern, not an arbitrary expression" p
 		in
+		let is_catch_all = match pl with
+			| [{p_def = PAny | PVar _}] -> true
+			| _ -> false
+		in
 		(* type case body *)
 		let e = match e with
 			| None -> mk (TBlock []) ctx.com.basic.tvoid (pos ep)
@@ -1176,8 +1198,7 @@ let match_expr ctx e cases def with_type p =
 		in
 		List.iter (fun f -> f()) restore;
 		save();
-		let is_default = match fst ep with (EConst(Ident "_")) -> true | _ -> false in
-		let out = mk_out mctx i e eg pl is_default (pos ep) in
+		let out = mk_out mctx i e eg is_catch_all (pos ep) in
 		Array.of_list pl,out
 	) cases in
 	let check_unused () =
@@ -1204,8 +1225,11 @@ let match_expr ctx e cases def with_type p =
 			(match cases with (e,_,_) :: cl -> loop e cl | [] -> assert false);
 			ctx.on_error <- old_error;
 		in
- 		PMap.iter (fun _ out ->
- 			if not (Hashtbl.mem mctx.used_paths out.o_id || out.o_default) then begin
+		let had_catch_all = ref false in
+ 		List.iter (fun out ->
+ 			if out.o_catch_all && not !had_catch_all then
+ 				had_catch_all := true
+ 			else if out.o_num_paths = 0 then begin
 				unused out.o_pos;
 				if mctx.toplevel_or then begin match evals with
 					| [{etype = t}] when (match follow t with TAbstract({a_path=[],"Int"},[]) -> true | _ -> false) ->
@@ -1213,7 +1237,7 @@ let match_expr ctx e cases def with_type p =
 					| _ -> ()
 				end;
 			end
-		) mctx.outcomes;
+		) (List.rev mctx.outcomes);
 	in
 	let dt = try
 		(* compile decision tree *)

+ 53 - 7
optimizer.ml

@@ -79,6 +79,45 @@ let api_inline ctx c field params p =
 			Some stringv
 		| _ ->
 			None)
+	| ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js ->
+		let mk_local ctx n t pos = mk (TLocal (try PMap.find n ctx.locals with _ -> add_local ctx n t)) t pos in
+
+		let tstring = ctx.com.basic.tstring in
+		let tbool = ctx.com.basic.tbool in
+		let tint = ctx.com.basic.tint in
+
+		let is_trivial e =
+			match e.eexpr with
+			| TConst _ | TLocal _ -> true
+			| _ -> false
+		in
+
+		let typeof t =
+			let tof = mk_local ctx "__typeof__" (tfun [o.etype] tstring) p in
+			let tof = mk (TCall (tof, [o])) tstring p in
+			mk (TBinop (Ast.OpEq, tof, (mk (TConst (TString t)) tstring p))) tbool p
+		in
+
+		(match t.eexpr with
+		(* generate simple typeof checks for basic types *)
+		| TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> Some (typeof "string")
+		| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean")
+		| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number")
+		| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o ->
+			(* generate (o|0) === o check *)
+			let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in
+			let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in
+			Some (mk (TCall (teq, [lhs; o])) tbool p)
+		| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
+			(* generate (o instanceof Array) && o.__enum__ == null check *)
+			let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in
+			let iof = mk (TCall (iof, [o; t])) tbool p in
+			let enum = mk (TField (o, FDynamic "__enum__")) (mk_mono()) p in
+			let null = mk (TConst TNull) (mk_mono()) p in
+			let not_enum = mk (TBinop (Ast.OpEq, enum, null)) tbool p in
+			Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p)
+		| _ ->
+			None)
 	| ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] ->
 		let f = float_of_string f in
 		(match classify_float f with
@@ -125,7 +164,7 @@ let inline_default_config cf t =
 	let tparams = fst tparams @ cf.cf_params in
 	tparams <> [], apply_params tparams tmonos
 
-let rec type_inline ctx cf f ethis params tret config p force =
+let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=false) force =
 	(* perform some specific optimization before we inline the call since it's not possible to detect at final optimization time *)
 	try
 		let cl = (match follow ethis.etype with
@@ -206,6 +245,7 @@ let rec type_inline ctx cf f ethis params tret config p force =
 		if has_side_effect e then l.i_force_temp <- true; (* force tmp var *)
 		l, e
 	) (ethis :: loop params f.tf_args true) ((vthis,None) :: f.tf_args) in
+	let inlined_vars = List.rev inlined_vars in
 	(*
 		here, we try to eliminate final returns from the expression tree.
 		However, this is not entirely correct since we don't yet correctly propagate
@@ -223,9 +263,10 @@ let rec type_inline ctx cf f ethis params tret config p force =
 	let cancel_inlining = ref false in
 	let has_return_value = ref false in
 	let ret_val = (match follow f.tf_type with TAbstract ({ a_path = ([],"Void") },[]) -> false | _ -> true) in
+	let map_pos = if self_calling_closure then (fun e -> e) else (fun e -> { e with epos = p }) in
 	let rec map term e =
 		let po = e.epos in
-		let e = { e with epos = p } in
+		let e = map_pos e in
 		match e.eexpr with
 		| TLocal v ->
 			let l = read_local v in
@@ -406,7 +447,7 @@ let rec type_inline ctx cf f ethis params tret config p force =
 
 		This could be fixed with better post process code cleanup (planed)
 	*)
-	if !cancel_inlining then
+	if !cancel_inlining || (Common.platform ctx.com Js && not !force && (init <> None || !has_vars)) then
 		None
 	else
 		let wrap e =
@@ -963,7 +1004,7 @@ let rec reduce_loop ctx e =
 		let cf = mk_field "" ef.etype e.epos in
 		let ethis = mk (TConst TThis) t_dynamic e.epos in
 		let rt = (match follow ef.etype with TFun (_,rt) -> rt | _ -> assert false) in
-		let inl = (try type_inline ctx cf func ethis el rt None e.epos false with Error (Custom _,_) -> None) in
+		let inl = (try type_inline ctx cf func ethis el rt None e.epos ~self_calling_closure:true false with Error (Custom _,_) -> None) in
 		(match inl with
 		| None -> reduce_expr ctx e
 		| Some e -> reduce_loop ctx e)
@@ -1184,14 +1225,19 @@ let inline_constructors ctx e =
 				in
 				List.iter (fun (v,e) -> el_b := (mk (TVar(v,Some (subst e))) ctx.t.tvoid e.epos) :: !el_b) (List.rev vars);
 				mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos
-			| TField ({ eexpr = TLocal v },FInstance (_,cf)) when v.v_id < 0 ->
+			| TField ({ eexpr = TLocal v },FInstance (c,cf)) when v.v_id < 0 ->
 				let (_, vars),el_init = PMap.find (-v.v_id) vfields in
 				(try
 					let v = PMap.find cf.cf_name vars in
 					mk (TLocal v) v.v_type e.epos
 				with Not_found ->
-					(* the variable was not set in the constructor, assume null *)
-					mk (TConst TNull) e.etype e.epos)
+					if (c.cl_path = ([],"Array") && cf.cf_name = "length") then begin
+						(* this can only occur for inlined array declarations, so we can use the statically known length here (issue #2568)*)
+						let l = PMap.fold (fun _ i -> i + 1) vars 0 in
+						mk (TConst (TInt (Int32.of_int l))) ctx.t.tint e.epos
+					end else
+						(* the variable was not set in the constructor, assume null *)
+						mk (TConst TNull) e.etype e.epos)
 			| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
 				let (_, vars),_ = PMap.find (-v.v_id) vfields in
 				(try

+ 24 - 11
parser.ml

@@ -62,6 +62,11 @@ let quote_ident s =
 	with Exit ->
 		quoted_ident_prefix ^ s
 
+let unquote_ident f =
+	let pf = quoted_ident_prefix in
+	let pflen = String.length pf in
+	if String.length f >= pflen && String.sub f 0 pflen = pf then String.sub f pflen (String.length f - pflen), false else f, true
+
 let cache = ref (DynArray.create())
 let last_doc = ref None
 let use_doc = ref false
@@ -215,12 +220,17 @@ let reify in_macro =
 		) in
 		mk_enum "TypeParam" n [v] p
 	and to_tpath t p =
-		let fields = [
-			("pack", to_array to_string t.tpackage p);
-			("name", to_string t.tname p);
-			("params", to_array to_tparam t.tparams p);
-		] in
-		to_obj (match t.tsub with None -> fields | Some s -> fields @ ["sub",to_string s p]) p
+		let len = String.length t.tname in
+		if t.tpackage = [] && len > 1 && t.tname.[0] = '$' then
+			(EConst (Ident (String.sub t.tname 1 (len - 1))),p)
+		else begin
+			let fields = [
+				("pack", to_array to_string t.tpackage p);
+				("name", to_string t.tname p);
+				("params", to_array to_tparam t.tparams p);
+			] in
+			to_obj (match t.tsub with None -> fields | Some s -> fields @ ["sub",to_string s p]) p
+		end
 	and to_ctype t p =
 		let ct n vl = mk_enum "ComplexType" n vl p in
 		match t with
@@ -530,7 +540,11 @@ let semicolon s =
 let rec	parse_file s =
 	last_doc := None;
 	match s with parser
-	| [< '(Kwd Package,_); p = parse_package; _ = semicolon; l = parse_type_decls p []; '(Eof,_) >] -> p , l
+	| [< '(Kwd Package,_); pack = parse_package; s >] ->
+		begin match s with parser
+		| [< '(Const(Ident _),p) when pack = [] >] -> error (Custom "Package name must start with a lowercase character") p
+		| [< _ = semicolon; l = parse_type_decls pack []; '(Eof,_) >] -> pack , l
+		end
 	| [< l = parse_type_decls [] []; '(Eof,_) >] -> [] , l
 
 and parse_type_decls pack acc s =
@@ -704,6 +718,9 @@ and parse_class_field_resume tdecl s =
 		in
 		let rec loop k =
 			match List.rev_map fst (Stream.npeek k s) with
+			(* metadata *)
+			| Kwd _ :: At :: _ | Kwd _ :: DblDot :: At :: _ ->
+				loop (k + 1)
 			(* field declaration *)
 			| Const _ :: Kwd Function :: _
 			| Kwd New :: Kwd Function :: _ ->
@@ -854,10 +871,6 @@ and parse_type_anonymous opt = parser
 	| [< '(Question,_) when not opt; s >] -> parse_type_anonymous true s
 	| [< name, p1 = ident; '(DblDot,_); t = parse_complex_type; s >] ->
 		let next p2 acc =
-			let t = if not opt then t else (match t with
-				| CTPath { tpackage = []; tname = "Null" } -> t
-				| _ -> CTPath { tpackage = []; tname = "Null"; tsub = None; tparams = [TPType t] }
-			) in
 			{
 				cff_name = name;
 				cff_meta = if opt then [Meta.Optional,[],p1] else [];

+ 2 - 2
std/Lambda.hx

@@ -227,8 +227,8 @@ class Lambda {
 	/**
 		Returns the first element of `it` for which `f` is true.
 
-		This function returns true as soon as an element is found for which a
-		call to `f` returns true.
+		This function returns as soon as an element is found for which a call to
+		`f` returns true.
 
 		If no such element is found, the result is null.
 

+ 2 - 2
std/Map.hx

@@ -41,7 +41,7 @@ import haxe.ds.EnumValueMap;
 	
 	Map is an abstract type, it is not available at runtime.
 **/
-@:multiType
+@:multiType(K)
 abstract Map<K,V>(IMap<K,V> ) {
 	
 	/**
@@ -79,7 +79,7 @@ abstract Map<K,V>(IMap<K,V> ) {
 		1. the map has no mapping for `key`
 		2. the map has a mapping with a value of `null`
 		
-		If it is important to distinguish these cases, `exists()` should be 
+		If it is important to distinguish these cases, `exists()` should be
 		used.
 		
 		If `key` is null, the result is unspecified.

+ 15 - 4
std/Std.hx

@@ -34,11 +34,22 @@ extern class Std {
 	public static function is( v : Dynamic, t : Dynamic ) : Bool;
 	
 	/**
-		Check if an object is an instance of the given class, then cast it.
-		Returns null if the object is not an instance of the class.
-		Is not guaranteed to work with interfaces or core types such as String, Array and Date.
+		Checks if object `value` is an instance of class `c`.
+		
+		Compiles only if the class specified by `c` can be assigned to the type
+		of `value`.
+		
+		This method checks if a downcast is possible. That is, if the runtime
+		type of `value` is assignable to the class specified by `c`, `value` is
+		returned. Otherwise null is returned.
+		
+		This method is not guaranteed to work with interfaces or core types such
+		as String, Array and Date.
+		
+		If `value` is null, the result is null. If `c` is null, the result is
+		unspecified.
 	**/
-	public static function instance<T>( v : {}, c : Class<T> ) : T;
+	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S;
 
 	/**
 		Converts any value to a String.

+ 70 - 69
std/UInt.hx

@@ -20,7 +20,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#if (flash9 || flash9doc || cs)
+#if ((flash9 || flash9doc || cs) && !doc_gen)
 /**
 	The unsigned Int type is only defined for Flash9 and C#. It's currently
 	handled the same as a normal Int.
@@ -33,73 +33,7 @@
 **/
 abstract UInt(Int) from Int {
 
-	@:commutative @:op(A + B) private static inline function addWithFloat(a:UInt, b:Float):Float {
-		return a.toFloat() + b;
-	}
-
-	@:commutative @:op(A * B) private static inline function mulWithFloat(a:UInt, b:Float):Float {
-		return a.toFloat() * b;
-	}
-
-	@:op(A / B) private static inline function divFloat(a:UInt, b:Float):Float {
-		return a.toFloat() / b;
-	}
-
-	@:op(A / B) private static inline function floatDiv(a:Float, b:UInt):Float {
-		return a / b.toFloat();
-	}
-
-	@:op(A - B) private static inline function subFloat(a:UInt, b:Float):Float {
-		return a.toFloat() - b;
-	}
-
-	@:op(A - B) private static inline function floatSub(a:Float, b:UInt):Float {
-		return a - b.toFloat();
-	}
-
-	@:op(A > B) private static inline function gtFloat(a:UInt, b:Float):Bool {
-		return a.toFloat() > b;
-	}
-
-	@:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool {
-		return a.toFloat() >= b;
-	}
-
-
-	@:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool {
-		return a > b.toFloat();
-	}
-
-	@:op(A >= B) private static inline function floatGte(a:Float, b:UInt):Bool {
-		return a >= b.toFloat();
-	}
-
-	@:op(A < B) private static inline function ltFloat(a:UInt, b:Float):Bool {
-		return a.toFloat() < b;
-	}
-
-	@:op(A <= B) private static inline function lteFloat(a:UInt, b:Float):Bool {
-		return a.toFloat() <= b;
-	}
-
-
-	@:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool {
-		return a < b.toFloat();
-	}
-
-	@:op(A <= B) private static inline function floatLte(a:Float, b:UInt):Bool {
-		return a <= b.toFloat();
-	}
-
-	@:op(A % B) private static inline function modFloat(a:UInt, b:Float):Float {
-		return a.toFloat() % b;
-	}
-
-	@:op(A % B) private static inline function floatMod(a:Float, b:UInt):Float {
-		return a % b.toFloat();
-	}
-
-	@:op(A + B) private static inline function add(a:UInt, b:UInt):UInt {
+		@:op(A + B) private static inline function add(a:UInt, b:UInt):UInt {
 		return a.toInt() + b.toInt();
 	}
 
@@ -188,6 +122,72 @@ abstract UInt(Int) from Int {
 	@:op(A % B) private static inline function mod(a:UInt, b:UInt):UInt {
 		return a.toInt() % b.toInt();
 	}
+	
+	@:commutative @:op(A + B) private static inline function addWithFloat(a:UInt, b:Float):Float {
+		return a.toFloat() + b;
+	}
+
+	@:commutative @:op(A * B) private static inline function mulWithFloat(a:UInt, b:Float):Float {
+		return a.toFloat() * b;
+	}
+
+	@:op(A / B) private static inline function divFloat(a:UInt, b:Float):Float {
+		return a.toFloat() / b;
+	}
+
+	@:op(A / B) private static inline function floatDiv(a:Float, b:UInt):Float {
+		return a / b.toFloat();
+	}
+
+	@:op(A - B) private static inline function subFloat(a:UInt, b:Float):Float {
+		return a.toFloat() - b;
+	}
+
+	@:op(A - B) private static inline function floatSub(a:Float, b:UInt):Float {
+		return a - b.toFloat();
+	}
+
+	@:op(A > B) private static inline function gtFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() > b;
+	}
+
+	@:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() >= b;
+	}
+
+
+	@:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool {
+		return a > b.toFloat();
+	}
+
+	@:op(A >= B) private static inline function floatGte(a:Float, b:UInt):Bool {
+		return a >= b.toFloat();
+	}
+
+	@:op(A < B) private static inline function ltFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() < b;
+	}
+
+	@:op(A <= B) private static inline function lteFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() <= b;
+	}
+
+
+	@:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool {
+		return a < b.toFloat();
+	}
+
+	@:op(A <= B) private static inline function floatLte(a:Float, b:UInt):Bool {
+		return a <= b.toFloat();
+	}
+
+	@:op(A % B) private static inline function modFloat(a:UInt, b:Float):Float {
+		return a.toFloat() % b;
+	}
+
+	@:op(A % B) private static inline function floatMod(a:Float, b:UInt):Float {
+		return a % b.toFloat();
+	}
 
 	@:op(~A) private inline function negBits():UInt {
 		return ~this;
@@ -209,7 +209,8 @@ abstract UInt(Int) from Int {
 		return this--;
 	}
 
-	private inline function toString():String {
+	// TODO: radix is just defined to deal with doc_gen issues
+	private inline function toString(?radix:Int):String {
 		return Std.string(toFloat());
 	}
 

+ 3 - 0
std/cpp/_std/Date.hx

@@ -50,6 +50,9 @@
 	public static function now() : Date {
 		return fromTime( untyped __global__.__hxcpp_date_now()*1000.0);
 	}
+  	private static function new1(t : Dynamic) : Date {
+		return  new Date(2005,1,1,0,0,0);
+	}
 
 	public static function fromTime( t : Float ) : Date {
 		var result = new Date(0,0,0,0,0,0);

+ 2 - 2
std/cpp/_std/Std.hx

@@ -24,8 +24,8 @@
 		return untyped __global__.__instanceof(v,t);
 	}
 
-	@:keep public static function instance<T>( v : { }, c : Class<T> ) : T {
-		return Std.is(v, c) ? cast v : null;
+	@:keep public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Std.is(value, c) ? cast value : null;
 	}
 
 	@:keep public static function string( s : Dynamic ) : String {

+ 3 - 1
std/cpp/_std/haxe/Utf8.hx

@@ -90,7 +90,9 @@ class Utf8
 
 	public static function sub( s : String, pos : Int, len : Int ) : String {
       var array:Array<Int> = untyped __global__.__hxcpp_utf8_string_to_char_array(s);
-      var sub = array.slice(pos,len);
+      var last = len < 0 ? array.length : pos+len;
+      if (last>array.length) last = array.length;
+      var sub = array.slice(pos,last);
 		return untyped __global__.__hxcpp_char_array_to_utf8_string(sub);
 	}
 

+ 2 - 2
std/cpp/_std/sys/FileSystem.hx

@@ -31,7 +31,7 @@ private enum FileKind {
 class FileSystem {
 
 	public static inline function exists( path : String ) : Bool {
-		return sys_exists(path);
+		return sys_exists(haxe.io.Path.removeTrailingSlashes(path));
 	}
 
 	public static function rename( path : String, newPath : String ) : Void {
@@ -54,7 +54,7 @@ class FileSystem {
 	}
 
 	static function kind( path : String ) : FileKind {
-		var k:String = sys_file_type(path);
+		var k:String = sys_file_type(haxe.io.Path.removeTrailingSlashes(path));
 		return switch(k) {
 		case "file": kfile;
 		case "dir": kdir;

+ 202 - 0
std/cpp/_std/sys/db/Mysql.hx

@@ -0,0 +1,202 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.db;
+
+private class D {
+
+	static function load(fun,args) : Dynamic {
+		return cpp.Lib.load(lib,fun,args);
+	}
+
+	static var lib = "mysql5";
+	public static var connect = load("mysql_connect",1);
+	public static var select_db = load("select_db",2);
+	public static var request = load("request",2);
+	public static var close = load("close",1);
+	public static var escape = load("escape", 2);
+	public static var set_conv_funs = load("set_conv_funs", 4);
+	public static var result_get_length = load("result_get_length",1);
+	public static var result_get_nfields = load("result_get_nfields",1);
+	public static var result_next = load("result_next",1);
+	public static var result_get = load("result_get",2);
+	public static var result_get_int = load("result_get_int",2);
+	public static var result_get_float = load("result_get_float",2);
+	public static var result_fields_names = cpp.Lib.loadLazy(lib,"result_get_fields_names",1);
+
+}
+
+private class MysqlResultSet implements sys.db.ResultSet {
+
+	public var length(get,null) : Int;
+	public var nfields(get,null) : Int;
+	private var __r : Dynamic;
+	private var cache : Dynamic;
+
+	public function new(r) {
+		__r = r;
+	}
+
+	private function get_length() {
+		return D.result_get_length(__r);
+	}
+
+	private function get_nfields() {
+		return D.result_get_nfields(__r);
+	}
+
+	public function hasNext() {
+		if( cache == null )
+			cache = next();
+		return (cache != null);
+	}
+
+	public function next() : Dynamic {
+		var c = cache;
+		if( c != null ) {
+			cache = null;
+			return c;
+		}
+		c = D.result_next(__r);
+		return c;
+	}
+
+	public function results() : List<Dynamic> {
+		var l = new List();
+		while( hasNext() )
+			l.add(next());
+		return l;
+	}
+
+	public function getResult( n : Int ) {
+		return new String(D.result_get(__r,n));
+	}
+
+	public function getIntResult( n : Int ) : Int {
+		return D.result_get_int(__r,n);
+	}
+
+	public function getFloatResult( n : Int ) : Float {
+		return D.result_get_float(__r,n);
+	}
+
+	public function getFieldsNames() : Array<String> {
+		var a = D.result_fields_names(__r);
+		return a;
+	}
+
+}
+
+private class MysqlConnection implements sys.db.Connection {
+
+	private var __c : Dynamic;
+
+	public function new(c) {
+		__c = c;
+		D.set_conv_funs(c, function(s) return new String(s), function(d) return untyped Date.new1(d), function(b) return haxe.io.Bytes.ofData(b));
+	}
+
+	public function request( s : String ) : sys.db.ResultSet {
+			var r = D.request(this.__c, s);
+			return new MysqlResultSet(r);
+	}
+
+	public function close() {
+		D.close(__c);
+	}
+
+	public function escape( s : String ) {
+		return new String(D.escape(__c,s));
+	}
+
+	public function quote( s : String ) {
+		return "'"+escape(s)+"'";
+	}
+
+	public function addValue( s : StringBuf, v : Dynamic ) {
+		if (v == null) {
+			s.add(v);
+      }
+      else {
+			var t:Int = untyped v.__GetType();
+			if( t == 0xff )
+				s.add(v);
+			else if( t == 2 )
+				s.add( untyped v.__GetInt() ? "1".code : "0".code );
+			else {
+				s.addChar("'".code);
+				s.add(escape(Std.string(v)));
+				s.addChar("'".code);
+			}
+		}
+	}
+
+	public function lastInsertId() {
+		return request("SELECT LAST_INSERT_ID()").getIntResult(0);
+	}
+
+	public function dbName() {
+		return "MySQL";
+	}
+
+	public function startTransaction() {
+		request("START TRANSACTION");
+	}
+
+	public function commit() {
+		request("COMMIT");
+	}
+
+	public function rollback() {
+		request("ROLLBACK");
+	}
+
+	private static var __use_date = Date;
+}
+
+@:coreApi class Mysql {
+
+	public static function connect( params : {
+		host : String,
+		?port : Int,
+		user : String,
+		pass : String,
+		?socket : String,
+		database : String
+	} ) : sys.db.Connection {
+		var o = {
+			host : params.host,
+			port : if( params.port == null ) 3306 else params.port,
+			user : params.user,
+			pass : params.pass,
+			socket : if( params.socket == null ) null else params.socket
+		};
+		var c = D.connect(o);
+		try {
+			D.select_db(c,params.database);
+		} catch( e : Dynamic ) {
+			D.close(c);
+			cpp.Lib.rethrow(e);
+		}
+		return new MysqlConnection(c);
+	}
+
+}

+ 186 - 0
std/cpp/_std/sys/db/Sqlite.hx

@@ -0,0 +1,186 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.db;
+
+private class SqliteConnection implements Connection {
+
+	var c : Dynamic;
+
+	public function new( file : String ) {
+		c = _connect(file);
+	}
+
+	public function close() {
+		_close(c);
+	}
+
+	public function request( s : String ) : ResultSet {
+		try {
+			return new SqliteResultSet(_request(c,s));
+		} catch( e : String ) {
+			throw "Error while executing "+s+" ("+e+")";
+		}
+	}
+
+	public function escape( s : String ) {
+		return s.split("'").join("''");
+	}
+
+	public function quote( s : String ) {
+		if( s.indexOf("\000") >= 0 )
+			return "x'"+new String(_encode(s,"0123456789ABCDEF"))+"'";
+		return "'"+s.split("'").join("''")+"'";
+	}
+
+	public function addValue( s : StringBuf, v : Dynamic ) {
+		if (v == null) {
+			s.add(v);
+      }
+      else {
+			var t:Int = untyped v.__GetType();
+			if( t == 0xff )
+				s.add(v);
+			else if( t == 2 )
+				s.add( untyped v.__GetInt() );
+			else
+				s.add(quote(Std.string(v)));
+		}
+	}
+
+	public function lastInsertId() {
+		return _last_id(c);
+	}
+
+	public function dbName() {
+		return "SQLite";
+	}
+
+	public function startTransaction() {
+		request("BEGIN TRANSACTION");
+	}
+
+	public function commit() {
+		request("COMMIT");
+		startTransaction(); // match mysql usage
+	}
+
+	public function rollback() {
+		request("ROLLBACK");
+		startTransaction(); // match mysql usage
+	}
+
+	static var _encode = cpp.Lib.load("std","base_encode",2);
+	static var _connect = cpp.Lib.load("sqlite","sqlite_connect",1);
+	static var _close = cpp.Lib.load("sqlite","close",1);
+	static var _request = cpp.Lib.load("sqlite","request",2);
+	static var _last_id = cpp.Lib.load("sqlite","last_insert_id",1);
+}
+
+
+private class SqliteResultSet implements ResultSet {
+
+	public var length(get,null) : Int;
+	public var nfields(get,null) : Int;
+	var r : Dynamic;
+	var cache : List<Dynamic>;
+
+	public function new( r ) {
+		cache = new List();
+		this.r = r;
+		hasNext(); // execute the request
+	}
+
+	function get_length() {
+		if( nfields != 0 ) {
+			while( true ) {
+				var c = result_next(r);
+				if( c == null )
+					break;
+				cache.add(c);
+			}
+			return cache.length;
+		}
+		return result_get_length(r);
+	}
+
+	function get_nfields() {
+		return result_get_nfields(r);
+	}
+
+	public function hasNext() {
+		var c = next();
+		if( c == null )
+			return false;
+		cache.push(c);
+		return true;
+	}
+
+	public function next() : Dynamic {
+		var c = cache.pop();
+		if( c != null )
+			return c;
+		return result_next(r);
+	}
+
+	public function results() : List<Dynamic> {
+		var l = new List();
+		while( true ) {
+			var c = next();
+			if( c == null )
+				break;
+			l.add(c);
+		}
+		return l;
+	}
+
+	public function getResult( n : Int ) {
+		return new String(result_get(r,n));
+	}
+
+	public function getIntResult( n : Int ) : Int {
+		return result_get_int(r,n);
+	}
+
+	public function getFloatResult( n : Int ) : Float {
+		return result_get_float(r,n);
+	}
+
+	public function getFieldsNames() : Array<String> {
+		return null;
+	}
+
+	static var result_next = cpp.Lib.load("sqlite","result_next",1);
+	static var result_get_length = cpp.Lib.load("sqlite","result_get_length",1);
+	static var result_get_nfields = cpp.Lib.load("sqlite","result_get_nfields",1);
+	static var result_get = cpp.Lib.load("sqlite","result_get",2);
+	static var result_get_int = cpp.Lib.load("sqlite","result_get_int",2);
+	static var result_get_float = cpp.Lib.load("sqlite","result_get_float",2);
+
+}
+
+@:coreApi class Sqlite {
+
+	public static function open( file : String ) : Connection {
+		return new SqliteConnection(file);
+	}
+
+}

+ 15 - 0
std/cpp/vm/Debugger.hx

@@ -188,6 +188,21 @@ class Debugger
         return untyped __global__.__hxcpp_dbg_getFiles();
    }
 
+
+    /**
+     * Returns the full paths of the set of source files known to the debugger.
+     * This is a copy of the original array and could be quite large.
+     * It is possible that this set will be empty, in which case the full paths are not known.
+     * The index of these files matches the index from "getFiles", so the full path for
+     * a given short path can be calculated.
+     *
+     * @return the known full paths of the set of source files
+     **/
+   public static function getFilesFullPath() : Array<String>
+   {
+        return untyped __global__.__hxcpp_dbg_getFilesFullPath();
+   }
+
     /**
      * Returns the set of class names of all classes known to the debugger.
      * This is a copy of the original array and could be quite large.  The

+ 20 - 8
std/cs/_std/Array.hx

@@ -408,15 +408,9 @@ import cs.NativeArray;
 		return ofNative(newarr);
 	}
 
-	public function iterator() : Iterator<T>
+	public inline function iterator() : Iterator<T>
 	{
-		var i = 0;
-		var len = length;
-		return
-		{
-			hasNext:function() return i < len,
-			next:function() return __a[i++]
-		};
+		return new ArrayIterator<T>(this);
 	}
 
 	private function __get(idx:Int):T
@@ -459,3 +453,21 @@ import cs.NativeArray;
 		return __a[idx] = val;
 	}
 }
+
+@:final
+private class ArrayIterator<T>
+{
+	var arr:Array<T>;
+	var len:Int;
+	var i:Int;
+
+	public inline function new(a:Array<T>)
+	{
+		arr = a;
+		len = a.length;
+		i = 0;
+	}
+
+	public inline function hasNext():Bool return i < len;
+	public inline function next():T return arr[i++];
+}

+ 2 - 2
std/cs/_std/Std.hx

@@ -234,8 +234,8 @@ import cs.internal.Exceptions;
 		}
 	}
 
-	public static function instance<T>( v : { }, c : Class<T> ) : T {
-		return Std.is(v, c) ? cast v : null;
+	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Std.is(value, c) ? cast value : null;
 	}
 
 	public static function random( x : Int ) : Int {

+ 5 - 0
std/cs/internal/StringExt.hx

@@ -176,6 +176,11 @@ private typedef NativeString = String;
 		return null;
 	}
 
+	public static function toString(me:NativeString):NativeString
+	{
+		return me;
+	}
+
 	@:functionCode('
 			return me.ToLower();
 	')

+ 2 - 2
std/flash/_std/Std.hx

@@ -27,8 +27,8 @@ import flash.Boot;
 		return untyped flash.Boot.__instanceof(v,t);
 	}
 
-	public inline static function instance<T>( v : { }, c : Class<T> ) : T {
-		return flash.Lib.as(v, c);
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return flash.Lib.as(value, c);
 	}
 
 	public static function string( s : Dynamic ) : String {

+ 16 - 6
std/js/html/DOMStringMap.hx → std/flash/_std/haxe/Json.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2013 Haxe Foundation
+ * Copyright (C)2005-2012 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -19,11 +19,21 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+package haxe;
 
-// This file is generated, do not edit!
-package js.html;
+@:coreApi
+#if (!haxeJSON && flash11)
+@:native("JSON") extern
+#end
+class Json {
 
-@:native("DOMStringMap")
-extern class DOMStringMap
-{
+	#if (haxeJSON || !flash11) inline #end
+	public static function parse( text : String ) : Dynamic {
+		return haxe.format.JsonParser.parse(text);
+	}
+
+	#if (haxeJSON || !flash11) inline #end
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer);
+	}
 }

+ 1 - 0
std/flash/display/DisplayObjectContainer.hx

@@ -18,6 +18,7 @@ extern class DisplayObjectContainer extends InteractiveObject {
 	function removeChildAt(index : Int) : DisplayObject;
 	@:require(flash11) function removeChildren(beginIndex : Int = 0, endIndex : Int = 2147483647) : Void;
 	function setChildIndex(child : DisplayObject, index : Int) : Void;
+	@:require(flash11_8) function stopAllMovieClips() : Void;
 	function swapChildren(child1 : DisplayObject, child2 : DisplayObject) : Void;
 	function swapChildrenAt(index1 : Int, index2 : Int) : Void;
 }

+ 1 - 0
std/flash/display/Stage3D.hx

@@ -6,4 +6,5 @@ package flash.display;
 	var x : Float;
 	var y : Float;
 	function requestContext3D(?context3DRenderMode : String, ?profile : flash.display3D.Context3DProfile) : Void;
+	@:require(flash12) function requestContext3DMatchingProfiles(profiles:Vector<String>) : Void;
 }

+ 2 - 0
std/flash/display3D/Context3D.hx

@@ -3,11 +3,13 @@ package flash.display3D;
 @:final extern class Context3D extends flash.events.EventDispatcher {
 	var driverInfo(default,null) : String;
 	var enableErrorChecking : Bool;
+	@:require(flash12) var profile : String;
 	function clear(red : Float = 0, green : Float = 0, blue : Float = 0, alpha : Float = 1, depth : Float = 1, stencil : UInt = 0, mask : UInt = 0xFFFFFFFF) : Void;
 	function configureBackBuffer(width : Int, height : Int, antiAlias : Int, enableDepthAndStencil : Bool = true, wantsBestResolution : Bool = false) : Void;
 	function createCubeTexture(size : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.CubeTexture;
 	function createIndexBuffer(numIndices : Int) : IndexBuffer3D;
 	function createProgram() : Program3D;
+	@:require(flash11_8) function createRectangleTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool) : flash.display3D.textures.RectangleTexture;
 	function createTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.Texture;
 	function createVertexBuffer(numVertices : Int, data32PerVertex : Int) : VertexBuffer3D;
 	function dispose(recreate : Bool = true) : Void;

+ 1 - 0
std/flash/display3D/Context3DProfile.hx

@@ -3,4 +3,5 @@ package flash.display3D;
 @:fakeEnum(String) extern enum Context3DProfile {
 	BASELINE;
 	BASELINE_CONSTRAINED;
+	BASELINE_EXTENDED;
 }

+ 1 - 0
std/flash/events/AVStatusEvent.hx

@@ -18,5 +18,6 @@ extern class AVStatusEvent extends Event {
 	static var SEEK_COMPLETE : String;
 	static var STEP_COMPLETE : String;
 	static var STREAM_SWITCH : String;
+	static var TRICKPLAY_ENDED : String;
 	static var WARNING : String;
 }

+ 10 - 0
std/flash/events/DRMReturnVoucherCompleteEvent.hx

@@ -0,0 +1,10 @@
+package flash.events;
+
+extern class DRMReturnVoucherCompleteEvent extends Event {
+	var licenseID : String;
+	var numberOfVouchersReturned : Int;
+	var policyID : String;
+	var serverURL : String;
+	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String, inNumberOfVouchersReturned : Int = 0) : Void;
+	static var RETURN_VOUCHER_COMPLETE : String;
+}

+ 10 - 0
std/flash/events/DRMReturnVoucherErrorEvent.hx

@@ -0,0 +1,10 @@
+package flash.events;
+
+extern class DRMReturnVoucherErrorEvent extends ErrorEvent {
+	var licenseID : String;
+	var policyID : String;
+	var serverURL : String;
+	var subErrorID : Int;
+	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inDetail : String, inErrorID : Int = 0, inSubErrorID : Int = 0, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String) : Void;
+	static var RETURN_VOUCHER_ERROR : String;
+}

+ 1 - 0
std/flash/events/GameInputEvent.hx

@@ -5,4 +5,5 @@ package flash.events;
 	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?device : flash.ui.GameInputDevice) : Void;
 	static var DEVICE_ADDED : String;
 	static var DEVICE_REMOVED : String;
+	static var DEVICE_UNUSABLE : String;
 }

+ 2 - 1
std/flash/events/HTTPStatusEvent.hx

@@ -1,10 +1,11 @@
 package flash.events;
 
 extern class HTTPStatusEvent extends Event {
+	var redirected : Bool;
 	@:require(flash10_1) var responseHeaders : Array<Dynamic>;
 	@:require(flash10_1) var responseURL : String;
 	var status(default,null) : Int;
-	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0) : Void;
+	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, redirected : Bool = false) : Void;
 	@:require(flash10_1) static var HTTP_RESPONSE_STATUS : String;
 	static var HTTP_STATUS : String;
 }

+ 1 - 0
std/flash/events/StageVideoAvailabilityEvent.hx

@@ -2,6 +2,7 @@ package flash.events;
 
 extern class StageVideoAvailabilityEvent extends Event {
 	var availability(default,null) : String;
+	var reason : String;
 	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?availability : String) : Void;
 	static var STAGE_VIDEO_AVAILABILITY : String;
 }

+ 2 - 1
std/flash/media/AVPeriodInfo.hx

@@ -5,7 +5,8 @@ extern class AVPeriodInfo {
 	var firstCuePointIndex(default,null) : Int;
 	var lastCuePointIndex(default,null) : Int;
 	var localStartTime(default,null) : Float;
+	var supportsTrickPlay(default,null) : Bool;
 	var userData(default,null) : Int;
 	var virtualStartTime(default,null) : Float;
-	function new(init_localStartTime : Float, init_virtualStartTime : Float, init_duration : Float, init_firstCuePointIndex : Int, init_lastCuePointIndex : Int, init_userData : Int) : Void;
+	function new(init_localStartTime : Float, init_virtualStartTime : Float, init_duration : Float, init_firstCuePointIndex : Int, init_lastCuePointIndex : Int, init_userData : Int, init_supportsTrickPlay : Bool) : Void;
 }

+ 1 - 0
std/flash/media/AVPlayState.hx

@@ -9,6 +9,7 @@ extern class AVPlayState {
 	static var PLAYING : Int;
 	static var READY : Int;
 	static var SUSPENDED : Int;
+	static var TRICK_PLAY : Int;
 	static var UNINITIALIZED : Int;
 	static var UNRECOVERABLE_ERROR : Int;
 }

+ 24 - 0
std/flash/media/AVResult.hx

@@ -4,11 +4,15 @@ extern class AVResult {
 	var result(default,null) : Int;
 	function new(inResult : Int) : Void;
 	static var ASYNC_OPERATION_IN_PROGRESS : Int;
+	static var AUDIO_START_ERROR : Int;
 	static var BAD_MANIFEST_SIGNATURE : Int;
+	static var BAD_MEDIASAMPLE_FOUND : Int;
 	static var BAD_MEDIA_INTERLEAVING : Int;
 	static var CALLED_FROM_WRONG_THREAD : Int;
+	static var CANNOT_ERASE_TIMELINE : Int;
 	static var CANNOT_FAIL_OVER : Int;
 	static var CANNOT_LOAD_PLAY_LIST : Int;
+	static var CANNOT_SPLIT_TIMELINE : Int;
 	static var CODEC_NOT_SUPPORTED : Int;
 	static var COMPONENT_CREATION_FAILURE : Int;
 	static var CONTAINER_NOT_SUPPORTED : Int;
@@ -16,43 +20,63 @@ extern class AVResult {
 	static var CURRENT_PERIOD_EXPIRED : Int;
 	static var DECODER_FAILED : Int;
 	static var DEVICE_OPEN_ERROR : Int;
+	static var DID_NOT_GET_NEXT_FRAGMENT : Int;
 	static var DRM_INIT_ERROR : Int;
 	static var DRM_NOT_AVAILABLE : Int;
+	static var END_OF_PERIOD : Int;
 	static var EOF : Int;
 	static var FILE_NOT_FOUND : Int;
+	static var FILE_OPEN_ERROR : Int;
+	static var FILE_READ_ERROR : Int;
 	static var FILE_STRUCTURE_INVALID : Int;
+	static var FILE_WRITE_ERROR : Int;
 	static var FRAGMENT_READ_ERROR : Int;
 	static var GENERIC_ERROR : Int;
 	static var HTTP_TIME_OUT : Int;
+	static var INCOMPATIBLE_RENDER_MODE : Int;
+	static var INCOMPATIBLE_VERSION : Int;
+	static var INTERNAL_ERROR : Int;
 	static var INVALID_OPERATION : Int;
 	static var INVALID_PARAMETER : Int;
 	static var INVALID_REPLACE_DURATION : Int;
 	static var INVALID_SEEK_TIME : Int;
 	static var INVALID_WITH_AUDIO_ONLY_FILE : Int;
 	static var IRRECOVERABLE_ERROR : Int;
+	static var LISTENER_NOT_FOUND : Int;
 	static var LIVE_HOLD : Int;
 	static var LIVE_WINDOW_MOVED_BACKWARD : Int;
 	static var LOST_CONNECTION_RECOVERABLE : Int;
+	static var MANIFEST_FILE_UNEXPECTEDLY_CHANGED : Int;
 	static var NETWORK_DOWN : Int;
 	static var NETWORK_ERROR : Int;
 	static var NETWORK_UNAVAILABLE : Int;
 	static var NOT_IMPLEMENTED : Int;
+	static var NO_AUDIO_SINK : Int;
 	static var NO_FIXED_SIZE : Int;
+	static var NO_TIMELINE : Int;
 	static var NO_USEABLE_BITRATE_PROFILE : Int;
+	static var NULL_OPERATION : Int;
 	static var ONLY_ALLOWED_IN_PAUSED_STATE : Int;
 	static var OPERATION_ABORTED : Int;
 	static var OUT_OF_MEMORY : Int;
 	static var OVERFLOW : Int;
 	static var PARSE_ERROR : Int;
+	static var PARTIAL_REPLACEMENT : Int;
 	static var PERIOD_HOLD : Int;
 	static var PERIOD_NOT_LOADED : Int;
 	static var PLAYBACK_NOT_ENABLED : Int;
+	static var POSTROLL_WITH_LIVE_NOT_ALLOWED : Int;
 	static var PREVIOUS_STEP_SEEK_IN_PROGRESS : Int;
+	static var PROTOCOL_NOT_SUPPORTED : Int;
 	static var RANGE_ERROR : Int;
+	static var RANGE_SPANS_READHEAD : Int;
+	static var RENDITION_M3U8_ERROR : Int;
 	static var REPLACEMENT_FAILED : Int;
 	static var RESOURCE_NOT_SPECIFIED : Int;
 	static var SEEK_FAILED : Int;
+	static var SEGMENT_SKIPPED_ON_FAILURE : Int;
 	static var SIZE_UNKNOWN : Int;
+	static var SPS_PPS_FOUND_OUTSIDE_AVCC : Int;
 	static var SUCCESS : Int;
 	static var SWITCH_TO_ASYMMETRIC_PROFILE : Int;
 	static var UNDERFLOW : Int;

+ 3 - 0
std/flash/media/AVStream.hx

@@ -19,12 +19,15 @@ extern class AVStream extends flash.events.EventDispatcher {
 	var volume : Float;
 	function new(source : AVSource) : Void;
 	function dispose() : Void;
+	function fastForward(rate : Float) : AVResult;
 	function pause() : AVResult;
 	function play() : AVResult;
 	function resume() : Bool;
+	function rewind(rate : Float) : AVResult;
 	function seek(offset : Float, inBufferSeek : Bool = true) : AVResult;
 	function seekToLivePoint() : AVResult;
 	function seekToLocalTime(periodIndex : Int, time : Float) : AVResult;
+	function setPlaySpeed(speed : Float, reserved : Float) : Void;
 	function step(frames : Int) : AVResult;
 	static var HARDWARE : String;
 	static var SOFTWARE : String;

+ 10 - 0
std/flash/media/StageVideoAvailabilityReason.hx

@@ -0,0 +1,10 @@
+package flash.media;
+
+extern class StageVideoAvailabilityReason {
+	function new() : Void;
+	static var DRIVER_TOO_OLD : String;
+	static var NO_ERROR : String;
+	static var UNAVAILABLE : String;
+	static var USER_DISABLED : String;
+	static var WMODE_INCOMPATIBLE : String;
+}

+ 1 - 0
std/flash/net/NetStream.hx

@@ -63,4 +63,5 @@ extern class NetStream extends flash.events.EventDispatcher {
 	function togglePause() : Void;
 	@:require(flash10) static var CONNECT_TO_FMS : String;
 	@:require(flash10) static var DIRECT_CONNECTIONS : String;
+	static function resetDRMVouchers() : Void;
 }

+ 1 - 0
std/flash/net/URLRequest.hx

@@ -8,4 +8,5 @@ package flash.net;
 	var requestHeaders : Array<URLRequestHeader>;
 	var url : String;
 	function new(?url : String) : Void;
+	function useRedirectedURL(sourceRequest : URLRequest, wholeURL : Bool = false, ?pattern : Dynamic, ?replace : String) : Void;
 }

+ 3 - 0
std/flash/net/drm/DRMManager.hx

@@ -5,8 +5,11 @@ extern class DRMManager extends flash.events.EventDispatcher {
 	function authenticate(serverURL : String, domain : String, username : String, password : String) : Void;
 	function loadPreviewVoucher(contentData : DRMContentData) : Void;
 	function loadVoucher(contentData : DRMContentData, setting : String) : Void;
+	function resetDRMVouchers() : Void;
+	function returnVoucher(inServerURL : String, immediateCommit : Bool, licenseID : String, policyID : String) : Void;
 	function setAuthenticationToken(serverUrl : String, domain : String, token : flash.utils.ByteArray) : Void;
 	function storeVoucher(voucher : flash.utils.ByteArray) : Void;
 	static var isSupported(default,null) : Bool;
+	static var networkIdleTimeout : Float;
 	static function getDRMManager() : DRMManager;
 }

+ 6 - 0
std/flash/net/drm/DRMReturnVoucherContext.hx

@@ -0,0 +1,6 @@
+package flash.net.drm;
+
+extern class DRMReturnVoucherContext extends DRMManagerSession {
+	function new() : Void;
+	function returnVoucher(inServerURL : String, immediateCommit : Bool, licenseID : String, policyID : String) : Void;
+}

+ 3 - 0
std/flash/net/drm/DRMVoucher.hx

@@ -1,10 +1,13 @@
 package flash.net.drm;
 
 extern class DRMVoucher {
+	var licenseID(default,null) : String;
 	var offlineLeaseEndDate(default,null) : Date;
 	var offlineLeaseStartDate(default,null) : Date;
 	var playbackTimeWindow(default,null) : DRMPlaybackTimeWindow;
 	var policies(default,null) : Dynamic;
+	var policyID(default,null) : String;
+	var serverURL(default,null) : String;
 	var voucherEndDate(default,null) : Date;
 	var voucherStartDate(default,null) : Date;
 	function new() : Void;

+ 1 - 0
std/flash/net/drm/VoucherAccessInfo.hx

@@ -4,5 +4,6 @@ package flash.net.drm;
 	var authenticationMethod(default,null) : String;
 	var displayName(default,null) : String;
 	var domain(default,null) : String;
+	var policyID(default,null) : String;
 	function new() : Void;
 }

+ 10 - 0
std/flash/system/ConnexionsClient.hx

@@ -0,0 +1,10 @@
+package flash.system;
+
+@:final extern class ConnexionsClient {
+	var enabled(default,null) : Bool;
+	function new() : Void;
+	function Connexions() : Dynamic;
+	function _init(port : Int, secret : String, topLocation : String, documentReferrer : String, windowLocation : String, movie : String, userAgent : String) : Void;
+	function autoAdd() : Dynamic;
+	function manualAdd() : Dynamic;
+}

+ 2 - 2
std/flash8/_std/Std.hx

@@ -26,8 +26,8 @@
 		return untyped flash.Boot.__instanceof(v,t);
 	}
 
-	public static function instance<T>( v : { }, c : Class<T> ) : T {
-		return Std.is(v, c) ? cast v : null;
+	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Std.is(value, c) ? cast value : null;
 	}
 	
 	public static function string( s : Dynamic ) : String {

+ 0 - 4
std/flash8/display/BitmapData.hx

@@ -1,9 +1,5 @@
 package flash.display;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 import flash.geom.Rectangle;
 import flash.geom.Point;
 

+ 0 - 4
std/flash8/filters/BitmapFilter.hx

@@ -1,9 +1,5 @@
 package flash.filters;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class BitmapFilter {
 
 }

+ 0 - 4
std/flash8/geom/ColorTransform.hx

@@ -1,9 +1,5 @@
 package flash.geom;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class ColorTransform {
 
 	var rgb : Float;

+ 0 - 4
std/flash8/geom/Matrix.hx

@@ -1,9 +1,5 @@
 package flash.geom;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class Matrix {
 
 	// 3x2 affine 2D matrix

+ 0 - 4
std/flash8/geom/Point.hx

@@ -1,9 +1,5 @@
 package flash.geom;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class Point<T> {
 
 	var x : T;

+ 0 - 4
std/flash8/geom/Rectangle.hx

@@ -1,9 +1,5 @@
 package flash.geom;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class Rectangle<T> {
 
 	var left : T;

+ 0 - 4
std/flash8/geom/Transform.hx

@@ -1,9 +1,5 @@
 package flash.geom;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class Transform {
 
 	var matrix : Matrix;

+ 0 - 4
std/flash8/net/FileReference.hx

@@ -1,9 +1,5 @@
 package flash.net;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class FileReference {
 
 	var creator : String;

+ 0 - 4
std/flash8/net/FileReferenceList.hx

@@ -1,9 +1,5 @@
 package flash.net;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class FileReferenceList {
 
 	var fileList : Array<Dynamic>;

+ 0 - 4
std/flash8/text/TextRenderer.hx

@@ -1,9 +1,5 @@
 package flash.text;
 
-#if !flash8
-"This class is only accesible in Flash8"
-#end
-
 extern class TextRenderer {
 
 	static var maxLevel : Float;

+ 42 - 5
std/haxe/Http.hx

@@ -153,6 +153,30 @@ class Http {
 	}
 	#end
 
+	#if (js || flash9)
+
+	#if js
+	var req:js.html.XMLHttpRequest;
+	#elseif flash9
+	var req:flash.net.URLLoader;
+	#end
+	
+	/**
+		Cancels `this` Http request if `request` has been called and a response 
+		has not yet been received.
+	**/
+	public function cancel()
+	{
+		if (req == null) return;
+		#if js
+		req.abort();
+		#elseif flash9
+		req.close();
+		#end
+		req = null;
+	}
+	#end
+
 	/**
 		Sends `this` Http request to the Url specified by `this.url`.
 
@@ -174,7 +198,7 @@ class Http {
 		var me = this;
 	#if js
 		me.responseData = null;
-		var r = js.Browser.createXMLHttpRequest();
+		var r = req = js.Browser.createXMLHttpRequest();
 		var onreadystatechange = function(_) {
 			if( r.readyState != 4 )
 				return;
@@ -183,16 +207,23 @@ class Http {
 				s = null;
 			if( s != null )
 				me.onStatus(s);
-			if( s != null && s >= 200 && s < 400 )
+			if( s != null && s >= 200 && s < 400 ) {
+				me.req = null;
 				me.onData(me.responseData = r.responseText);
-			else if ( s == null )
-				me.onError("Failed to connect or resolve host")
+			}
+			else if ( s == null ) {
+				me.req = null;
+				me.onError("Failed to connect or resolve host");
+			}
 			else switch( s ) {
 			case 12029:
+				me.req = null;
 				me.onError("Failed to connect to host");
 			case 12007:
+				me.req = null;
 				me.onError("Unknown host");
 			default:
+				me.req = null;
 				me.responseData = r.responseText;
 				me.onError("Http Error #"+r.status);
 			}
@@ -219,6 +250,7 @@ class Http {
 			} else
 				r.open("GET",url,async);
 		} catch( e : Dynamic ) {
+			me.req = null;
 			onError(e.toString());
 			return;
 		}
@@ -232,8 +264,9 @@ class Http {
 			onreadystatechange(null);
 	#elseif flash9
 		me.responseData = null;
-		var loader = new flash.net.URLLoader();
+		var loader = req = new flash.net.URLLoader();
 		loader.addEventListener( "complete", function(e) {
+			me.req = null;
 			me.responseData = loader.data;
 			me.onData( loader.data );
 		});
@@ -243,10 +276,12 @@ class Http {
 				me.onStatus( e.status );
 		});
 		loader.addEventListener( "ioError", function(e:flash.events.IOErrorEvent){
+			me.req = null;
 			me.responseData = loader.data;
 			me.onError(e.text);
 		});
 		loader.addEventListener( "securityError", function(e:flash.events.SecurityErrorEvent){
+			me.req = null;
 			me.onError(e.text);
 		});
 
@@ -283,6 +318,7 @@ class Http {
 		try {
 			loader.load( request );
 		}catch( e : Dynamic ){
+			me.req = null;
 			onError("Exception: "+Std.string(e));
 		}
 	#elseif flash
@@ -602,6 +638,7 @@ class Http {
 			var a = hline.split(": ");
 			var hname = a.shift();
 			var hval = if( a.length == 1 ) a[0] else a.join(": ");
+			hval = StringTools.ltrim( StringTools.rtrim( hval ) );
 			responseHeaders.set(hname, hval);
 			switch(hname.toLowerCase())
 			{

+ 17 - 453
std/haxe/Json.hx

@@ -24,467 +24,31 @@ package haxe;
 /**
 	Crossplatform JSON API : it will automatically use the optimized native API if available.
 	Use -D haxeJSON to force usage of the Haxe implementation even if a native API is found : this will provide
-	extra encoding features such as enums (replaced by their index), Hashs and Iterable.
+	extra encoding features such as enums (replaced by their index) and StringMaps.
 **/
-#if ((flash11 || (js && !old_browser)) && !haxeJSON)
-@:native('JSON') extern
-#end
 class Json {
 
-#if (haxeJSON || !(flash11 || (js && !old_browser)))
-	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
-	var str : String;
-	var pos : Int;
+	/**
+		Parses given JSON-encoded `text` and returns the resulting object.
 
-	function new() {
-	}
-
-	@:extern inline function addChar(c:Int) {
-		#if flash9
-		buf.writeByte(c);
-		#else
-		buf.addChar(c);
-		#end
-	}
-
-	@:extern inline function add(v:String) {
-		#if flash9
-		// argument is not always a string but will be automatically casted
-		buf.writeUTFBytes(v);
-		#else
-		buf.add(v);
-		#end
-	}
-
-	var replacer:Dynamic -> Dynamic -> Dynamic;
-
-	function toString(v:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic) {
-		#if flash9
-		buf = new flash.utils.ByteArray();
-		buf.endian = flash.utils.Endian.BIG_ENDIAN;
-		buf.position = 0;
-		#else
-		buf = new StringBuf();
-		#end
-		this.replacer = replacer;
-		toStringRec("", v);
-		return buf.toString();
-	}
-
-	function fieldsString( v : Dynamic, fields : Array<String> )
-	{
-		var first = true;
-		addChar('{'.code);
-		for( f in fields ) {
-			var value = Reflect.field(v,f);
-			if( Reflect.isFunction(value) ) continue;
-			if( first ) first = false else addChar(','.code);
-			quote(f);
-			addChar(':'.code);
-			toStringRec(f, value);
-		}
-		addChar('}'.code);
-	}
-
-	#if flash9
-	function classString ( v : Dynamic ) {
-		fieldsString(v,Type.getInstanceFields(Type.getClass(v)));
-	}
-	#end
-
-	function objString( v : Dynamic ) {
-		fieldsString(v,Reflect.fields(v));
-	}
-
-	function toStringRec(k:Dynamic, v:Dynamic) {
-		if (replacer != null) v = replacer(k, v);
-		switch( Type.typeof(v) ) {
-		case TUnknown:
-			add('"???"');
-		case TObject:
-			objString(v);
-		case TInt:
-			add(v);
-		case TFloat:
-			add(Math.isFinite(v) ? v : 'null');
-		case TFunction:
-			add('"<fun>"');
-		case TClass(c):
-			if( c == String )
-				quote(v);
-			else if( c == Array ) {
-				var v : Array<Dynamic> = v;
-				addChar('['.code);
-				var len = v.length;
-				if( len > 0 ) {
-					toStringRec(0, v[0]);
-					var i = 1;
-					while( i < len ) {
-						addChar(','.code);
-						toStringRec(i, v[i++]);
-					}
-				}
-				addChar(']'.code);
-			} else if( c == haxe.ds.StringMap ) {
-				var v : haxe.ds.StringMap<Dynamic> = v;
-				var o = {};
-				for( k in v.keys() )
-					Reflect.setField(o,k,v.get(k));
-				objString(o);
-			} else
-				#if flash9
-				classString(v);
-				#else
-				objString(v);
-				#end
-		case TEnum(_):
-			var i : Dynamic = Type.enumIndex(v);
-			add(i);
-		case TBool:
-			add(#if php (v ? 'true' : 'false') #else v #end);
-		case TNull:
-			add('null');
-		}
-	}
-
-	function quote( s : String ) {
-		#if (neko || php || cpp)
-		if( s.length != haxe.Utf8.length(s) ) {
-			quoteUtf8(s);
-			return;
-		}
-		#end
-		addChar('"'.code);
-		var i = 0;
-		while( true ) {
-			var c = StringTools.fastCodeAt(s, i++);
-			if( StringTools.isEof(c) ) break;
-			switch( c ) {
-			case '"'.code: add('\\"');
-			case '\\'.code: add('\\\\');
-			case '\n'.code: add('\\n');
-			case '\r'.code: add('\\r');
-			case '\t'.code: add('\\t');
-			case 8: add('\\b');
-			case 12: add('\\f');
-			default:
-				#if flash9
-				if( c >= 128 ) add(String.fromCharCode(c)) else addChar(c);
-				#else
-				addChar(c);
-				#end
-			}
-		}
-		addChar('"'.code);
-	}
-
-	#if (neko || php || cpp)
-	function quoteUtf8( s : String ) {
-		var u = new haxe.Utf8();
-		haxe.Utf8.iter(s,function(c) {
-			switch( c ) {
-			case '\\'.code, '"'.code: u.addChar('\\'.code); u.addChar(c);
-			case '\n'.code: u.addChar('\\'.code); u.addChar('n'.code);
-			case '\r'.code: u.addChar('\\'.code); u.addChar('r'.code);
-			case '\t'.code: u.addChar('\\'.code); u.addChar('t'.code);
-			case 8: u.addChar('\\'.code); u.addChar('b'.code);
-			case 12: u.addChar('\\'.code); u.addChar('f'.code);
-			default: u.addChar(c);
-			}
-		});
-		buf.add('"');
-		buf.add(u.toString());
-		buf.add('"');
-	}
-	#end
-
-	function doParse( str : String ) {
-		this.str = str;
-		this.pos = 0;
-		return parseRec();
-	}
-
-	function invalidChar() {
-		pos--; // rewind
-		throw "Invalid char "+StringTools.fastCodeAt(str,pos)+" at position "+pos;
-	}
-
-	inline function nextChar() {
-		return StringTools.fastCodeAt(str,pos++);
-	}
-
-	function parseRec() : Dynamic {
-		while( true ) {
-			var c = nextChar();
-			switch( c ) {
-			case ' '.code, '\r'.code, '\n'.code, '\t'.code:
-				// loop
-			case '{'.code:
-				var obj = {}, field = null, comma : Null<Bool> = null;
-				while( true ) {
-					var c = nextChar();
-					switch( c ) {
-					case ' '.code, '\r'.code, '\n'.code, '\t'.code:
-						// loop
-					case '}'.code:
-						if( field != null || comma == false )
-							invalidChar();
-						return obj;
-					case ':'.code:
-						if( field == null )
-							invalidChar();
-						Reflect.setField(obj,field,parseRec());
-						field = null;
-						comma = true;
-					case ','.code:
-						if( comma ) comma = false else invalidChar();
-					case '"'.code:
-						if( comma ) invalidChar();
-						field = parseString();
-					default:
-						invalidChar();
-					}
-				}
-			case '['.code:
-				var arr = [], comma : Null<Bool> = null;
-				while( true ) {
-					var c = nextChar();
-					switch( c ) {
-					case ' '.code, '\r'.code, '\n'.code, '\t'.code:
-						// loop
-					case ']'.code:
-						if( comma == false ) invalidChar();
-						return arr;
-					case ','.code:
-						if( comma ) comma = false else invalidChar();
-					default:
-						if( comma ) invalidChar();
-						pos--;
-						arr.push(parseRec());
-						comma = true;
-					}
-				}
-			case 't'.code:
-				var save = pos;
-				if( nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code ) {
-					pos = save;
-					invalidChar();
-				}
-				return true;
-			case 'f'.code:
-				var save = pos;
-				if( nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code ) {
-					pos = save;
-					invalidChar();
-				}
-				return false;
-			case 'n'.code:
-				var save = pos;
-				if( nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code ) {
-					pos = save;
-					invalidChar();
-				}
-				return null;
-			case '"'.code:
-				return parseString();
-			case '0'.code, '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code,'-'.code:
-				return parseNumber(c);
-			default:
-				invalidChar();
-			}
-		}
-	}
-
-	function parseString() {
-		var start = pos;
-		var buf = new StringBuf();
-		while( true ) {
-			var c = nextChar();
-			if( c == '"'.code )
-				break;
-			if( c == '\\'.code ) {
-				buf.addSub(str,start, pos - start - 1);
-				c = nextChar();
-				switch( c ) {
-				case "r".code: buf.addChar("\r".code);
-				case "n".code: buf.addChar("\n".code);
-				case "t".code: buf.addChar("\t".code);
-				case "b".code: buf.addChar(8);
-				case "f".code: buf.addChar(12);
-				case "/".code, '\\'.code, '"'.code: buf.addChar(c);
-				case 'u'.code:
-					var uc = Std.parseInt("0x" + str.substr(pos, 4));
-					pos += 4;
-					#if (neko || php || cpp)
-					if( uc <= 0x7F )
-						buf.addChar(uc);
-					else if( uc <= 0x7FF ) {
-						buf.addChar(0xC0 | (uc >> 6));
-						buf.addChar(0x80 | (uc & 63));
-					} else if( uc <= 0xFFFF ) {
-						buf.addChar(0xE0 | (uc >> 12));
-						buf.addChar(0x80 | ((uc >> 6) & 63));
-						buf.addChar(0x80 | (uc & 63));
-					} else {
-						buf.addChar(0xF0 | (uc >> 18));
-						buf.addChar(0x80 | ((uc >> 12) & 63));
-						buf.addChar(0x80 | ((uc >> 6) & 63));
-						buf.addChar(0x80 | (uc & 63));
-					}
-					#else
-					buf.addChar(uc);
-					#end
-				default:
-					throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1);
-				}
-				start = pos;
-			}
-			#if (neko || php || cpp)
-			// ensure utf8 chars are not cut
-			else if( c >= 0x80 ) {
-				pos++;
-				if( c >= 0xFC ) pos += 4;
-				else if( c >= 0xF8 ) pos += 3;
-				else if( c >= 0xF0 ) pos += 2;
-				else if( c >= 0xE0 ) pos++;
-			}
-			#end
-			else if( StringTools.isEof(c) )
-				throw "Unclosed string";
-		}
-		buf.addSub(str,start, pos - start - 1);
-		return buf.toString();
-	}
-
-	function invalidNumber( start : Int ) {
-		throw "Invalid number at position "+start+": " + str.substr(start, pos - start);
-	}
+		JSON objects are parsed into anonymous structures and JSON arrays
+		are parsed into Array<Dynamic>.
 
-	inline function parseNumber( c : Int ) {
-		var start = pos - 1;
-		var minus = c == '-'.code, digit = !minus, zero = c == '0'.code;
-		var point = false, e = false, pm = false, end = false;
-		while( true ) {
-			c = nextChar();
-			switch( c ) {
-				case '0'.code :
-					if (zero && !point) invalidNumber(start);
-					if (minus) {
-						minus = false; zero = true;
-					}
-					digit = true;
-				case '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code :
-					if (zero && !point) invalidNumber(start);
-					if (minus) minus = false;
-					digit = true; zero = false;
-				case '.'.code :
-					if (minus || point) invalidNumber(start);
-					digit = false; point = true;
-				case 'e'.code, 'E'.code :
-					if (minus || zero || e) invalidNumber(start);
-					digit = false; e = true;
-				case '+'.code, '-'.code :
-					if (!e || pm) invalidNumber(start);
-					digit = false; pm = true;
-				default :
-					if (!digit) invalidNumber(start);
-					pos--;
-					end = true;
-			}
-			if (end) break;
-		}
-		var f = Std.parseFloat(str.substr(start, pos - start));
-		var i = Std.int(f);
-		return if( i == f ) i else f;
+		If given `text` is not valid JSON, an exception will be thrown.
+	**/
+	public static inline function parse( text : String ) : Dynamic {
+		return haxe.format.JsonParser.parse(text);
 	}
 
-#end
+	/**
+		Encodes given `value` and returns the resulting JSON string.
 
-	public static function parse( text : String ) : Dynamic {
-		#if (php && !haxeJSON)
-		return phpJsonDecode(text);
-		#elseif (flash11 && !haxeJSON)
-		return null;
-		#else
-		return new Json().doParse(text);
-		#end
+		If `replacer` is given and is not null, it is used to retrieve
+		actual object to be encoded. The `replacer` function two parameters,
+		the key and the value being encoded. Initial key value is an empty string.
+	**/
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer);
 	}
 
-	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		#if (php && !haxeJSON)
-		return phpJsonEncode(value, replacer);
-		#elseif (flash11 && !haxeJSON)
-		return null;
-		#else
-		return new Json().toString(value, replacer);
-		#end
-	}
-
-	#if !haxeJSON
-		#if (js && old_browser)
-		static function __init__() untyped {
-			if( __js__('typeof(JSON)') != 'undefined' )
-				Json = __js__('JSON');
-		}
-		#end
-	#end
-
-	#if php
-	static function phpJsonDecode(json:String):Dynamic {
-		var val = untyped __call__("json_decode", json);
-		return convertAfterDecode(val);
-	}
-
-	static function convertAfterDecode(val:Dynamic):Dynamic {
-		var arr:php.NativeArray;
-		if (untyped __call__("is_object", val)) {
-			arr = phpMapArray(php.Lib.associativeArrayOfObject(val), convertAfterDecode);
-			return untyped __call__("_hx_anonymous", arr);
-		}
-		else if (untyped __call__("is_array", val)) {
-			arr = phpMapArray(val, convertAfterDecode);
-			return php.Lib.toHaxeArray(arr);
-		}
-		else
-			return val;
-	}
-
-	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic):String {
-		if(null != replacer)
-			return new Json().toString(val, replacer);
-		var json = untyped __call__("json_encode", convertBeforeEncode(val));
-		if (untyped __physeq__(json, false))
-			return throw "invalid json";
-		else
-			return json;
-	}
-
-	static function convertBeforeEncode(val:Dynamic):Dynamic {
-		var arr:php.NativeArray;
-		if (untyped __call__("is_object", val)) {
-			switch (untyped __call__("get_class", val)) {
-				case "_hx_anonymous", "stdClass" : arr = php.Lib.associativeArrayOfObject(val);
-				case "_hx_array" : arr = php.Lib.toPhpArray(val);
-				case "Date" : return Std.string(val); //.split(" ").join("T"); //better with "T"?
-				case "HList" : arr = php.Lib.toPhpArray(Lambda.array(val)); //convert List to array?
-				case "_hx_enum" : return Type.enumIndex(val);
-				case "StringMap", "IntMap" : arr = php.Lib.associativeArrayOfHash(val);
-				default : arr = php.Lib.associativeArrayOfObject(val);
-			}
-		}
-		else if (untyped __call__("is_array", val)) arr = val;
-		else {
-			if (untyped __call__("is_float",val) && !__call__("is_finite",val)) val = null;
-			return val;
-		}
-		return phpMapArray(arr, convertBeforeEncode);
-	}
-
-	inline static function phpMapArray(arr:php.NativeArray
-	, func:Dynamic->Dynamic):php.NativeArray {
-		return untyped __call__("array_map", func, arr);
-	}
-
-	#end
-
 }

+ 2 - 2
std/haxe/Resource.hx

@@ -99,7 +99,7 @@ class Resource {
 				return new String(x.data);
 				#else
 				if( x.str != null ) return x.str;
-				var b : haxe.io.Bytes = haxe.Unserializer.run(x.data);
+				var b : haxe.io.Bytes = haxe.crypto.Base64.decode(x.data);
 				return b.toString();
 				#end
 			}
@@ -133,7 +133,7 @@ class Resource {
 				return haxe.io.Bytes.ofData(cast x.data);
 				#else
 				if( x.str != null ) return haxe.io.Bytes.ofString(x.str);
-				return haxe.Unserializer.run(x.data);
+				return haxe.crypto.Base64.decode(x.data);
 				#end
 			}
 		return null;

+ 1 - 1
std/haxe/Template.hx

@@ -96,7 +96,7 @@ class Template {
 
 		If `macros` has a field 'name', all occurrences of $$name(args) are
 		replaced with the result of calling that field. The first argument is
-		always the the resolve() method, followed by the given arguments.
+		always the resolve() method, followed by the given arguments.
 		If `macros` has no such field, the result is unspecified.
 
 		If `context` is null, the result is unspecified. If `macros` is null,

+ 43 - 12
std/haxe/Timer.hx

@@ -28,15 +28,22 @@ package haxe;
 	The intended usage is to create an instance of the Timer class with a given
 	interval, set its run() method to a custom function to be invoked and
 	eventually call stop() to stop the Timer.
+
+	Note that a running Timer may or may not prevent the program to exit 
+	automatically when main() returns.
 	
 	It is also possible to extend this class and override its run() method in
 	the child class.
 **/
 class Timer {
-	#if (neko || php || cpp)
-	#else
+	#if (flash || js || java)
 
-	private var id : Null<Int>;
+	#if (flash || js)
+		private var id : Null<Int>;
+	#elseif java
+		private var timer : java.util.Timer;
+		private var task : java.util.TimerTask;
+	#end
 
 	/**
 		Creates a new timer that will run every `time_ms` milliseconds.
@@ -59,6 +66,9 @@ class Timer {
 		#elseif js
 			var me = this;
 			id = untyped setInterval(function() me.run(),time_ms);
+		#elseif java
+			timer = new java.util.Timer();
+			timer.scheduleAtFixedRate(task = new TimerTask(this), haxe.Int64.ofInt(time_ms), haxe.Int64.ofInt(time_ms));
 		#end
 	}
 
@@ -71,16 +81,22 @@ class Timer {
 		It is not possible to restart `this` Timer once stopped.
 	**/
 	public function stop() {
-		if( id == null )
-			return;
-		#if flash9
-			untyped __global__["flash.utils.clearInterval"](id);
-		#elseif flash
-			untyped _global["clearInterval"](id);
-		#elseif js
-			untyped clearInterval(id);
+		#if (flash || js)
+			if( id == null )
+				return;
+			#if flash9
+				untyped __global__["flash.utils.clearInterval"](id);
+			#elseif flash
+				untyped _global["clearInterval"](id);
+			#elseif js
+				untyped clearInterval(id);
+			#end
+			id = null;
+		#elseif java
+			timer.cancel();
+			timer = null;
+			task = null;
 		#end
-		id = null;
 	}
 
 	/**
@@ -159,3 +175,18 @@ class Timer {
 	}
 
 }
+
+#if java
+@:nativeGen
+private class TimerTask extends java.util.TimerTask {
+	var timer:Timer;
+	public function new(timer:Timer):Void {
+		super();
+		this.timer = timer;
+	}
+
+	@:overload public function run():Void {
+		timer.run();
+	}
+}
+#end

+ 1 - 1
std/haxe/crypto/Base64.hx

@@ -32,7 +32,7 @@ class Base64 {
 	public static function encode( bytes : haxe.io.Bytes, complement = true ) : String {
 		var str = new BaseCode(BYTES).encodeBytes(bytes).toString();
 		if( complement )
-			for( i in 0...(bytes.length*4)%3 )
+			for( i in 0...(3-(bytes.length*4)%3)%3 )
 				str += "=";
 		return str;
 	}

+ 1 - 0
std/haxe/ds/Vector.hx

@@ -173,6 +173,7 @@ abstract Vector<T>(VectorData<T>) {
 
 		If `array` is null, the result is unspecified.
 	**/
+	#if as3 @:extern #end
 	static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
 		// TODO: Optimize this for flash (and others?)
 		var vec = new Vector<T>(array.length);

+ 210 - 0
std/haxe/format/JsonParser.hx

@@ -0,0 +1,210 @@
+package haxe.format;
+
+class JsonParser {
+
+	static public inline function parse(str : String) : Dynamic {
+		return new JsonParser(str).parseRec();
+	}
+
+	var str : String;
+	var pos : Int;
+
+	function new( str : String ) {
+		this.str = str;
+		this.pos = 0;
+	}
+
+	function parseRec() : Dynamic {
+		while( true ) {
+			var c = nextChar();
+			switch( c ) {
+			case ' '.code, '\r'.code, '\n'.code, '\t'.code:
+				// loop
+			case '{'.code:
+				var obj = {}, field = null, comma : Null<Bool> = null;
+				while( true ) {
+					var c = nextChar();
+					switch( c ) {
+					case ' '.code, '\r'.code, '\n'.code, '\t'.code:
+						// loop
+					case '}'.code:
+						if( field != null || comma == false )
+							invalidChar();
+						return obj;
+					case ':'.code:
+						if( field == null )
+							invalidChar();
+						Reflect.setField(obj,field,parseRec());
+						field = null;
+						comma = true;
+					case ','.code:
+						if( comma ) comma = false else invalidChar();
+					case '"'.code:
+						if( comma ) invalidChar();
+						field = parseString();
+					default:
+						invalidChar();
+					}
+				}
+			case '['.code:
+				var arr = [], comma : Null<Bool> = null;
+				while( true ) {
+					var c = nextChar();
+					switch( c ) {
+					case ' '.code, '\r'.code, '\n'.code, '\t'.code:
+						// loop
+					case ']'.code:
+						if( comma == false ) invalidChar();
+						return arr;
+					case ','.code:
+						if( comma ) comma = false else invalidChar();
+					default:
+						if( comma ) invalidChar();
+						pos--;
+						arr.push(parseRec());
+						comma = true;
+					}
+				}
+			case 't'.code:
+				var save = pos;
+				if( nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code ) {
+					pos = save;
+					invalidChar();
+				}
+				return true;
+			case 'f'.code:
+				var save = pos;
+				if( nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code ) {
+					pos = save;
+					invalidChar();
+				}
+				return false;
+			case 'n'.code:
+				var save = pos;
+				if( nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code ) {
+					pos = save;
+					invalidChar();
+				}
+				return null;
+			case '"'.code:
+				return parseString();
+			case '0'.code, '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code,'-'.code:
+				return parseNumber(c);
+			default:
+				invalidChar();
+			}
+		}
+	}
+
+	function parseString() {
+		var start = pos;
+		var buf = new StringBuf();
+		while( true ) {
+			var c = nextChar();
+			if( c == '"'.code )
+				break;
+			if( c == '\\'.code ) {
+				buf.addSub(str,start, pos - start - 1);
+				c = nextChar();
+				switch( c ) {
+				case "r".code: buf.addChar("\r".code);
+				case "n".code: buf.addChar("\n".code);
+				case "t".code: buf.addChar("\t".code);
+				case "b".code: buf.addChar(8);
+				case "f".code: buf.addChar(12);
+				case "/".code, '\\'.code, '"'.code: buf.addChar(c);
+				case 'u'.code:
+					var uc = Std.parseInt("0x" + str.substr(pos, 4));
+					pos += 4;
+					#if (neko || php || cpp)
+					if( uc <= 0x7F )
+						buf.addChar(uc);
+					else if( uc <= 0x7FF ) {
+						buf.addChar(0xC0 | (uc >> 6));
+						buf.addChar(0x80 | (uc & 63));
+					} else if( uc <= 0xFFFF ) {
+						buf.addChar(0xE0 | (uc >> 12));
+						buf.addChar(0x80 | ((uc >> 6) & 63));
+						buf.addChar(0x80 | (uc & 63));
+					} else {
+						buf.addChar(0xF0 | (uc >> 18));
+						buf.addChar(0x80 | ((uc >> 12) & 63));
+						buf.addChar(0x80 | ((uc >> 6) & 63));
+						buf.addChar(0x80 | (uc & 63));
+					}
+					#else
+					buf.addChar(uc);
+					#end
+				default:
+					throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1);
+				}
+				start = pos;
+			}
+			#if (neko || php || cpp)
+			// ensure utf8 chars are not cut
+			else if( c >= 0x80 ) {
+				pos++;
+				if( c >= 0xFC ) pos += 4;
+				else if( c >= 0xF8 ) pos += 3;
+				else if( c >= 0xF0 ) pos += 2;
+				else if( c >= 0xE0 ) pos++;
+			}
+			#end
+			else if( StringTools.isEof(c) )
+				throw "Unclosed string";
+		}
+		buf.addSub(str,start, pos - start - 1);
+		return buf.toString();
+	}
+
+	inline function parseNumber( c : Int ) : Dynamic {
+		var start = pos - 1;
+		var minus = c == '-'.code, digit = !minus, zero = c == '0'.code;
+		var point = false, e = false, pm = false, end = false;
+		while( true ) {
+			c = nextChar();
+			switch( c ) {
+				case '0'.code :
+					if (zero && !point) invalidNumber(start);
+					if (minus) {
+						minus = false; zero = true;
+					}
+					digit = true;
+				case '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code :
+					if (zero && !point) invalidNumber(start);
+					if (minus) minus = false;
+					digit = true; zero = false;
+				case '.'.code :
+					if (minus || point) invalidNumber(start);
+					digit = false; point = true;
+				case 'e'.code, 'E'.code :
+					if (minus || zero || e) invalidNumber(start);
+					digit = false; e = true;
+				case '+'.code, '-'.code :
+					if (!e || pm) invalidNumber(start);
+					digit = false; pm = true;
+				default :
+					if (!digit) invalidNumber(start);
+					pos--;
+					end = true;
+			}
+			if (end) break;
+		}
+		var f = Std.parseFloat(str.substr(start, pos - start));
+		var i = Std.int(f);
+		return if( i == f ) i else f;
+	}
+
+	inline function nextChar() {
+		return StringTools.fastCodeAt(str,pos++);
+	}
+
+	function invalidChar() {
+		pos--; // rewind
+		throw "Invalid char "+StringTools.fastCodeAt(str,pos)+" at position "+pos;
+	}
+
+	function invalidNumber( start : Int ) {
+		throw "Invalid number at position "+start+": " + str.substr(start, pos - start);
+	}
+}

+ 168 - 0
std/haxe/format/JsonPrinter.hx

@@ -0,0 +1,168 @@
+package haxe.format;
+
+class JsonPrinter {
+
+	static public function print(o:Dynamic, replacer:Dynamic -> Dynamic -> Dynamic) : String {
+		var printer = new JsonPrinter(replacer);
+		printer.write("", o);
+		return printer.buf.toString();
+	}
+
+	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
+	var replacer : Dynamic -> Dynamic -> Dynamic;
+	
+	function new(replacer:Dynamic -> Dynamic -> Dynamic) {
+		this.replacer = replacer;
+
+		#if flash9
+		buf = new flash.utils.ByteArray();
+		buf.endian = flash.utils.Endian.BIG_ENDIAN;
+		buf.position = 0;
+		#else
+		buf = new StringBuf();
+		#end
+	}
+
+	function write(k:Dynamic, v:Dynamic) {
+		if (replacer != null) v = replacer(k, v);
+		switch( Type.typeof(v) ) {
+		case TUnknown:
+			add('"???"');
+		case TObject:
+			objString(v);
+		case TInt:
+			add(v);
+		case TFloat:
+			add(Math.isFinite(v) ? v : 'null');
+		case TFunction:
+			add('"<fun>"');
+		case TClass(c):
+			if( c == String )
+				quote(v);
+			else if( c == Array ) {
+				var v : Array<Dynamic> = v;
+				addChar('['.code);
+				var len = v.length;
+				if( len > 0 ) {
+					write(0, v[0]);
+					var i = 1;
+					while( i < len ) {
+						addChar(','.code);
+						write(i, v[i++]);
+					}
+				}
+				addChar(']'.code);
+			} else if( c == haxe.ds.StringMap ) {
+				var v : haxe.ds.StringMap<Dynamic> = v;
+				var o = {};
+				for( k in v.keys() )
+					Reflect.setField(o,k,v.get(k));
+				objString(o);
+			} else
+				#if flash9
+				classString(v);
+				#else
+				objString(v);
+				#end
+		case TEnum(_):
+			var i : Dynamic = Type.enumIndex(v);
+			add(i);
+		case TBool:
+			add(#if php (v ? 'true' : 'false') #else v #end);
+		case TNull:
+			add('null');
+		}
+	}
+
+	@:extern inline function addChar(c:Int) {
+		#if flash9
+		buf.writeByte(c);
+		#else
+		buf.addChar(c);
+		#end
+	}
+
+	@:extern inline function add(v:String) {
+		#if flash9
+		// argument is not always a string but will be automatically casted
+		buf.writeUTFBytes(v);
+		#else
+		buf.add(v);
+		#end
+	}
+
+	#if flash9
+	function classString ( v : Dynamic ) {
+		fieldsString(v,Type.getInstanceFields(Type.getClass(v)));
+	}
+	#end
+
+	inline function objString( v : Dynamic ) {
+		fieldsString(v,Reflect.fields(v));
+	}
+
+	function fieldsString( v : Dynamic, fields : Array<String> ) {
+		var first = true;
+		addChar('{'.code);
+		for( f in fields ) {
+			var value = Reflect.field(v,f);
+			if( Reflect.isFunction(value) ) continue;
+			if( first ) first = false else addChar(','.code);
+			quote(f);
+			addChar(':'.code);
+			write(f, value);
+		}
+		addChar('}'.code);
+	}
+
+	function quote( s : String ) {
+		#if (neko || php || cpp)
+		if( s.length != haxe.Utf8.length(s) ) {
+			quoteUtf8(s);
+			return;
+		}
+		#end
+		addChar('"'.code);
+		var i = 0;
+		while( true ) {
+			var c = StringTools.fastCodeAt(s, i++);
+			if( StringTools.isEof(c) ) break;
+			switch( c ) {
+			case '"'.code: add('\\"');
+			case '\\'.code: add('\\\\');
+			case '\n'.code: add('\\n');
+			case '\r'.code: add('\\r');
+			case '\t'.code: add('\\t');
+			case 8: add('\\b');
+			case 12: add('\\f');
+			default:
+				#if flash9
+				if( c >= 128 ) add(String.fromCharCode(c)) else addChar(c);
+				#else
+				addChar(c);
+				#end
+			}
+		}
+		addChar('"'.code);
+	}
+
+	#if (neko || php || cpp)
+	function quoteUtf8( s : String ) {
+		var u = new haxe.Utf8();
+		haxe.Utf8.iter(s,function(c) {
+			switch( c ) {
+			case '\\'.code, '"'.code: u.addChar('\\'.code); u.addChar(c);
+			case '\n'.code: u.addChar('\\'.code); u.addChar('n'.code);
+			case '\r'.code: u.addChar('\\'.code); u.addChar('r'.code);
+			case '\t'.code: u.addChar('\\'.code); u.addChar('t'.code);
+			case 8: u.addChar('\\'.code); u.addChar('b'.code);
+			case 12: u.addChar('\\'.code); u.addChar('f'.code);
+			default: u.addChar(c);
+			}
+		});
+		buf.add('"');
+		buf.add(u.toString());
+		buf.add('"');
+	}
+	#end
+}

+ 10 - 7
std/haxe/io/Path.hx

@@ -199,20 +199,23 @@ class Path {
 	}
 	
 	/**
-		Removes a trailing slash from `path` if it exists.
+		Removes trailing slashes from `path`.
 		
 		If `path` does not end with a `/` or `\`, `path` is returned unchanged.
 		
-		Otherwise the substring of `path` excluding the trailing slash or
-		backslash is returned.
+		Otherwise the substring of `path` excluding the trailing slashes or
+		backslashes is returned.
 		
 		If `path` is null, the result is unspecified.
 	**/
 	@:require(haxe_ver >= 3.01)
-	public static function removeTrailingSlash ( path : String ) : String {
-		return switch(path.charCodeAt(path.length - 1)) {
-			case '/'.code | '\\'.code: path.substr(0, -1);
-			case _: path;
+	public static function removeTrailingSlashes ( path : String ) : String {
+		while (true) {
+			switch(path.charCodeAt(path.length - 1)) {
+				case '/'.code | '\\'.code: path = path.substr(0, -1);
+				case _: break;
+			}
 		}
+		return path;
 	}
 }

+ 0 - 136
std/haxe/macro/Build.hx

@@ -1,136 +0,0 @@
-/*
- * Copyright (C)2005-2012 Haxe Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-package haxe.macro;
-
-import haxe.macro.Context;
-import haxe.macro.Expr;
-import haxe.macro.Type;
-
-using haxe.macro.Tools;
-
-class Build {
-	macro static public function buildEnumAbstract():Array<Field> {
-		var fields = Context.getBuildFields();
-		var a = switch(Context.getLocalClass().get().kind) {
-			case KAbstractImpl(a): a;
-			case _: throw "";
-		}
-		var aT = a.get();
-		var tThis = aT.type;
-		var ctA = TAbstract(a, aT.params.map(function(tp) return tp.t));
-		for (field in fields) {
-			// allow extra static fields
-			if( Lambda.has(field.access,AStatic) )
-				continue;
-			switch(field.kind) {
-				case FVar(t, e):
-					field.access = [AStatic,APublic,AInline];
-					if (e == null) Context.error("Value required", field.pos);
-					var monos = aT.params.map(function(_) return Context.typeof(macro null));
-					var tF = ctA.applyTypeParameters(aT.params, monos);
-					if (t != null) {
-						switch(t.toType().follow()) {
-							case t = TAbstract(a2, tl2) if (a.toString() == a2.toString()): tF = t;
-							case _: Context.error("Explicit field type must be " + ctA.toString(), field.pos);
-						}
-					}
-					var tE = Context.typeof(e);
-					if (!Context.unify(tE, tThis)) Context.error('${tE.toString()} should be ${tThis.toString()}', e.pos);
-					field.meta.push({name: ":impl", params: [], pos: field.pos});
-					field.meta.push({name: ":enum", params: [], pos: field.pos});
-					field.kind = FVar(tF.toComplexType(), macro cast $e);
-				case _:
-			}
-		}
-		return fields;
-	}
-
-	macro static public function exposeUnderlyingFields(fieldExprs:Array<Expr>):Array<Field> {
-		var fields = Context.getBuildFields();
-		var a = switch(Context.getLocalClass().get().kind) {
-			case KAbstractImpl(a): a;
-			case _: throw "";
-		}
-		var tThis = a.get().type;
-		var map:Type->Type = function(t) return t;
-		var c = switch(tThis.follow()) {
-			case TInst(c, tl):
-				var c = c.get();
-				if (tl.length > 0) map = function(t) {
-					var t2 = t.applyTypeParameters(c.params, tl);
-					return t2;
-				}
-				c;
-			case _: Context.error("Underlying type of exposing abstract must be a class", Context.currentPos());
-		}
-		function getIdentNames(e) return switch(e.expr) {
-			case EConst(CIdent(s)): { field : s, newField : s };
-			case EBinop(OpArrow, { expr : EConst(CIdent(s1))}, { expr: EConst(CIdent(s2))}): { field: s1, newField : s2 };
-			case _: Context.error("Identifier or (Identifier => Identifier) expected", e.pos);
-		}
-		function toField(cf:ClassField, oldName:String, newName:String) {
-			return {
-				name: newName,
-				doc: cf.doc,
-				access: [AStatic, APublic, AInline],
-				pos: cf.pos,
-				meta: [{name: ":impl", params: [], pos: cf.pos}],
-				kind: switch(cf.type.follow()) {
-					case TFun(args, ret):
-						var args = args.map(function(arg) return {
-							name: arg.name,
-							opt: arg.opt,
-							type: arg.t.toComplexType(),
-							value: null
-						});
-						var expr = macro return this.$oldName($a{args.map(function(arg) return macro $i{arg.name})});
-						args.unshift({name: "this", type: null, opt:false, value: null});
-						FFun({
-							args: args,
-							ret: ret.toComplexType(),
-							expr: expr,
-							params: cf.params.map(function(param) return {
-								name: param.name,
-								constraints: [],
-								params: []
-							})
-						});
-					case _: throw "";
-				}
-			}
-		}
-		for (fieldExpr in fieldExprs) {
-			var fieldNames = getIdentNames(fieldExpr);
-			var fieldName = fieldNames.field;
-			var cField = c.findField(fieldName, false);
-			if (cField == null) Context.error('Underlying type has no field $fieldName', fieldExpr.pos);
-			switch(cField.kind) {
-				case FMethod(_):
-				case _: Context.error("Only function fields can be exposed", fieldExpr.pos);
-			}
-			cField.type = map(cField.type);
-			var field = toField(cField, fieldName, fieldNames.newField);
-			fields.push(field);
-		}
-		return fields;
-	}
-}

+ 31 - 0
std/haxe/macro/Context.hx

@@ -97,6 +97,22 @@ class Context {
 		return load("curpos", 0)();
 	}
 
+	/**
+		Returns the type which is expected at the place the macro is called.
+		
+		This affects usages such as `var x:Int = macroCall()`, where the
+		expected type will be reported as Int.
+		
+		Might return null if no specific type is expected or if the calling
+		macro is not an expression-macro.
+	**/
+	@:require(haxe_ver >= 3.01)
+	public static function getExpectedType():Null<Type> {
+		var l : Type = load("expected_type", 0)();
+		if( l == null ) return null;
+		return l;
+	}
+	
 	/**
 		Returns the current class in which the macro was called.
 		
@@ -348,6 +364,21 @@ class Context {
 		return load("make_pos",3)(inf.min,inf.max,untyped inf.file.__s);
 	}
 
+	/**
+		Returns a map of all registered resources for this compilation unit.
+
+		Modifying the returned map has no effect on the compilation, use
+		`haxe.macro.Context.addResource` to add new resources to the compilation unit.
+	**/
+	public static function getResources():haxe.ds.StringMap<haxe.io.Bytes> {
+		var x:haxe.ds.StringMap<neko.NativeString> = load("get_resources",0)();
+		var r = new haxe.ds.StringMap();
+		for (k in x.keys()) {
+			r.set(k, haxe.io.Bytes.ofData(x.get(k)));
+		} 
+		return r;
+	}
+
 	/**
 		Makes resource `data` available as `name`.
 		

+ 1 - 0
std/haxe/macro/Expr.hx

@@ -132,6 +132,7 @@ enum Binop {
 		`|=`
 		`&=`
 		`^=`
+		`%=`
 	**/
 	OpAssignOp( op : Binop );
 	/**

+ 34 - 19
std/haxe/macro/Printer.hx

@@ -99,7 +99,7 @@ class Printer {
 		case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}";
 		case TParent(ct): "(" + printComplexType(ct) + ")";
 		case TOptional(ct): "?" + printComplexType(ct);
-		case TExtend(tpl, fields): '{${tpl.map(printTypePath).join(", ")} >, ${fields.map(printField).join(", ")} }';
+		case TExtend(tpl, fields): '{> ${tpl.map(printTypePath).join(" >, ")}, ${fields.map(printField).join(", ")} }';
 	}
 
 	public function printMetadata(meta:MetadataEntry) return
@@ -118,7 +118,7 @@ class Printer {
 	
 	public function printField(field:Field) return
 		(field.doc != null && field.doc != "" ? "/**\n" + tabs + tabString + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + "\n" + tabs + "**/\n" + tabs : "")
-		+ (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "")
+		+ (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join('\n$tabs') + '\n$tabs' : "")
 		+ (field.access != null && field.access.length > 0 ? field.access.map(printAccess).join(" ") + " " : "")
 		+ switch(field.kind) {
 		  case FVar(t, eo): 'var ${field.name}' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = ");
@@ -134,18 +134,18 @@ class Printer {
 	public function printFunctionArg(arg:FunctionArg) return
 		(arg.opt ? "?" : "")
 		+ arg.name
-		+ opt(arg.type, printComplexType, " : ")
+		+ opt(arg.type, printComplexType, ":")
 		+ opt(arg.value, printExpr, " = ");
 
 	public function printFunction(func:Function) return
 		(func.params.length > 0 ? "<" + func.params.map(printTypeParamDecl).join(", ") + ">" : "")
-		+ "( " + func.args.map(printFunctionArg).join(", ") + " )"
-		+ opt(func.ret, printComplexType, " : ")
+		+ "(" + func.args.map(printFunctionArg).join(", ") + ")"
+		+ opt(func.ret, printComplexType, ":")
 		+ opt(func.expr, printExpr, " ");
 
 	public function printVar(v:Var) return
 		v.name
-		+ opt(v.type, printComplexType, " : ")
+		+ opt(v.type, printComplexType, ":")
 		+ opt(v.expr, printExpr, " = ");
 
 
@@ -156,43 +156,44 @@ class Printer {
 		case EField(e1, n): '${printExpr(e1)}.$n';
 		case EParenthesis(e1): '(${printExpr(e1)})';
 		case EObjectDecl(fl):
-			"{ " + fl.map(function(fld) return '${fld.field} : ${printExpr(fld.expr)} ').join(",") + "}";
+			"{ " + fl.map(function(fld) return '${fld.field} : ${printExpr(fld.expr)}').join(", ") + " }";
 		case EArrayDecl(el): '[${printExprs(el, ", ")}]';
 		case ECall(e1, el): '${printExpr(e1)}(${printExprs(el,", ")})';
 		case ENew(tp, el): 'new ${printTypePath(tp)}(${printExprs(el,", ")})';
 		case EUnop(op, true, e1): printExpr(e1) + printUnop(op);
 		case EUnop(op, false, e1): printUnop(op) + printExpr(e1);
 		case EFunction(no, func) if (no != null): 'function $no' + printFunction(func);
-		case EFunction(_, func): "function " +printFunction(func);
+		case EFunction(_, func): "function" +printFunction(func);
 		case EVars(vl): "var " +vl.map(printVar).join(", ");
-		case EBlock([]): '{\n$tabs}';
+		case EBlock([]): '{ }';
 		case EBlock(el):
 			var old = tabs;
 			tabs += tabString;
 			var s = '{\n$tabs' + printExprs(el, ';\n$tabs');
 			tabs = old;
 			s + ';\n$tabs}';
-		case EFor(e1, e2): 'for(${printExpr(e1)}) ${printExpr(e2)}';
+		case EFor(e1, e2): 'for (${printExpr(e1)}) ${printExpr(e2)}';
 		case EIn(e1, e2): '${printExpr(e1)} in ${printExpr(e2)}';
-		case EIf(econd, eif, eelse): 'if(${printExpr(econd)}) ${printExpr(eif)} ${opt(eelse,printExpr,"else ")}';
-		case EWhile(econd, e1, true): 'while(${printExpr(econd)}) ${printExpr(e1)}';
-		case EWhile(econd, e1, false): 'do ${printExpr(e1)} while(${printExpr(econd)})';
+		case EIf(econd, eif, null): 'if (${printExpr(econd)}) ${printExpr(eif)}';
+		case EIf(econd, eif, eelse): 'if (${printExpr(econd)}) ${printExpr(eif)} else ${printExpr(eelse)}';
+		case EWhile(econd, e1, true): 'while (${printExpr(econd)}) ${printExpr(e1)}';
+		case EWhile(econd, e1, false): 'do ${printExpr(e1)} while (${printExpr(econd)})';
 		case ESwitch(e1, cl, edef):
 			var old = tabs;
 			tabs += tabString;
 			var s = 'switch ${printExpr(e1)} {\n$tabs' +
 				cl.map(function(c)
 					return 'case ${printExprs(c.values, ", ")}'
-						+ (c.guard != null ? ' if(${printExpr(c.guard)}): ' : ":")
+						+ (c.guard != null ? ' if (${printExpr(c.guard)}):' : ":")
 						+ (c.expr != null ? (opt(c.expr, printExpr)) + ";" : ""))
 				.join('\n$tabs');
 			if (edef != null)
-				s += '\n${tabs}default: ' + (edef.expr == null ? "" : printExpr(edef) + ";");
+				s += '\n${tabs}default:' + (edef.expr == null ? "" : printExpr(edef) + ";");
 			tabs = old;
 			s + '\n$tabs}';
 		case ETry(e1, cl):
 			'try ${printExpr(e1)}'
-			+ cl.map(function(c) return ' catch(${c.name} : ${printComplexType(c.type)}) ${printExpr(c.expr)}').join("");
+			+ cl.map(function(c) return ' catch(${c.name}:${printComplexType(c.type)}) ${printExpr(c.expr)}').join("");
 		case EReturn(eo): "return" + opt(eo, printExpr, " ");
 		case EBreak: "break";
 		case EContinue: "continue";
@@ -211,6 +212,16 @@ class Printer {
 		return el.map(printExpr).join(sep);
 	}
 	
+	function printExtension(tpl:Array<TypePath>, fields: Array<Field>) {
+		return '{\n$tabs>' + tpl.map(printTypePath).join(',\n$tabs>') + ","
+		    + (fields.length > 0 ? ('\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}") : ("\n}"));
+	}
+	
+	function printStructure(fields:Array<Field>) {
+		return fields.length == 0 ? "{ }" :
+			'{\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}";
+	}
+	
 	public function printTypeDefinition(t:TypeDefinition, printPackage = true):String {
 		var old = tabs;
 		tabs = tabString;
@@ -224,7 +235,7 @@ class Printer {
 						tabs + (field.doc != null && field.doc != "" ? "/**\n" + tabs + tabString + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + "\n" + tabs + "**/\n" + tabs : "")
 						+ (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "")
 						+ (switch(field.kind) {
-							case FVar(_, _): field.name;
+							case FVar(t, _): field.name + opt(t, printComplexType, ":");
 							case FProp(_, _, _, _): throw "FProp is invalid for TDEnum.";
 							case FFun(func): field.name + printFunction(func);
 						}) + ";"
@@ -252,12 +263,16 @@ class Printer {
 					+ "\n}";
 				case TDAlias(ct):
 					"typedef " + t.name + (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = "
-					+ printComplexType(ct)
+					+ (switch(ct) {
+						case TExtend(tpl, fields): printExtension(tpl, fields);
+						case TAnonymous(fields): printStructure(fields);
+						case _: printComplexType(ct);
+					})
 					+ ";";
 				case TDAbstract(tthis, from, to):
 					"abstract " + t.name
-					+ (tthis == null ? "" : "(" + printComplexType(tthis) + ")")
 					+ (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
+					+ (tthis == null ? "" : "(" + printComplexType(tthis) + ")")
 					+ (from == null ? "" : [for (f in from) " from " + printComplexType(f)].join(""))
 					+ (to == null ? "" : [for (t in to) " to " + printComplexType(t)].join(""))
 					+ " {\n"

+ 11 - 1
std/haxe/macro/Type.hx

@@ -40,7 +40,16 @@ enum Type {
 
 typedef AnonType = {
 	var fields : Array<ClassField>;
-	//var status : AnonStatus;
+	var status : AnonStatus;
+}
+
+enum AnonStatus {
+	AClosed;
+	AOpened;
+	AConst;
+	AClassStatics( t : Ref<ClassType> );
+	AEnumStatics( t : Ref<EnumType> );
+	AAbstractStatics( t : Ref<AbstractType> );
 }
 
 typedef TypeParameter = {
@@ -82,6 +91,7 @@ enum ClassKind {
 	KGenericInstance(cl:Ref<ClassType>, params:Array<Type>);
 	KMacroType;
 	KAbstractImpl(a:Ref<AbstractType>);
+	KGenericBuild;
 }
 
 typedef ClassType = {> BaseType,

+ 1 - 1
std/haxe/web/Dispatch.hx

@@ -309,7 +309,7 @@ class Dispatch {
 		case TAnonymous(a):
 			for( f in a.get().fields ) {
 				var r = getType(f.type, f.pos);
-				var opt = false;
+				var opt = f.meta.has(":optional");
 				switch( f.type ) {
 				case TType(t, _):
 					if( t.get().name == "Null" ) opt = true;

+ 20 - 8
std/java/_std/Array.hx

@@ -402,15 +402,9 @@ import java.NativeArray;
 		return ofNative(newarr);
 	}
 
-	public function iterator() : Iterator<T>
+	public inline function iterator() : Iterator<T>
 	{
-		var i = 0;
-		var len = length;
-		return
-		{
-			hasNext:function() return i < len,
-			next:function() return __a[i++]
-		};
+		return new ArrayIterator<T>(this);
 	}
 
 	public function map<S>( f : T -> S ) : Array<S> {
@@ -467,3 +461,21 @@ import java.NativeArray;
 		return __a[idx] = val;
 	}
 }
+
+@:final
+private class ArrayIterator<T>
+{
+	var arr:Array<T>;
+	var len:Int;
+	var i:Int;
+
+	public inline function new(a:Array<T>)
+	{
+		arr = a;
+		len = a.length;
+		i = 0;
+	}
+
+	public inline function hasNext():Bool return i < len;
+	public inline function next():T return arr[i++];
+}

+ 2 - 2
std/java/_std/Std.hx

@@ -240,8 +240,8 @@ import java.internal.Exceptions;
 		return 0.0;
 	}
 
-	public static function instance<T>( v : { }, c : Class<T> ) : T {
-		return Std.is(v, c) ? cast v : null;
+	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Std.is(value, c) ? cast value : null;
 	}
 
 	public static function random( x : Int ) : Int {

+ 5 - 0
std/java/internal/StringExt.hx

@@ -169,6 +169,11 @@ private typedef NativeString = String;
 		return null;
 	}
 
+	public static function toString(me:NativeString):NativeString
+	{
+		return me;
+	}
+
 	@:functionCode('
 			return me.toLowerCase();
 	')

+ 6 - 3
std/js/Boot.hx

@@ -68,7 +68,10 @@ class Boot {
 	}
 
 	static inline function getClass(o:Dynamic) : Dynamic {
-		return untyped __define_feature__("js.Boot.getClass", o.__class__);
+		if (Std.is(o, Array))
+			return Array;
+		else
+			return untyped __define_feature__("js.Boot.getClass", o.__class__);
 	}
 
 	@:ifFeature("has_enum")
@@ -171,6 +174,8 @@ class Boot {
 			return (untyped __js__("typeof"))(o) == "boolean";
 		case String:
 			return (untyped __js__("typeof"))(o) == "string";
+		case Array:
+			return (untyped __js__("(o instanceof Array)")) && o.__enum__ == null;
 		case Dynamic:
 			return true;
 		default:
@@ -178,8 +183,6 @@ class Boot {
 				// Check if o is an instance of a Haxe class
 				if( (untyped __js__("typeof"))(cl) == "function" ) {
 					if( untyped __js__("o instanceof cl") ) {
-						if( cl == Array )
-							return (o.__enum__ == null);
 						return true;
 					}
 					if( __interfLoop(getClass(o),cl) )

+ 9 - 0
std/js/Browser.hx

@@ -37,6 +37,15 @@ class Browser {
 	public static var navigator(get, never):js.html.Navigator;
 	inline static function get_navigator() return untyped __js__("window.navigator");
 	
+	/**
+	 * True if a window object exists, false otherwise.
+	 *
+	 * This can be used to check if the code is being executed in a non-browser
+	 * environment such as node.js.
+	 */
+	public static var supported(get, never):Bool;
+	public static function get_supported() return untyped __js__("typeof window != \"undefined\"");
+	
 	/**
 	 * Safely gets the browser's local storage, or returns null if localStorage is unsupported or
 	 * disabled.

+ 3 - 3
std/js/_std/Std.hx

@@ -28,8 +28,8 @@ import js.Boot;
 		return untyped js.Boot.__instanceof(v,t);
 	}
 	
-	public static inline function instance<T>( v : { }, c : Class<T> ) : T {
-		return untyped __instanceof__(v, c) ? cast v : null;
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return untyped __instanceof__(value, c) ? cast value : null;
 	}
 
 	public static function string( s : Dynamic ) : String {
@@ -61,7 +61,7 @@ import js.Boot;
 	static function __init__() : Void untyped {
 		__feature__("js.Boot.getClass",String.prototype.__class__ = __feature__("Type.resolveClass",$hxClasses["String"] = String,String));
 		__feature__("js.Boot.isClass",String.__name__ = __feature__("Type.getClassName",["String"],true));
-		__feature__("js.Boot.getClass",Array.prototype.__class__ = __feature__("Type.resolveClass",$hxClasses["Array"] = Array,Array));
+		__feature__("Type.resolveClass",$hxClasses["Array"] = Array);
 		__feature__("js.Boot.isClass",Array.__name__ = __feature__("Type.getClassName",["Array"],true));
 		__feature__("Date.*", {
 			__feature__("js.Boot.getClass",__js__('Date').prototype.__class__ = __feature__("Type.resolveClass",$hxClasses["Date"] = __js__('Date'),__js__('Date')));

+ 47 - 0
std/js/_std/haxe/Json.hx

@@ -0,0 +1,47 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe;
+
+@:coreApi
+#if (!haxeJSON && !old_browser)
+@:native("JSON") extern
+#end
+class Json {
+
+	#if haxeJSON inline #end
+	public static function parse( text : String ) : Dynamic {
+		return haxe.format.JsonParser.parse(text);
+	}
+
+	#if haxeJSON inline #end
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer);
+	}
+
+	#if (!haxeJSON && old_browser)
+	static function __init__():Void untyped {
+		if( __js__('typeof(JSON)') != 'undefined' )
+			Json = __js__('JSON');
+	}
+	#end
+
+}

+ 3 - 3
std/js/_std/haxe/ds/ObjectMap.hx

@@ -43,7 +43,7 @@ class ObjectMap<K:{ }, V> implements Map.IMap<K,V> {
 	}
 	
 	public function set(key:K, value:V):Void untyped {
-		var id = key.__id__ != null ? key.__id__ : assignId(key);
+		var id : Int = untyped key.__id__ || assignId(key);
 		h[id] = value;
 		h.__keys__[id] = key;
 	}
@@ -53,12 +53,12 @@ class ObjectMap<K:{ }, V> implements Map.IMap<K,V> {
 	}
 	
 	public inline function exists(key:K):Bool {
-		return untyped h.hasOwnProperty(getId(key));
+		return untyped h.__keys__[getId(key)] != null;
 	}
 	
 	public function remove( key : K ) : Bool {
 		var id = getId(key);
-		if ( untyped !h.hasOwnProperty(id) ) return false;
+		if ( untyped h.__keys__[id] == null ) return false;
 		untyped  __js__("delete")(h[id]);
 		untyped  __js__("delete")(h.__keys__[id]);
 		return true;

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません