[ 
https://issues.apache.org/jira/browse/THRIFT-3876?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16430462#comment-16430462
 ] 

ASF GitHub Bot commented on THRIFT-3876:
----------------------------------------

jeking3 closed pull request #1045: THRIFT-3876 haxe js/nodejs client
URL: https://github.com/apache/thrift/pull/1045
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/lib/haxe/README.md b/lib/haxe/README.md
index c5ad680024..4a84e23aae 100644
--- a/lib/haxe/README.md
+++ b/lib/haxe/README.md
@@ -36,6 +36,7 @@ enter the following commands after installing Haxe:
     haxelib install hxcpp
     haxelib install hxjava
     haxelib install hxcs
+    haxelib install hxnodejs
 
 For other targets, please consult the Haxe documentation whether or not any 
additional
 target libraries need to be installed and how to achieve this.
@@ -95,6 +96,7 @@ Current status
 ========================
 - tested with Haxe C++ target
 - tested with Haxe PHP target (console/web server, binary protocols)
+- tested with Haxe Javascript target (node/webjs, client only, json/binary 
over HTTP)
 - transports: Socket, HTTP (servers run inside PHP server/PHP target only), 
Stream
 - protocols: Binary, JSON, Multiplex, Compact
 - tutorial client and server available
@@ -114,9 +116,6 @@ Known restrictions
 Although designed with maximum portability in mind, for technical reasons some 
platforms
 may only support parts of the library, or not be compatible at all.
 
-Javascript:
-- tutorial fails to build because of unsupported Sys.args
-
 PHP HTTP Server notes
 ========================
 
@@ -162,3 +161,9 @@ var server = new TSimpleServer( processor, transport, 
transfactory, protfactory)
 server.runOnce = true;
 ```
 
+Javascript notes
+========================
+
+- non async HTTP requests are used (for Node.js every request is run in 
separate process and ~20x slower over javascript in browser)
+- tutorial for js uses PHP server. Please check details at 
[README](../../tutorial/haxe/README.md)
+
diff --git a/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx 
b/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx
index ee0aaa8e93..ad780f9e52 100644
--- a/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx
+++ b/lib/haxe/src/org/apache/thrift/helper/BitConverter.hx
@@ -136,15 +136,18 @@ class BitConverter {
         TestPair( 1.2345678901234569E+000,  
Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FC,Int)));
         TestPair( 1.2345678901234569E+150,  
Int64.make(cast(0x5F182344,Int),cast(0xCD3CDF9F,Int)));
         TestPair( 1.2345678901234569E+300,  
Int64.make(cast(0x7E3D7EE8,Int),cast(0xBCBBD352,Int)));
+        TestPair( 0.0000000000000000E+000,  
Int64.make(cast(0x00000000,Int),cast(0x00000000,Int)));
+        
+        #if !js //js doesn't support values over 2^52
         TestPair( -1.7976931348623157E+308, 
Int64.make(cast(0xFFEFFFFF,Int),cast(0xFFFFFFFF,Int)));
         TestPair( 1.7976931348623157E+308,  
Int64.make(cast(0x7FEFFFFF,Int),cast(0xFFFFFFFF,Int)));
         TestPair( 4.9406564584124654E-324,  
Int64.make(cast(0x00000000,Int),cast(0x00000001,Int)));
-        TestPair( 0.0000000000000000E+000,  
Int64.make(cast(0x00000000,Int),cast(0x00000000,Int)));
         TestPair( 4.94065645841247E-324,    
Int64.make(cast(0x00000000,Int),cast(0x00000001,Int)));
         TestPair( 3.2378592100206092E-319,  
Int64.make(cast(0x00000000,Int),cast(0x0000FFFF,Int)));
         TestPair( 1.3906711615669959E-309,  
Int64.make(cast(0x0000FFFF,Int),cast(0xFFFFFFFF,Int)));
         TestPair( Math.NEGATIVE_INFINITY,   
Int64.make(cast(0xFFF00000,Int),cast(0x00000000,Int)));
         TestPair( Math.POSITIVE_INFINITY,   
Int64.make(cast(0x7FF00000,Int),cast(0x00000000,Int)));
+        #end
 
         // NaN is special
         var i64nan = DoubleToInt64Bits( Math.NaN);
@@ -152,6 +155,7 @@ class BitConverter {
         if ( ! Math.isNaN( Int64BitsToDouble( i64cmp)))
             throw 'BitConverter NaN-Test #1: expected NaN';
 
+        #if !js //js doesn't support values over 2^52
         // For doubles, a quiet NaN is a bit pattern
         // between 7FF8000000000000 and 7FFFFFFFFFFFFFFF
         //      or FFF8000000000000 and FFFFFFFFFFFFFFFF
@@ -163,8 +167,9 @@ class BitConverter {
         var ok2 =  (Int64.compare( min2, i64nan) <= 0) && (Int64.compare( 
i64nan, max2) <= 0);
         if( ! (ok1 || ok2))
             throw 'BitConverter NaN-Test #2: failed';
+        #end
     }
     #end
 
 }
-    
\ No newline at end of file
+    
diff --git a/lib/haxe/src/org/apache/thrift/transport/TFileStream.hx 
b/lib/haxe/src/org/apache/thrift/transport/TFileStream.hx
index cd8ad17763..b26175f567 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TFileStream.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TFileStream.hx
@@ -24,6 +24,9 @@ import haxe.io.BytesBuffer;
 import haxe.io.Input;
 import haxe.io.Output;
 
+#if js
+import js.node.Fs;
+#end
 
 enum TFileMode {
     CreateNew;
@@ -36,8 +39,14 @@ class TFileStream implements TStream {
 
     public var FileName(default,null) : String;
 
+    #if !js
     private var Input  : sys.io.FileInput;
     private var Output : sys.io.FileOutput;
+    #else
+    private var Input  : Null<Int>;
+    private var Output  : Null<Int>;
+    private var lastInputOffset : Int = 0;
+    #end
 
 
     public function new( fname : String, mode : TFileMode) {
@@ -45,13 +54,25 @@ class TFileStream implements TStream {
         switch ( mode)
         {
             case TFileMode.CreateNew:
+                #if !js
                 Output = sys.io.File.write( fname, true);
+                #else
+                Output = Fs.openSync(fname, WriteCreate);
+                #end
 
             case TFileMode.Append:
+                #if !js
                 Output = sys.io.File.append( fname, true);
+                #else
+                Output = Fs.openSync(fname, AppendCreate);
+                #end
 
             case TFileMode.Read:
+                #if !js
                 Input = sys.io.File.read( fname, true);
+                #else
+                Input = Fs.openSync(fname, js.node.FsOpenFlag.Read);
+                #end
 
             default:
                 throw new TTransportException( TTransportException.UNKNOWN,
@@ -62,11 +83,19 @@ class TFileStream implements TStream {
 
     public function Close() : Void {
         if( Input != null) {
+            #if !js
             Input.close();
+            #else
+            Fs.closeSync(Input);
+            #end
             Input = null;
         }
         if( Output != null) {
+            #if !js
             Output.close();
+            #else
+            Fs.closeSync(Output);
+            #end
             Output = null;
         }
     }
@@ -75,27 +104,56 @@ class TFileStream implements TStream {
         if( Input == null)
             throw new TTransportException( TTransportException.NOT_OPEN, "File 
not open for input");
 
+        #if !js
         return (! Input.eof());
+        #else
+        var bytesRead = 0;
+        var copyBuf = new js.node.Buffer(1);
+        return ((bytesRead = Fs.readSync(Input, copyBuf, 0, 1, 
lastInputOffset)) > 0);
+        #end
+        
     }
 
     public function Read( buf : Bytes, offset : Int, count : Int) : Int {
         if( Input == null)
             throw new TTransportException( TTransportException.NOT_OPEN, "File 
not open for input");
 
+        #if !js
         return Input.readBytes( buf, offset, count);
+        #else
+        var bytesRead = 0;
+        var copyJsBuf = new js.node.Buffer(count);
+        bytesRead = Fs.readSync(Input, copyJsBuf, 0, count, lastInputOffset);
+        if(bytesRead > 0) {
+            lastInputOffset += bytesRead;
+            var readBuf = copyJsBuf.hxToBytes();
+            buf.blit(offset, readBuf, 0, bytesRead);
+        }
+        return bytesRead;
+        #end
     }
 
     public function Write( buf : Bytes, offset : Int, count : Int) : Void {
         if( Output == null)
             throw new TTransportException( TTransportException.NOT_OPEN, "File 
not open for output");
 
+        #if !js
         Output.writeBytes( buf, offset, count);
+        #else
+        var writeBuf = js.node.buffer.Buffer.hxFromBytes(buf);
+        Fs.writeSync(Output, writeBuf, offset, count);
+        #end
     }
 
     public function Flush() : Void {
-        if( Output != null)
+        if( Output != null) {
+            #if !js
             Output.flush();
+            #else
+            Fs.fsyncSync(Output);
+            #end
+        }
     }
 
 }
- 
\ No newline at end of file
+ 
diff --git a/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx 
b/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
index 79f86610d6..6ada5e8b45 100644
--- a/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
@@ -27,7 +27,14 @@ import haxe.io.BytesInput;
 
 import haxe.Http;
 
+#if nodejs
+import js.node.Fs;
+import js.Node;
+import js.node.ChildProcess;
+import js.Node.process;
+#end
 
+using StringTools;
 
 /**
 * HTTP implementation of the TTransport interface. Used for working with a
@@ -39,12 +46,25 @@ class THttpClient extends TTransport {
     private var requestBuffer_  : BytesOutput = new BytesOutput();
     private var responseBuffer_ : BytesInput = null;
 
+    #if !js
     private var request_        : Http = null;
+    #else
+    private var request_        : JsHttp = null;
+    #end
 
 
     public function new( requestUrl : String) : Void {
-          request_ = new Http(requestUrl);
-        request_.addHeader( "contentType", "application/x-thrift");
+        #if !js
+        request_ = new Http(requestUrl);
+        #else
+        request_ = new JsHttp(requestUrl);
+        request_.async = false;
+        #end
+        request_.addHeader("Content-Type", "application/x-thrift");
+        request_.addHeader("Accept", "application/x-thrift");
+        #if !(js && !nodejs)
+        request_.addHeader("User-Agent", "Haxe/THttpClient");
+        #end
     }
 
 
@@ -94,10 +114,245 @@ class THttpClient extends TTransport {
             }
         };
 
+        #if js
+        request_.onBinaryData = function(data : Bytes) {
+            responseBuffer_ = new BytesInput(data);
+            if( callback != null) {
+                callback(null);
+            }
+        };
+
+        request_.setBinaryPostData(buffer.getBytes());
+        #else
         request_.setPostData(buffer.getBytes().toString());
+        #end
         request_.request(true/*POST*/);
     }
-
 }
 
-    
\ No newline at end of file
+#if js
+/*supports sending/receiving binary/json data (browser, nodejs) 
+  implemented atop 
https://github.com/HaxeFoundation/haxe/blob/development/std/haxe/Http.hx
+  */
+class JsHttp extends Http {
+    var binaryPostData : Bytes;
+
+    public function setBinaryPostData( data : Bytes ):Http {
+        binaryPostData = data;
+        return this;
+    }
+
+    public dynamic function onBinaryData( data : Bytes ) {
+    }
+
+    #if !nodejs
+    public override function request( ?post : Bool ) : Void {
+        var me = this;
+        me.responseData = null;
+        var r = req = js.Browser.createXMLHttpRequest();
+        var onreadystatechange = function(_) {
+            if( r.readyState != 4 )
+                return;
+            var s = try r.status catch( e : Dynamic ) null;
+            if ( s != null && untyped __js__('"undefined" !== typeof window') 
) {
+                // If the request is local and we have data: assume a success 
(jQuery approach):
+                var protocol = js.Browser.location.protocol.toLowerCase();
+                var rlocalProtocol = 
~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/;
+                var isLocal = rlocalProtocol.match( protocol );
+                if ( isLocal ) {
+                    s = r.responseText != null ? 200 : 404;
+                }
+            }
+            if( s == untyped __js__("undefined") )
+                s = null;
+            if( s != null )
+                me.onStatus(s);
+            if( s != null && s >= 200 && s < 400 ) {
+                me.req = null;
+                var len = r.responseText.length;
+                var bytes = new BytesOutput();
+                bytes.prepare(len);
+                for(i in 0 ... len) {
+                    var byte = (r.responseText.charCodeAt(i) & 255);
+                    if(byte >= 128) {
+                        byte -= 256;
+                    }
+                    bytes.writeInt8(byte);
+                }
+                var resBytes = bytes.getBytes();
+                me.onBinaryData(resBytes);
+            }
+            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);
+            }
+        };
+        if( async )
+            r.onreadystatechange = onreadystatechange;
+        var uri = postData;
+        var jsData = binaryPostData;
+        if( jsData != null )
+            post = true;
+        else for( p in params ) {
+            if( uri == null )
+                uri = "";
+            else
+                uri += "&";
+            uri += 
StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value);
+        }
+        try {
+            if( post )
+                r.open("POST",url,async);
+            else if( uri != null ) {
+                var question = url.split("?").length <= 1;
+                r.open("GET",url+(if( question ) "?" else "&")+uri,async);
+                uri = null;
+            } else
+                r.open("GET",url,async);
+        } catch( e : Dynamic ) {
+            me.req = null;
+            onError(e.toString());
+            return;
+        }
+
+        //XHR binary charset opt by Marcus Granado 2006 
[http://mgran.blogspot.com]
+        req.overrideMimeType("text\\/plain; charset=x-user-defined");
+
+        #if (haxe_ver >= 3.3)
+        r.withCredentials = me.withCredentials;
+        #end
+        if( !Lambda.exists(headers, function(h) return h.header == 
"Content-Type") && post && postData == null )
+            
r.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
+
+        for( h in headers )
+            r.setRequestHeader(h.header,h.value);
+
+        if( jsData != null ) {
+            r.send(new js.html.Uint8Array(jsData.getData()));
+        } else {
+            r.send(uri);
+        }
+
+        if( !async )
+            onreadystatechange(null);
+    }
+    #elseif nodejs
+    public override function request( ?post : Bool ) : Void {
+
+        var url_regexp = ~/^(https?:\/\/)?([a-zA-Z\.0-9_-]+)(:[0-9]+)?(.*)$/;
+        if( !url_regexp.match(url) ) {
+            onError("Invalid URL");
+            return;
+        }
+        var ssl = (url_regexp.matched(1) == "https://";);
+        var host = url_regexp.matched(2);
+        var portString = url_regexp.matched(3);
+        var request = url_regexp.matched(4);
+        if( request == "" )
+            request = "/";
+        var port = if ( portString == null || portString == "" ) ssl ? 443 : 
80 else Std.parseInt(portString.substr(1, portString.length - 1));
+
+        var options = {
+            "hostname":host,
+            "port":port,
+            "path":request,
+            "method":post ? "POST" : "GET",
+            "agent":false,
+            "withCredentials":#if (haxe_ver >= 3.3) me.withCredentials #else 
false #end
+        };
+
+        var headersArray = [];
+        for( h in headers ) {
+            headersArray.push({header : h.header, value : h.value});
+        }
+
+        // stringify data
+        var sendCode = "";
+        var data = binaryPostData;
+
+        if(data != null) {
+            var bufStr = 
haxe.Json.stringify(js.node.buffer.Buffer.hxFromBytes(data)).replace("'", 
"\\'");
+            sendCode = "var dataObj = JSON.parse('" + bufStr + "', "
+            + " function(key, value) {"
+                + "return value && value.type === 'Buffer'"
+                + "? new Buffer(value.data)"
+                + ": value;"
+            + "});";
+            sendCode += "req.write(dataObj);";
+            headersArray.push({header : "Content-Length", value : 
Std.string(data.length)});
+        } else {
+            headersArray.push({header : "Content-Length", value : '0'});
+        }
+
+        var responseEncoding = 'binary';
+ 
+        // The async request the other Node process executes
+        var execString = "var http = require('http'), https = 
require('https'), fs = require('fs');"
+          + "var doRequest = http" + (ssl ? "s" : "") + ".request;"
+          + "var options = " + haxe.Json.stringify(options) + ";"
+          + "var responseText = '';"
+          + "var req = doRequest(options, function(response) {"
+          + "response.setEncoding(" + (responseEncoding != null ? "'" + 
responseEncoding + "'" : responseEncoding) + ");"
+          + "response.on('data', function(chunk) {"
+          + "  responseText += chunk;"
+          + "});"
+          + "response.on('end', function() {"
+          + "if(responseText.length) {"
+          + "  responseText = JSON.stringify(new Buffer(responseText, " + 
(responseEncoding != null ? "'" + responseEncoding + "'" : responseEncoding) + 
"));"
+          + "}"
+          + "process.stdout.write(JSON.stringify({err: null, data: 
{statusCode: response.statusCode, headers: response.headers, text: 
responseText}}));"
+          + "});"
+          + "response.on('error', function(error) {"
+          + "process.stdout.write(JSON.stringify({err: error, errorMessage : 
error.message}));"
+          + "});"
+          + "}).on('error', function(error) {"
+          + "process.stdout.write(JSON.stringify({err: error, errorMessage : 
error.message}));"
+          + "});"
+          + "var headersArr = JSON.parse('" + 
haxe.Json.stringify(headersArray) + "');"
+          + "for(i = 0; i > headersArr.length; i++) {"
+          + "req.setHeader(headersArr[i].header, headersArr[i].value);"
+          + "}"
+          + sendCode 
+          + "req.end();";
+
+        //Fs.writeFileSync("codetorun.js", execString, "binary");
+
+        // Start the other Node Process, executing this string
+        var subProcess = ChildProcess.spawnSync(Node.process.argv[0], ["-e", 
execString], {stdio: "pipe"});
+
+        if(subProcess.status != 0 || subProcess.stderr != '') {
+            this.onError('Execution of js is failed : ${execString}\n error : 
${subProcess.stderr}');
+        }
+
+        var responseBody = subProcess.stdout; 
+        var resp = haxe.Json.parse(responseBody);
+  
+        if (resp.err != null) {
+            this.onError(resp.errorMessage);
+        } else {
+            if(resp.data.text != '') {
+                var responseBuffer = haxe.Json.parse(resp.data.text);
+                var buffer = new js.node.buffer.Buffer(responseBuffer.data);
+                this.onBinaryData(buffer.hxToBytes());
+            } else {
+                this.onBinaryData(Bytes.alloc(0));
+            }
+        }
+    }
+    #end
+
+}
+#end
+    
diff --git a/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx 
b/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
index 4badb2a1f1..b02a4ccd22 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
@@ -29,7 +29,7 @@ import haxe.io.Output;
 import haxe.io.Eof;
 
 //import flash.net.ServerSocket; - not yet available on Haxe 3.1.3
-#if ! (flash || html5)
+#if ! (flash || html5 || js)
 
 import sys.net.Host;
 
diff --git a/lib/haxe/src/org/apache/thrift/transport/TSocket.hx 
b/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
index 7941ab9fe5..5666149747 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
@@ -262,7 +262,7 @@ class TSocket extends TTransport  {
     public override function open()  :  Void
     {
         #if js
-        var socket = new WebSocket();
+        var socket = new WebSocket(host);
         socket.onmessage = function( event : js.html.MessageEvent) {
             this.input = event.data;
         }
@@ -308,10 +308,13 @@ class TSocket extends TTransport  {
         #end
     }
 
-    public function setTimeout( timeout : Float ) : Void {
+    public function setTimeout( timeout : Float ) : Void 
+    {
+        #if !js
         if(isOpen()) {
             socket.setTimeout(timeout);
         }
+        #end
         this.timeout = timeout;
     }
 
diff --git a/lib/haxe/test/Makefile.am b/lib/haxe/test/Makefile.am
index 5c638d4aa3..3473ce586e 100644
--- a/lib/haxe/test/Makefile.am
+++ b/lib/haxe/test/Makefile.am
@@ -25,6 +25,7 @@ BENCHMARK = $(top_srcdir)/lib/rb/benchmark/Benchmark.thrift
 
 BIN_CPP = bin/Main-debug
 BIN_PHP = bin/php/Main-debug.php
+BIN_JS = bin/Main.js
 
 gen-haxe/thrift/test/ThriftTest.hx: $(THRIFTTEST)
        $(THRIFTCMD) $(THRIFTTEST)
@@ -35,30 +36,33 @@ gen-haxe/thrift/test/Aggr.hx: $(AGGR)
 gen-haxe/thrift/test/BenchmarkService.hx: $(BENCHMARK)
        $(THRIFTCMD) $(BENCHMARK)
 
-all-local: $(BIN_CPP) $(BIN_PHP)
+all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_JS)
 
-$(BIN_CPP): \
-               src/*.hx \
+HX_SRC = src/*.hx \
                ../src/org/apache/thrift/**/*.hx \
                gen-haxe/thrift/test/ThriftTest.hx \
                gen-haxe/thrift/test/Aggr.hx \
                gen-haxe/thrift/test/BenchmarkService.hx
+
+$(BIN_CPP): $(HX_SRC) \
+               cpp.hxml
        $(HAXE) --cwd .  cpp.hxml
 
-$(BIN_PHP): \
-               src/*.hx \
-               ../src/org/apache/thrift/**/*.hx \
-               gen-haxe/thrift/test/ThriftTest.hx \
-               gen-haxe/thrift/test/Aggr.hx \
-               gen-haxe/thrift/test/BenchmarkService.hx
+$(BIN_PHP): $(HX_SRC) \
+               php.hxml
        $(HAXE) --cwd .  php.hxml
 
+$(BIN_JS): $(HX_SRC) \
+               javascript.hxml
+       haxelib list | grep hxnodejs > /dev/null || haxelib install hxnodejs
+       $(HAXE) --cwd .  javascript.hxml
+       
+
 
 #TODO: other haxe targets
 #    $(HAXE)  --cwd .  csharp
 #    $(HAXE)  --cwd .  flash
 #    $(HAXE)  --cwd .  java
-#    $(HAXE)  --cwd .  javascript
 #    $(HAXE)  --cwd .  neko
 #    $(HAXE)  --cwd .  python  # needs Haxe 3.2.0
 
@@ -66,9 +70,10 @@ $(BIN_PHP): \
 clean-local:
        $(RM) -r gen-haxe bin
 
-check: $(BIN_CPP) $(BIN_PHP)
+check: $(BIN_CPP) $(BIN_PHP) $(BIN_JS)
        $(BIN_CPP)
        php -f $(BIN_PHP)
+       node $(BIN_JS) 
 
 EXTRA_DIST = \
              src \
diff --git a/lib/haxe/test/javascript.hxml b/lib/haxe/test/javascript.hxml
index 18d9964c2d..253a629c87 100644
--- a/lib/haxe/test/javascript.hxml
+++ b/lib/haxe/test/javascript.hxml
@@ -22,11 +22,14 @@
 -cp ../src
 -cp gen-haxe
 
+#libs
+-lib hxnodejs
+
 #this class wil be used as entry point for your app.
 -main Main
 
 #JavaScript target
--js bin/Test.js
+-js bin/Main.js
 
 #You can use -D source-map-content (requires Haxe 3.1+) to have the .hx 
 #files directly embedded into the map file, this way you only have to 
@@ -41,4 +44,4 @@
 #"-dce no" : do not remove unused code
 #"-dce std" : remove unused code in the std lib (default)
 #"-dce full" : remove all unused code
--dce full
\ No newline at end of file
+-dce full
diff --git a/lib/haxe/test/src/Main.hx b/lib/haxe/test/src/Main.hx
index 6c262d78f5..eb8049ce06 100644
--- a/lib/haxe/test/src/Main.hx
+++ b/lib/haxe/test/src/Main.hx
@@ -74,8 +74,10 @@ class Main
             switch( tests) {
                 case Normal:
                     StreamTest.Run(server);
+                #if !js
                 case Multiplex:
                     MultiplexTest.Run(server);
+                #end
                 default:
                     throw "Unhandled test mode $tests";
             }
@@ -85,9 +87,10 @@ class Main
         catch( e: Dynamic)
         {
             trace('$e');
+            trace(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
             #if sys
             Sys.exit(1);  // indicate error
             #end
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/haxe/Makefile.am b/test/haxe/Makefile.am
index 1a32185ecd..60a863c82f 100644
--- a/test/haxe/Makefile.am
+++ b/test/haxe/Makefile.am
@@ -24,31 +24,45 @@ THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift
 BIN_CPP = bin/Main-debug
 BIN_PHP = bin/php/Main-debug.php
 BIN_PHP_WEB = bin/php-web-server/Main-debug.php
+BIN_NODE_JS = bin/nodejs/Main.js
+BIN_JS = bin/js/Main.js
 
 gen-haxe/thrift/test/ThriftTest.hx: $(THRIFTTEST)
        $(THRIFTCMD) $(THRIFTTEST)
 
 all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB)
 
-$(BIN_CPP): \
+HX_SRC = \
                src/*.hx \
                ../../lib/haxe/src/org/apache/thrift/**/*.hx \
                gen-haxe/thrift/test/ThriftTest.hx
+
+$(BIN_CPP): $(HX_SRC) \
+               cpp.hxml
        $(HAXE) --cwd .  cpp.hxml
 
-$(BIN_PHP): \
-               src/*.hx \
-               ../../lib/haxe/src/org/apache/thrift/**/*.hx \
-               gen-haxe/thrift/test/ThriftTest.hx
+$(BIN_PHP): $(HX_SRC) \
+               php.hxml
        $(HAXE) --cwd .  php.hxml
 
-$(BIN_PHP_WEB): \
-               src/*.hx \
-               ../../lib/haxe/src/org/apache/thrift/**/*.hx \
-               gen-haxe/thrift/test/ThriftTest.hx
+$(BIN_PHP_WEB): $(HX_SRC) \
+               php-web-server.hxml
        $(HAXE) --cwd .  php-web-server.hxml
 
+$(BIN_NODE_JS): $(HX_SRC) \
+               nodejs.hxml
+       haxelib list | grep hxnodejs > /dev/null || haxelib install hxnodejs
+       $(HAXE) --cwd .  nodejs.hxml
+
+$(BIN_JS): $(HX_SRC) \
+               javascript.hxml
+       $(HAXE) --cwd .  javascript.hxml
 
+PHANTOMJS_BIN = node_modules/.bin/phantomjs
+
+$(PHANTOMJS_BIN):
+       npm install 
+       
 
 #TODO: other haxe targets
 #    $(HAXE)  --cwd .  csharp
@@ -60,31 +74,60 @@ $(BIN_PHP_WEB): \
 
 
 clean-local:
-       $(RM) -r gen-haxe bin
+       $(RM) -r gen-haxe bin node_modules
 
 .NOTPARALLEL:
 
 check: check_cpp \
        check_php \
-       check_php_web 
+       check_php_web \
+       check_node_web \
+       check_js_web
 
 check_cpp: $(BIN_CPP) 
-       timeout 20 $(BIN_CPP) server &
+       timeout 20 $(BIN_CPP) server & echo $$! > server.PID
        sleep 1
        $(BIN_CPP) client
-       sleep 10
+       kill `cat server.PID` && rm server.PID
 
 check_php: $(BIN_PHP) 
-       timeout 20 php -f $(BIN_PHP) server &
+       timeout 20 php -f $(BIN_PHP) server & echo $$! > server.PID
        sleep 1
        php -f $(BIN_PHP) client
-       sleep 10
+       kill `cat server.PID` && rm server.PID
 
 check_php_web: $(BIN_PHP_WEB) $(BIN_CPP)
-       timeout 20 php -S 127.0.0.1:9090 router.php &
+       timeout 20 php -S 127.0.0.1:9090 router.php & echo $$! > server.PID
        sleep 1
        $(BIN_CPP) client --transport http
-       sleep 10
+       kill `cat server.PID` && rm server.PID
+
+check_node_web: $(BIN_NODE_JS)
+       timeout 20 php -S 127.0.0.1:9090 router.php & echo $$! > server.PID
+       sleep 1
+       node $(BIN_NODE_JS) client --transport http --skip-speed-test
+       kill `cat server.PID` && rm server.PID
+
+check_js_web: $(BIN_JS) $(PHANTOMJS_BIN)
+       timeout 20 php -S 127.0.0.1:9090 router.php & echo $$! > server.PID
+       sleep 1
+       $(PHANTOMJS_BIN) phantom-js-client-test.js
+       kill `cat server.PID` && rm server.PID
+
+nodejs_client_http: $(BIN_NODE_JS)
+       node $(BIN_NODE_JS) client --transport http --skip-speed-test
+
+js_client_http: $(BIN_JS) $(PHANTOMJS_BIN)
+       $(PHANTOMJS_BIN) phantom-js-client-test.js
+
+php_client_http: $(BIN_PHP)
+       php -f $(BIN_PHP) client --transport http
+
+cpp_client_http: $(BIN_CPP)
+       $(BIN_CPP) client --transport http
+
+php_web_server: $(BIN_PHP_WEB) 
+       php -S 127.0.0.1:9090 router.php 
 
 
 EXTRA_DIST = \
@@ -94,6 +137,7 @@ EXTRA_DIST = \
              flash.hxml \
              java.hxml \
              javascript.hxml \
+             nodejs.hxml \
              neko.hxml \
              php.hxml \
              python.hxml \
diff --git a/test/haxe/javascript.hxml b/test/haxe/javascript.hxml
index b2b3876cf1..d109d73352 100644
--- a/test/haxe/javascript.hxml
+++ b/test/haxe/javascript.hxml
@@ -26,7 +26,7 @@
 -main Main
 
 #JavaScript target
--js bin/Tutorial.js
+-js bin/js/Main.js
 
 #You can use -D source-map-content (requires Haxe 3.1+) to have the .hx 
 #files directly embedded into the map file, this way you only have to 
@@ -41,4 +41,4 @@
 #"-dce no" : do not remove unused code
 #"-dce std" : remove unused code in the std lib (default)
 #"-dce full" : remove all unused code
--dce full
\ No newline at end of file
+-dce full
diff --git a/test/haxe/nodejs.hxml b/test/haxe/nodejs.hxml
new file mode 100644
index 0000000000..83a7b9523d
--- /dev/null
+++ b/test/haxe/nodejs.hxml
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+ 
+#integrate files to classpath
+-cp src
+-cp gen-haxe
+-cp ../../lib/haxe/src
+
+#libs
+-lib hxnodejs
+
+#this class wil be used as entry point for your app.
+-main Main
+
+#JavaScript target
+-js bin/nodejs/Main.js
+
+#You can use -D source-map-content (requires Haxe 3.1+) to have the .hx 
+#files directly embedded into the map file, this way you only have to 
+#upload it, and it will be always in sync with the compiled .js even if 
+#you modify your .hx files.
+-D source-map-content
+
+#Generate source map and add debug information
+-debug
+
+#dead code elimination : remove unused code
+#"-dce no" : do not remove unused code
+#"-dce std" : remove unused code in the std lib (default)
+#"-dce full" : remove all unused code
+-dce full
diff --git a/test/haxe/package.json b/test/haxe/package.json
new file mode 100644
index 0000000000..d7eb7a20e3
--- /dev/null
+++ b/test/haxe/package.json
@@ -0,0 +1,13 @@
+{
+  "name": "haxe-js-client-test",
+  "version": "1.0.0",
+  "description": "",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "Apache-2.0",
+  "dependencies" : {
+         "phantomjs-prebuilt" : "*"
+  }
+}
diff --git a/test/haxe/phantom-js-client-test.js 
b/test/haxe/phantom-js-client-test.js
new file mode 100644
index 0000000000..1d2e196218
--- /dev/null
+++ b/test/haxe/phantom-js-client-test.js
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+var url = 'http://localhost:9090/';
+console.log("Trying to connect to : " + url);
+
+var page = require('webpage').create();
+
+var successRun = false;
+page.onConsoleMessage = function(msg) {
+    if(msg.indexOf("Tests failed      0") !== -1) {
+        successRun = true;
+    }
+    console.log('page : ' + msg);
+};
+
+page.open(url, function(status) {
+    if(status === "success") {
+        console.log("connected. page text : " + page.plainText);
+        var jsToInject = 'bin/js/Main.js';
+        if (page.injectJs(jsToInject)) {
+            if(successRun) {
+                phantom.exit(0);
+            } else {
+                console.log("error on running tests");
+                phantom.exit(1);
+            }
+        } else {
+            console.log("error in injecting " + jsToInject);
+            phantom.exit(1);
+        }
+    } else {
+        console.log("Status: " + status);
+        console.log("Please run test web server : make php_web_server");
+        phantom.exit(1);
+    }
+});
+
+
diff --git a/test/haxe/src/Arguments.hx b/test/haxe/src/Arguments.hx
index cc10749873..190a6f076d 100644
--- a/test/haxe/src/Arguments.hx
+++ b/test/haxe/src/Arguments.hx
@@ -71,7 +71,7 @@ class Arguments
 
 
     public function new() {
-        #if sys
+        #if (sys || nodejs)
           #if !phpwebserver
           try {
               ParseArgs();
@@ -84,12 +84,14 @@ class Arguments
             server = true;
             transport = http;
           #end
+        #elseif js
+            transport = http;
         #else
         trace("WN: Platform does not support program arguments, using 
defaults.");
         #end
     }
 
-    #if sys
+    #if (sys || nodejs)
 
     private static function GetHelp() : String {
         var sProg = Path.withoutDirectory( Sys.executablePath());
diff --git a/test/haxe/src/Main.hx b/test/haxe/src/Main.hx
index 9eb828f1f7..da6981ea29 100644
--- a/test/haxe/src/Main.hx
+++ b/test/haxe/src/Main.hx
@@ -50,7 +50,6 @@ class Main
                 TestServer.Execute(args);
             else
                 TestClient.Execute(args);
-
             trace("Completed.");
         } catch (e : String) {
             trace(e);
diff --git a/test/haxe/src/TestClient.hx b/test/haxe/src/TestClient.hx
index aa496dc8d3..5cb25574ad 100644
--- a/test/haxe/src/TestClient.hx
+++ b/test/haxe/src/TestClient.hx
@@ -137,11 +137,13 @@ class TestClient {
         catch (e : TException)
         {
             trace('TException: $e');
+            trace(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
             exitCode = 0xFF;
         }
         catch (e : Dynamic)
         {
             trace('Exception: $e');
+            trace(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
             exitCode = 0xFF;
         }
 
diff --git a/test/haxe/src/TestServer.hx b/test/haxe/src/TestServer.hx
index 450c8f28c2..fb53f27bbc 100644
--- a/test/haxe/src/TestServer.hx
+++ b/test/haxe/src/TestServer.hx
@@ -39,14 +39,18 @@ class TestServer
             switch( args.transport) {
             case socket:
                 trace("- socket port "+args.port);
-                transport = new TServerSocket( args.port);
+                #if !js
+                    transport = new TServerSocket( args.port);
+                #else
+                    throw "Server Socket not implemented yet";
+                #end
             case http:
                 trace("- http");
                 #if !phpwebserver
-                  throw "HTTP server not implemented yet";
-                 //transport = new THttpServer( targetHost);
+                    throw "HTTP server not implemented yet";
+                    //transport = new THttpServer( targetHost);
                 #else
-                transport =    new TWrappingServerTransport(
+                    transport =    new TWrappingServerTransport(
                         new TStreamTransport(
                           new TFileStream("php://input", Read),
                           new TFileStream("php://output", Append)
@@ -86,6 +90,9 @@ class TestServer
 
 
             // Processor
+            #if js
+                throw "Server Handler not implemented yet";
+            #else
             var handler = new TestServerHandler();
             var processor = new ThriftTestProcessor(handler);
 
@@ -117,6 +124,7 @@ class TestServer
             // Run it
             server.Serve();
             trace("done.");
+            #end //!js
 
         }
         catch (x : TException)
diff --git a/tutorial/haxe/Makefile.am b/tutorial/haxe/Makefile.am
index e9c88204c9..f05e9473a7 100644
--- a/tutorial/haxe/Makefile.am
+++ b/tutorial/haxe/Makefile.am
@@ -22,33 +22,43 @@ THRIFT = $(top_builddir)/compiler/cpp/thrift
 BIN_CPP = bin/Main-debug
 BIN_PHP = bin/php/Main-debug.php
 BIN_PHP_WEB = bin/php-web-server/Main-debug.php
+BIN_JS = bin/js/Main.js
+BIN_NODE_JS = bin/nodejs/Main.js
 
 
 gen-haxe/tutorial/calculator.hx gen-haxe/shared/shared_service.hx: 
$(top_srcdir)/tutorial/tutorial.thrift
        $(THRIFT) --gen haxe -r $<
 
-all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB)
+all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB) $(BIN_NODE_JS) $(BIN_JS)
 
 check: gen-haxe/tutorial/calculator.hx
 
-$(BIN_CPP): \
+HX_SRC = \
                src/*.hx \
                ../../lib/haxe/src/org/apache/thrift/**/*.hx \
                gen-haxe/tutorial/calculator.hx
+
+$(BIN_CPP): $(HX_SRC) \
+               cpp.hxml
        $(HAXE) --cwd .  cpp.hxml
 
-$(BIN_PHP): \
-               src/*.hx \
-               ../../lib/haxe/src/org/apache/thrift/**/*.hx \
-               gen-haxe/tutorial/calculator.hx
+$(BIN_PHP): $(HX_SRC) \
+               php.hxml
        $(HAXE) --cwd .  php.hxml
 
-$(BIN_PHP_WEB): \
-               src/*.hx \
-               ../../lib/haxe/src/org/apache/thrift/**/*.hx \
-               gen-haxe/tutorial/calculator.hx
+$(BIN_PHP_WEB): $(HX_SRC) \
+               php-web-server.hxml
        $(HAXE) --cwd .  php-web-server.hxml
 
+$(BIN_NODE_JS): $(HX_SRC) \
+               nodejs.hxml
+       haxelib list | grep hxnodejs > /dev/null || haxelib install hxnodejs
+       $(HAXE) --cwd .  nodejs.hxml
+
+$(BIN_JS): $(HX_SRC) \
+               javascript.hxml
+       $(HAXE) --cwd .  javascript.hxml
+
 tutorialserver: all
        $(BIN_CPP) server
 
@@ -79,8 +89,17 @@ tutorialserver_php_http: all
 tutorialclient_http: all
        $(BIN_CPP) client http
 
+tutorialclient_php_http: all
+       php -f $(BIN_PHP) client http
+
+tutorialclient_nodejs_http_json: all
+       node $(BIN_NODE_JS) client http json
+
+tutorialclient_nodejs_http: all
+       node $(BIN_NODE_JS) client http
+
 clean-local:
-       $(RM) -r gen-haxe bin
+       $(RM) -r gen-haxe bin node_modules
 
 EXTRA_DIST = \
              src \
@@ -89,10 +108,12 @@ EXTRA_DIST = \
              flash.hxml \
              java.hxml \
              javascript.hxml \
+             nodejs.hxml \
              neko.hxml \
              php.hxml \
              python.hxml \
              project.hide \
              Tutorial.hxproj \
              make_all.bat \
-             make_all.sh
+             make_all.sh \
+                        router.php
diff --git a/tutorial/haxe/README.md b/tutorial/haxe/README.md
new file mode 100644
index 0000000000..b678549ca4
--- /dev/null
+++ b/tutorial/haxe/README.md
@@ -0,0 +1,42 @@
+Thrift Haxe Tutorial
+==================================================
+1) Compile the library
+
+    make
+
+2) TCP/Socket transport:
+
+server:
+
+    make tutorialserver 
+
+or
+    
+    make tutorialserver_php  
+
+
+client: 
+    
+    ```
+    make tutorialclient
+    make tutorialclient_php
+    ```
+
+3) http transport 
+
+server:
+
+    make tutorialserver_php_http
+
+client:
+
+    ```
+    make tutorialclient_http
+    make tutorialclient_nodejs_http_json
+    make tutorialclient_nodejs_http
+    make tutorialclient_php_http
+    ```
+
+for browser side javascript open http://localhost:9090/javascript.html
+
+
diff --git a/tutorial/haxe/javascript.html b/tutorial/haxe/javascript.html
new file mode 100644
index 0000000000..1353fb757a
--- /dev/null
+++ b/tutorial/haxe/javascript.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Thrift Haxe-Javascript Bindings - Tutorial Example</title>
+
+
+  <script type="text/javascript" 
src="https://code.jquery.com/jquery-3.0.0.min.js";></script>
+
+
+  <script type="text/javascript" charset="utf-8">
+  //<![CDATA[
+  $(document).ready(function(){
+      $('#repeat').click(function() {
+          $('#trace').html('');
+          var protocol = $('input[name=prot]:checked').val();
+          if(protocol == "binary") {
+              Main.setProtBinary();
+          } else {
+              Main.setProtJson();
+          }
+
+          Main.RunClient();
+      });
+  });
+
+  //]]>
+  </script>
+
+</head>
+<body>
+  <h2>Thrift Haxe-Javascript Bindings</h2>
+
+  <div>
+      <h3>For testing :</h3>
+      <ol>
+          <li> run haxe-php tutorial server : <code>make 
tutorialserver_php_http</code></li>
+          <li> open <a 
href="http://localhost:9090/javascript.html";>http://localhost:9090/javascript.html</a>
 in browser
+          <li> click 'Test' </li>
+      </ol>
+  </div>
+
+  <h3>Protocol : </h3>
+  JSON : <input type="radio" name="prot" value="json" checked="checked" /> <br 
/>
+  Binary : <input type="radio" name="prot" value="binary" />
+  
+  <h3></h3>
+  <input type="button" id="repeat" value="Test" />
+
+  <h3>Trace Output : </h3>
+  <div id='trace'>
+  </div>
+
+  
+  <p>This Java Script example uses <a 
href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;hb=HEAD";>tutorial.thrift</a>
 and a Thrift server using JSON protocol and HTTP transport.
+  </p>
+    <p>
+        <a href="http://validator.w3.org/check/referer";><img
+            src="http://www.w3.org/Icons/valid-xhtml10";
+            alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+    </p>
+  <script src="bin/js/Main.js"        type="text/javascript"></script>
+</body>
+</html>
+
diff --git a/tutorial/haxe/javascript.hxml b/tutorial/haxe/javascript.hxml
index b2b3876cf1..d109d73352 100644
--- a/tutorial/haxe/javascript.hxml
+++ b/tutorial/haxe/javascript.hxml
@@ -26,7 +26,7 @@
 -main Main
 
 #JavaScript target
--js bin/Tutorial.js
+-js bin/js/Main.js
 
 #You can use -D source-map-content (requires Haxe 3.1+) to have the .hx 
 #files directly embedded into the map file, this way you only have to 
@@ -41,4 +41,4 @@
 #"-dce no" : do not remove unused code
 #"-dce std" : remove unused code in the std lib (default)
 #"-dce full" : remove all unused code
--dce full
\ No newline at end of file
+-dce full
diff --git a/tutorial/haxe/nodejs.hxml b/tutorial/haxe/nodejs.hxml
new file mode 100644
index 0000000000..83a7b9523d
--- /dev/null
+++ b/tutorial/haxe/nodejs.hxml
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+ 
+#integrate files to classpath
+-cp src
+-cp gen-haxe
+-cp ../../lib/haxe/src
+
+#libs
+-lib hxnodejs
+
+#this class wil be used as entry point for your app.
+-main Main
+
+#JavaScript target
+-js bin/nodejs/Main.js
+
+#You can use -D source-map-content (requires Haxe 3.1+) to have the .hx 
+#files directly embedded into the map file, this way you only have to 
+#upload it, and it will be always in sync with the compiled .js even if 
+#you modify your .hx files.
+-D source-map-content
+
+#Generate source map and add debug information
+-debug
+
+#dead code elimination : remove unused code
+#"-dce no" : do not remove unused code
+#"-dce std" : remove unused code in the std lib (default)
+#"-dce full" : remove all unused code
+-dce full
diff --git a/tutorial/haxe/src/Main.hx b/tutorial/haxe/src/Main.hx
index 6bebe71648..e7ddc16551 100644
--- a/tutorial/haxe/src/Main.hx
+++ b/tutorial/haxe/src/Main.hx
@@ -28,7 +28,6 @@ import org.apache.thrift.meta_data.*;
 import tutorial.*;
 import shared.*;
 
-
 enum Prot {
     binary;
     json;
@@ -39,6 +38,10 @@ enum Trns {
     http;
 }
 
+#if js
+@:expose
+@:keep
+#end
 class Main {
 
     private static var server : Bool = false;
@@ -52,7 +55,7 @@ class Main {
 
     static function main() {
 
-        #if ! (flash || js || phpwebserver)
+        #if ! (flash || phpwebserver || (js && !nodejs))
         try {
               ParseArgs();
         } catch (e : String) {
@@ -62,6 +65,19 @@ class Main {
         }
 
         #elseif  phpwebserver
+        //support json proto via url
+        var uri = php.Web.getURI();
+        if(uri == '/json') {
+            prot = json;
+        } else if (uri != '/' && uri.length > 0) {
+            //work as simple web server for files in directory
+            Sys.stderr().writeString('${uri}\n');
+            var path = uri.substr(1); //remove trailing /
+            if(sys.FileSystem.exists(path) && 
!sys.FileSystem.isDirectory(path)) {
+                php.Lib.printFile(path);
+                return;
+            }
+        }
         //forcing server
         server = true;
         trns = http;
@@ -71,8 +87,14 @@ class Main {
           Sys.println('http endpoint for thrift test server');
           return;
         }
+        //provide content type
+        #elseif (js && !nodejs)
+        trns = http;
+        prot = json;
+        initJsBrowser();
         #end
 
+        #if ! (flash || (js && !nodejs))
         try {
             if (server)
                 RunServer();
@@ -83,7 +105,31 @@ class Main {
         }
 
         trace("Completed.");
+        #end
     }
+    #if (js && !nodejs)
+    private static function initJsBrowser()
+    {
+        //remap trace to div
+        haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos)
+        {
+          // handle trace
+          var newValue : Dynamic;
+          if (infos != null && infos.customParams!=null) {
+            var extra:String = "";
+            for( v in infos.customParams )
+              extra += "," + v;
+            newValue = v + extra;
+          }
+          else {
+            newValue = v;
+          }
+          var msg = infos != null ? infos.fileName + ':' + infos.lineNumber + 
': ' : '';
+          var traceDiv = new js.JQuery('#trace');
+          traceDiv.html(traceDiv.html() + '<br />${msg}${newValue}');
+        }
+    }
+    #end
 
     #if phpwebserver
     private static function initPhpWebServer()
@@ -109,7 +155,7 @@ class Main {
     #end
 
 
-    #if ! (flash || js)
+    #if ! (flash || (js && !nodejs))
 
     private static function GetHelp() : String {
         return Sys.executablePath()+"  modus  trnsOption  transport  
protocol\n"
@@ -178,6 +224,14 @@ class Main {
 
     #end
 
+    public static function setProtJson() {
+        prot = json;
+    }
+
+    public static function setProtBinary() {
+        prot = binary;
+    }
+
     private static function ClientSetup() : Calculator {
          trace("Client configuration:");
 
@@ -190,6 +244,11 @@ class Main {
             transport = new TSocket( targetHost, targetPort);
         case http:
             var uri = 'http://${targetHost}:${targetPort}';
+            #if js
+            if(haxe.Json.stringify(prot) == haxe.Json.stringify(json)) {
+                uri += '/json';
+            }
+            #end
             trace('- HTTP transport $uri');
             transport = new THttpClient(uri);
         default:
@@ -236,8 +295,10 @@ class Main {
             trace("ping() successful");
         } catch(error : TException) {
             trace('ping() failed: $error');
+             trace(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
         } catch(error : Dynamic) {
             trace('ping() failed: $error');
+            trace(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
         }
 
         try {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> haxe js/nodejs client
> ---------------------
>
>                 Key: THRIFT-3876
>                 URL: https://issues.apache.org/jira/browse/THRIFT-3876
>             Project: Thrift
>          Issue Type: Improvement
>          Components: Haxe - Library
>            Reporter: Oleksii Prudkyi
>            Assignee: Oleksii Prudkyi
>            Priority: Major
>




--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to