Skip to content

Commit

Permalink
Add @:shallowExpose meta.
Browse files Browse the repository at this point in the history
@:shallowExpose works very similarly to @:expose, but instead of
exposing on the window object (or export for nodejs), the class or
static field is instead exposed only to the surrounding scope of
the js_modern generated Haxe closure.

These are different things, when the Haxe generated code is used as
one part of a larger JS project with where in my particular use-case;
all JS code (including haxe generated code) is compiled into a single
optimised and minified JS file wrapped in a large closure, in this case
I do not wish the Haxe types to be exposed to window, but only to this
large closure containing the other JS code using the Haxe types,
the @:shallowExpose permits that.

Example:

@:shallowExpose class A {}
@:shallowExpose class B {}
@:shallowExpose("x.y.D") class D {}
@:shallowExpose("x.C") class C {}

class E {
        @:shallowExpose static function e() {}
}

Generates:

var $__hx_shallows = {E:{},x:{y:{}}};
(function () { "use strict";
var A = $__hx_shallows.A = function() { };
var B = $__hx_shallows.B = function() { };
var D = $__hx_shallows.x.y.D = function() { };
var C = $__hx_shallows.x.C = function() { };
var E = function() { };
E.e = $__hx_shallows.E.e = function() {
};
...
})();
var E = {};
var x = {y:{}};
var A = $__hx_shallows.A;
var B = $__hx_shallows.B;
x.y.D = $__hx_shallows.x.y.D;
x.C = $__hx_shallows.x.C;
E.e = $__hx_shallows.E.e;
  • Loading branch information
deltaluca committed Oct 10, 2013
1 parent b94ee60 commit 67a0921
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
3 changes: 2 additions & 1 deletion ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ module Meta = struct
| Runtime
| RuntimeValue
| Setter
| ShallowExpose
| SkipCtor
| SkipReflection
| Sound
Expand Down Expand Up @@ -692,4 +693,4 @@ let rec s_expr (e,_) =
| EArrayDecl el -> "[" ^ (String.concat "," (List.map s_expr el)) ^ "]"
| EObjectDecl fl -> "{" ^ (String.concat "," (List.map (fun (n,e) -> n ^ ":" ^ (s_expr e)) fl)) ^ "}"
| EBinop (op,e1,e2) -> s_expr e1 ^ s_binop op ^ s_expr e2
| _ -> "'???'"
| _ -> "'???'"
1 change: 1 addition & 0 deletions common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ module MetaInfo = struct
| Runtime -> ":runtime",("?",[])
| RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract])
| Setter -> ":setter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
| ShallowExpose -> ":shallowExpose",("Similar to @:expose meta, but exposed only to the surrounding scope of the Haxe generated closure, instead of to global scope",[HasParam "?Name=Class path";UsedOn TClass;Platform Js])
| SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; Internal])
| SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; Internal])
| Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash])
Expand Down
78 changes: 77 additions & 1 deletion genjs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ type ctx = {
mutable found_expose : bool;
}

type object_store = {
os_name : string;
mutable os_fields : object_store list;
}

let get_shallow ctx path meta =
if not ctx.js_modern then []
else try
let (_, args, pos) = Meta.get Meta.ShallowExpose meta in
(match args with
| [ EConst (String s), _ ] -> [s]
| [] -> [path]
| _ -> error "Invalid @:shallowExpose parameters" pos)
with Not_found -> []

let dot_path = Ast.s_type_path

let flat_path (p,s) =
Expand Down Expand Up @@ -892,6 +907,7 @@ let gen_class_static_field ctx c f =
print ctx "%s = " path;
gen_value ctx e;
ctx.separator <- false;
(match (get_shallow ctx path f.cf_meta) with [s] -> print ctx "$__hx_shallows.%s = " s | _ -> ());
newline ctx;
handle_expose ctx path f.cf_meta
| _ ->
Expand Down Expand Up @@ -933,6 +949,7 @@ let generate_class ctx c =
print ctx "%s = " p
else
print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path c.cl_path);
(match (get_shallow ctx p c.cl_meta) with [s] -> print ctx "$__hx_shallows.%s = " s | _ -> ());
(match c.cl_constructor with
| Some { cf_expr = Some e } -> gen_expr ctx e
| _ -> print ctx "function() { }");
Expand Down Expand Up @@ -1119,11 +1136,52 @@ let generate com =
if has_feature ctx "Class" || has_feature ctx "Type.getClassName" then add_feature ctx "js.Boot.isClass";
if has_feature ctx "Enum" || has_feature ctx "Type.getEnumName" then add_feature ctx "js.Boot.isEnum";

let shallows = List.concat (List.map (fun t ->
match t with
| TClassDecl c ->
let path = s_path ctx c.cl_path in
let class_shallows = get_shallow ctx path c.cl_meta in
let static_shallows = List.map (fun f ->
get_shallow ctx (path ^ static_field f.cf_name) f.cf_meta
) c.cl_ordered_statics in
List.concat (class_shallows :: static_shallows)
| _ -> []
) com.types) in
let anyShallowExposed = shallows <> [] in
let smap = ref (PMap.create String.compare) in
let shallowObject = { os_name = ""; os_fields = [] } in
List.iter (fun path -> (
let parts = ExtString.String.nsplit path "." in
let rec loop p pre = match p with
| f :: g :: ls ->
let path = match pre with "" -> f | pre -> (pre ^ "." ^ f) in
if not (PMap.exists path !smap) then (
let elts = { os_name = f; os_fields = [] } in
smap := PMap.add path elts !smap;
let cobject = match pre with "" -> shallowObject | pre -> PMap.find pre !smap in
cobject.os_fields <- elts :: cobject.os_fields
);
loop (g :: ls) path;
| _ -> ()
in loop parts "";
)) shallows;

if ctx.js_modern then begin
(* Additional ES5 strict mode keywords. *)
List.iter (fun s -> Hashtbl.replace kwds s ()) [ "arguments"; "eval" ];

(* Wrap output in a closure. *)
(* Wrap output in a closure. Exposing shallowExpose types to outside of closure *)
if anyShallowExposed then (
print ctx "var $__hx_shallows = ";
let rec print_obj { os_fields = fields } = (
print ctx "{";
concat ctx "," (fun ({ os_name = name } as f) -> print ctx "%s" (name ^ ":"); print_obj f) fields;
print ctx "}"
) in
print_obj shallowObject;
ctx.separator <- true;
newline ctx
);
print ctx "(function () { \"use strict\"";
newline ctx;
end;
Expand Down Expand Up @@ -1197,6 +1255,24 @@ let generate com =
if ctx.js_modern then begin
print ctx "})()";
newline ctx;
if anyShallowExposed then begin
let rec print_obj { os_fields = fields } = (
print ctx "{";
concat ctx "," (fun f-> print ctx "%s" (f.os_name ^ ":"); print_obj f) fields;
print ctx "}"
) in
List.iter (fun f ->
print ctx "var %s = " f.os_name;
print_obj f;
ctx.separator <- true;
newline ctx
) shallowObject.os_fields;
List.iter (fun path ->
if not (ExtString.String.contains path '.') then print ctx "var ";
print ctx "%s" (path ^ " = $__hx_shallows." ^ path);
newline ctx;
) shallows;
end
end;
if com.debug then write_mappings ctx else (try Sys.remove (com.file ^ ".map") with _ -> ());
let ch = open_out_bin com.file in
Expand Down

0 comments on commit 67a0921

Please sign in to comment.