Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
Index: haxe/std/js/Boot.hx
===================================================================
--- haxe/std/js/Boot.hx	(revision 3973)
+++ haxe/std/js/Boot.hx	(working copy)
@@ -254,6 +254,13 @@
 				}
 				return oldsub.apply(__this__,[pos,len]);
 			};
+			if( Function.prototype.bind == null )
+				Function.prototype.bind = function(object){ 
+					var fn = __this__; 
+					return function(){ 
+						return fn.apply(object, arguments); 
+					}
+				}
 			__js__("$closure = js.Boot.__closure");
 		}
 	}
Index: haxe/std/js/_std/Type.hx
===================================================================
--- haxe/std/js/_std/Type.hx	(revision 3973)
+++ haxe/std/js/_std/Type.hx	(working copy)
@@ -115,7 +115,8 @@
 	}
 
 	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {
-		return __new__(cl,__js__("$_"));
+		__js__("function empty() {}; empty.prototype = cl.prototype");
+		return __js__("new empty()");
 	}
 
 	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
Index: haxe/std/js/_std/Reflect.hx
===================================================================
--- haxe/std/js/_std/Reflect.hx	(revision 3973)
+++ haxe/std/js/_std/Reflect.hx	(working copy)
@@ -37,20 +37,32 @@
 	public inline static function field( o : Dynamic, field : String ) : Dynamic untyped {
 		var v = null;
 		try {
-			v = o[field];
+			var getter = hasGetter(o, field);
+			if (getter != null) v = getter.call(o);
+			else v = o[field];
 		} catch( e : Dynamic ) {
 		}
 		return v;
 	}
 
 	public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
-		o[field] = value;
+		var setter = hasSetter(o, field);
+		if (setter != null) setter.call(o, value);
+		else o[field] = value;
 	}
 
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 		return func.apply(o,args);
 	}
 
+	private inline static function hasGetter( o : Dynamic, field : String ) : Dynamic untyped {
+		if (o.__properties__) return o.__properties__["get_" + field]; else return null;
+	}
+
+	private inline static function hasSetter( o : Dynamic, field : String ) : Dynamic untyped {
+		if (o.__properties__) return o.__properties__["set_" + field]; else return null;
+	}
+
 	public static function fields( o : Dynamic ) : Array<String> untyped {
 		if( o == null ) return new Array();
 		var a = new Array();
Index: haxe/genjs.ml
===================================================================
--- haxe/genjs.ml	(revision 3973)
+++ haxe/genjs.ml	(working copy)
@@ -36,6 +36,7 @@
 	mutable curmethod : (string * bool);
 	mutable type_accessor : module_type -> string;
 	mutable separator : bool;
+	mutable m_props : string list;
 }
 
 let s_path ctx = function
@@ -71,6 +72,11 @@
 	| '}' | '{' | ':' when not ctx.separator -> print ctx "\n%s" ctx.tabs
 	| _ -> print ctx ";\n%s" ctx.tabs
 
+let newprop ctx =
+	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
+	| '{' -> print ctx "\n%s " ctx.tabs
+	| _ -> print ctx "\n%s," ctx.tabs
+
 let semicolon ctx =
 	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
 	| '}' when not ctx.separator -> ()
@@ -227,11 +233,16 @@
 		gen_value ctx x;
 		spr ctx (field s)
 	| TClosure (x,s) ->
-		spr ctx "$closure(";
-		gen_value ctx x;
-		spr ctx ",";
-		gen_constant ctx e.epos (TString s);
-		spr ctx ")";
+		(match x.eexpr with
+		| TConst _ | TLocal _ ->  
+			gen_value ctx x; 
+			print ctx ".%s.bind(" s; 
+			gen_value ctx x; 
+			print ctx ")"
+		| _ -> 
+			print ctx "($_=";
+			gen_value ctx x;
+			print ctx ",$_.%s.bind($_))" s);
 	| TTypeExpr t ->
 		spr ctx (ctx.type_accessor t)
 	| TParenthesis e ->
@@ -636,7 +647,7 @@
 			Hashtbl.add ctx.packages (p :: acc) ();
 			(match acc with
 			| [] ->
-				print ctx "if(typeof %s=='undefined') %s = {}" p p;
+				print ctx "if(typeof %s=='undefined') var %s = {}" p p;
 			| _ ->
 				let p = String.concat "." (List.rev acc) ^ (field p) in
 		        print ctx "if(!%s) %s = {}" p p);
@@ -671,41 +682,66 @@
 
 let gen_class_field ctx c f =
 	check_field_name c f;
-	print ctx "%s.prototype%s = " (s_path ctx c.cl_path) (field f.cf_name);
+	newprop ctx;
+	print ctx "%s: " f.cf_name;
 	match f.cf_expr with
 	| None ->
 		print ctx "null";
-		newline ctx
 	| Some e ->
 		ctx.curmethod <- (f.cf_name,false);
 		ctx.id_counter <- 0;
 		gen_value ctx e;
-		ctx.separator <- false;
-		newline ctx
+		ctx.separator <- false
 
+let add_getter_meta ctx prop c fn =
+	ctx.m_props <- 
+		(Printf.sprintf "get_%s: %s.prototype%s" prop (s_path ctx c.cl_path) (field fn))
+		:: ctx.m_props
+	
+let add_setter_meta ctx prop c fn =
+	ctx.m_props <- 
+		(Printf.sprintf "set_%s: %s.prototype%s" prop (s_path ctx c.cl_path) (field fn))
+		:: ctx.m_props
+
+let gen_class_prop_metas ctx c =
+	(match c.cl_super with
+ 	| None -> print ctx "%s.prototype.__properties__ = {" (s_path ctx c.cl_path);
+	| Some (csup,_) -> print ctx "%s.prototype.__properties__ = $extend(%s.prototype.__properties__, {" (s_path ctx c.cl_path) (s_path ctx csup.cl_path);
+	);
+	(match ctx.m_props with 
+	| [] -> print ctx "}" 
+	| _ -> 
+		let bend = open_block ctx in
+		List.iter ( fun c -> newprop ctx; print ctx "%s" c; ) ctx.m_props;
+		bend();
+		print ctx "\n%s}" ctx.tabs;
+	);
+	match c.cl_super with None -> () | Some (csup,_) -> print ctx ")"
+
 let gen_constructor ctx e =
 	match e.eexpr with
 	| TFunction f  ->
 		let args  = List.map arg_name f.tf_args in
-		let a, args = (match args with [] -> "p" , ["p"] | x :: _ -> x, args) in
 		print ctx "function(%s) {" (String.concat "," (List.map ident args));
 		let bend = open_block ctx in
-		if Codegen.constructor_side_effects f.tf_expr then begin
-			newline ctx;
-			print ctx "if( %s === $_ ) return" a;
-		end;
 		gen_block ctx (fun_block ctx f e.epos);
 		bend();
 		newline ctx;
 		print ctx "}";
 	| _ -> assert false
 
+let gen_class_decl_scope ctx (p,_) =
+	match p with
+	| [] -> print ctx "var ";
+	| _ -> ()
+
 let generate_class ctx c =
 	ctx.current <- c;
 	ctx.curmethod <- ("new",true);
 	ctx.id_counter <- 0;
 	let p = s_path ctx c.cl_path in
 	generate_package_create ctx c.cl_path;
+	gen_class_decl_scope ctx c.cl_path;
 	print ctx "%s = " p;
 	(match c.cl_constructor with
 	| Some { cf_expr = Some e } -> gen_constructor ctx e
@@ -713,28 +749,44 @@
 	newline ctx;
 	print ctx "%s.__name__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst c.cl_path @ [snd c.cl_path])));
 	newline ctx;
+	List.iter (gen_class_static_field ctx c) c.cl_ordered_statics;
+
 	(match c.cl_super with
-	| None -> ()
+	| None -> print ctx "%s.prototype = {" p;
 	| Some (csup,_) ->
 		let psup = s_path ctx csup.cl_path in
 		print ctx "%s.__super__ = %s" p psup;
 		newline ctx;
-		print ctx "for(var k in %s.prototype ) %s.prototype[k] = %s.prototype[k]" psup p psup;
-		newline ctx;
+		print ctx "%s.prototype = $extend(%s.prototype, {" p psup;
 	);
-	List.iter (gen_class_static_field ctx c) c.cl_ordered_statics;
-	List.iter (fun f -> match f.cf_kind with Var { v_read = AccResolve } -> () | _ -> gen_class_field ctx c f) c.cl_ordered_fields;
-	print ctx "%s.prototype.__class__ = %s" p p;
-	newline ctx;
-	match c.cl_implements with
+
+	let bend = open_block ctx in
+	(List.iter (fun f -> match f.cf_kind with Var { v_read = AccResolve } -> () | _ -> gen_class_field ctx c f) c.cl_ordered_fields;
+
+	newprop ctx;
+	print ctx "__class__: %s" p;
+	(match c.cl_implements with
 	| [] -> ()
 	| l ->
-		print ctx "%s.__interfaces__ = [%s]" p (String.concat "," (List.map (fun (i,_) -> s_path ctx i.cl_path) l));
-		newline ctx
+		newprop ctx;
+		print ctx "__interfaces__: [%s]" (String.concat "," (List.map (fun (i,_) -> s_path ctx i.cl_path) l));
+	);
+	);
+	bend();
+	print ctx "\n}";
+	(match c.cl_super with None -> () | _ -> print ctx ")";);
+	newline ctx;
 
+	ctx.m_props <- [];
+	List.iter (fun f -> match f.cf_kind with Var { v_read = AccCall fname } -> add_getter_meta ctx f.cf_name c fname | _ -> ()) c.cl_ordered_fields;
+	List.iter (fun f -> match f.cf_kind with Var { v_write = AccCall fname } -> add_setter_meta ctx f.cf_name c fname | _ -> ()) c.cl_ordered_fields;
+	gen_class_prop_metas ctx c; 
+	newline ctx
+
 let generate_enum ctx e =
 	let p = s_path ctx e.e_path in
 	generate_package_create ctx e.e_path;
+	gen_class_decl_scope ctx e.e_path;
 	let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path]) in
 	print ctx "%s = { __ename__ : [%s], __constructs__ : [%s] }" p (String.concat "," ename) (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names));
 	newline ctx;
@@ -795,6 +847,7 @@
 		curmethod = ("",false);
 		type_accessor = (fun _ -> assert false);
 		separator = false;
+		m_props = [];
 	} in
 	ctx.type_accessor <- (fun t -> s_path ctx (t_path t));
 	ctx
@@ -816,16 +869,20 @@
 	| Some g -> g()
 	| None ->
 	let ctx = alloc_ctx com in
-	print ctx "$estr = function() { return js.Boot.__string_rec(this,''); }";
+	print ctx 
+"var $_, $estr = function() { return js.Boot.__string_rec(this,''); }
+function $extend(from, fields) {
+	function inherit() {}; inherit.prototype = from; var proto = new inherit();
+	for (var name in fields) proto[name] = fields[name];
+	return proto;
+}";
 	newline ctx;
 	(match ctx.namespace with
 		| None -> ()
 		| Some ns ->
-			print ctx "if(typeof %s=='undefined') %s = {}" ns ns;
+			print ctx "if(typeof %s=='undefined') var %s = {}" ns ns;
 			newline ctx);
 	List.iter (generate_type ctx) com.types;
-	print ctx "$_ = {}";
-	newline ctx;
 	print ctx "js.Boot.__res = {}";
 	newline ctx;
 	(match ctx.namespace with