diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..53fe1d7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+node_modules
+
+# Optional npm cache directory
+.npm
+
+# Optional REPL history
+.node_repl_history
+
+example/test.html
+
+.vscode
+package-lock.json
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..fd01957
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,25 @@
+{
+ "sub":true,
+ "laxbreak":true,
+ "laxcomma":true,
+ "regexp":true,
+ "asi": true,
+ "browser": true,
+ "loopfunc":true,
+ "expr":true,
+ "es3": true,
+ "esnext": true,
+ "curly": true,
+ "immed": true,
+ "latedef": false,
+ "expr": true,
+ "eqeqeq": false,
+ "eqnull": false,
+ "newcap": true,
+ "noarg": true,
+ "undef": true,
+ "unused": true,
+ "proto": true,
+ "strict": false,
+ "smarttabs": true
+}
diff --git a/LICENSE.md b/LICENSE.md
index 5a1390e..70a0e7b 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2008-2015 http://hprose.com
+Copyright (c) 2008-2018 http://hprose.com
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
diff --git a/README.md b/README.md
index e9e101e..2eb9986 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,21 @@
+

+
-
-
-
-
+
+
# Hprose for HTML5
[](https://gitter.im/hprose/hprose-html5?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](http://bower.io/search/?q=hprose-html5)
+[](https://www.npmjs.com/package/hprose-html5)
[](https://github.com/hprose/hprose-html5/releases)
[](http://opensource.org/licenses/MIT)
>---
- **[Introduction](#introduction)**
- **[Browser support](#browser-support)**
+ - **[Hybird app support](#hybird-app-support)**
- **[Usage](#usage)**
- **[Exception Handling](#exception-handling)**
@@ -70,6 +71,17 @@ This project is the implementation of Hprose for HTML5.
* Internet Explorer on Windows Phone
* ...
+### Hybird app support
+
+* ionic + cordova (http, tcp, websocket)
+* Chrome extentions (http, tcp, websocket)
+* APICloud (http, tcp*)
+* DCloud (http)
+* AppCan (http)
+* ... (http, websocket)
+
+TCP is only available on iOS for APICloud, because there is a bug of APICloud Android SDK, and they don't want to fix this bug.
+
## Usage
You don't need use the javascript source files. You only need include `hprose-html5.js` in your html.
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 9aafdde..7b5497b 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -1,21 +1,21 @@
+
+
-
-
-
-
+
# Hprose for HTML5
[](https://gitter.im/hprose/hprose-html5?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](http://bower.io/search/?q=hprose-html5)
+[](https://www.npmjs.com/package/hprose-html5)
[](https://github.com/hprose/hprose-html5/releases)
[](http://opensource.org/licenses/MIT)
>---
- **[简介](#简介)**
- **[浏览器支持](#浏览器支持)**
+ - **[混合应用支持](#混合应用支持)**
- **[使用](#使用)**
- **[异常处理](#异常处理)**
@@ -71,6 +71,17 @@
* Internet Explorer on Windows Phone
* ...
+### 混合应用支持
+
+* ionic + cordova (http, tcp, websocket)
+* Chrome extentions (http, tcp, websocket)
+* APICloud (http, tcp*)
+* DCloud (http)
+* AppCan (http)
+* ... (http, websocket)
+
+在 APICloud 平台上,TCP 只在 iOS 上有效,因为 APICloud 的 Android SDK 有个 bug,但是他们不肯修复,所以我也无能为力。
+
## 使用
你不需要使用 javascript 的源文件,你只需要在你的 html 中包含 `hprose-html5.js` 就够了。
diff --git a/bower.json b/bower.json
index 0ce04a7..531cef3 100644
--- a/bower.json
+++ b/bower.json
@@ -1,8 +1,8 @@
{
"author": "Ma Bingyao ",
"name": "hprose-html5",
- "version": "2.0.3",
- "description": "Hprose is a High Performance Remote Object Service Engine. It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware.",
+ "version": "2.0.36",
+ "description": "Hprose is a High Performance Remote Object Service Engine.",
"keywords": [
"hprose",
"rpc",
diff --git a/dist/hprose-html5.js b/dist/hprose-html5.js
index d9519f1..0c6b7c0 100644
--- a/dist/hprose-html5.js
+++ b/dist/hprose-html5.js
@@ -1,7 +1,9 @@
-// Hprose for HTML5 v2.0.3
-// Copyright (c) 2008-2015 http://hprose.com
+// Hprose for HTML5 v2.0.36
+// Copyright (c) 2008-2016 http://hprose.com
// Hprose is freely distributable under the MIT license.
// For all details and documentation:
// https://github.com/hprose/hprose-html5
-eval(function(n){"use strict";function r(n){var r=[];return r[n-1]=void 0,r}function u(n,r){return f(n[0]+r[0],n[1]+r[1])}function t(n,r){var u,t;return n[0]==r[0]&&n[1]==r[1]?0:(u=0>n[1],t=0>r[1],u&&!t?-1:!u&&t?1:a(n,r)[1]<0?-1:1)}function f(n,r){var u,t;for(r%=0x10000000000000000,n%=0x10000000000000000,u=r%un,t=Math.floor(n/un)*un,r=r-u+t,n=n-t+u;0>n;)n+=un,r-=un;for(;n>4294967295;)n-=un,r+=un;for(r%=0x10000000000000000;r>0x7fffffff00000000;)r-=0x10000000000000000;for(;-0x8000000000000000>r;)r+=0x10000000000000000;return[n,r]}function i(n){return n>=0?[n,0]:[n+un,-un]}function c(n){return n[0]>=2147483648?~~Math.max(Math.min(n[0]-un,2147483647),-2147483648):~~Math.max(Math.min(n[0],2147483647),-2147483648)}function a(n,r){return f(n[0]-r[0],n[1]-r[1])}function o(n,r){return n.ab=r,n.cb=0,n.O=r.length,n}function e(n){return n.cb>=n.O?-1:255&n.ab[n.cb++]}function v(n){return n.ab=r(32),n.O=0,n}function s(n){var r=n.ab;return r.length=n.O,r}function g(n,r,u,t){l(r,u,n.ab,n.O,t),n.O+=t}function l(n,r,u,t,f){for(var i=0;f>i;++i)u[t+i]=n[r+i]}function C(n,r,u){var t,f,c,a,o="",v=[];for(f=0;5>f;++f){if(c=e(r),-1==c)throw Error("truncated input");v[f]=c<<24>>24}if(t=F({}),!V(t,v))throw Error("corrupted input");for(f=0;64>f;f+=8){if(c=e(r),-1==c)throw Error("truncated input");c=c.toString(16),1==c.length&&(c="0"+c),o=c+""+o}/^0+$|^f+$/i.test(o)?n.M=tn:(a=parseInt(o,16),n.M=a>4294967295?tn:i(a)),n.S=M(t,r,u,n.M)}function z(n,r){return n.Y=v({}),C(n,o({},r),n.Y),n}function p(n,r,u){var t=n.y-r-1;for(0>t&&(t+=n.c);0!=u;--u)t>=n.c&&(t=0),n.x[n.y++]=n.x[t++],n.y>=n.c&&N(n)}function x(n,u){(null==n.x||n.c!=u)&&(n.x=r(u)),n.c=u,n.y=0,n.w=0}function N(n){var r=n.y-n.w;r&&(g(n.T,n.x,n.w,r),n.y>=n.c&&(n.y=0),n.w=n.y)}function d(n,r){var u=n.y-r-1;return 0>u&&(u+=n.c),n.x[u]}function J(n,r){n.x[n.y++]=r,n.y>=n.c&&N(n)}function L(n){N(n),n.T=null}function j(n){return n-=2,4>n?n:3}function B(n){return 4>n?0:10>n?n-3:n-6}function b(n,r){return n.h=r,n.bb=null,n.V=1,n}function k(n){if(!n.V)throw Error("bad state");if(n.bb)throw Error("No encoding");return h(n),n.V}function h(n){var r=U(n.h);if(-1==r)throw Error("corrupted input");n.$=tn,n.Z=n.h.d,(r||t(n.h.U,fn)>=0&&t(n.h.d,n.h.U)>=0)&&(N(n.h.b),L(n.h.b),n.h.a.K=null,n.V=0)}function M(n,r,u,t){return n.a.K=r,L(n.b),n.b.T=u,A(n),n.f=0,n.l=0,n.Q=0,n.R=0,n._=0,n.U=t,n.d=fn,n.G=0,b({},n)}function U(n){var r,f,a,o,e,v;if(v=c(n.d)&n.P,Q(n.a,n.t,(n.f<<4)+v)){if(Q(n.a,n.E,n.f))a=0,Q(n.a,n.r,n.f)?(Q(n.a,n.u,n.f)?(Q(n.a,n.s,n.f)?(f=n._,n._=n.R):f=n.R,n.R=n.Q):f=n.Q,n.Q=n.l,n.l=f):Q(n.a,n.o,(n.f<<4)+v)||(n.f=7>n.f?9:11,a=1),a||(a=q(n.n,n.a,v)+2,n.f=7>n.f?8:11);else if(n._=n.R,n.R=n.Q,n.Q=n.l,a=2+q(n.D,n.a,v),n.f=7>n.f?7:10,e=S(n.k[j(a)],n.a),e>=4){if(o=(e>>1)-1,n.l=(2|1&e)<e)n.l+=X(n.J,n.l-e-1,n.a,o);else if(n.l+=T(n.a,o-4)<<4,n.l+=Y(n.q,n.a),0>n.l)return-1==n.l?1:-1}else n.l=e;if(t(i(n.l),n.d)>=0||n.l>=n.m)return-1;p(n.b,n.l,a),n.d=u(n.d,i(a)),n.G=d(n.b,0)}else r=D(n.j,c(n.d),n.G),n.G=7>n.f?E(r,n.a):R(r,n.a,d(n.b,n.l)),J(n.b,n.G),n.f=B(n.f),n.d=u(n.d,cn);return 0}function F(n){n.b={},n.a={},n.t=r(192),n.E=r(12),n.r=r(12),n.u=r(12),n.s=r(12),n.o=r(192),n.k=r(4),n.J=r(114),n.q=H({},4),n.D=m({}),n.n=m({}),n.j={};for(var u=0;4>u;++u)n.k[u]=H({},6);return n}function A(n){n.b.w=0,n.b.y=0,I(n.t),I(n.o),I(n.E),I(n.r),I(n.u),I(n.s),I(n.J),Z(n.j);for(var r=0;4>r;++r)I(n.k[r].z);w(n.D),w(n.n),I(n.q.z),K(n.a)}function V(n,r){var u,t,f,i,c,a,o;if(5>r.length)return 0;for(o=255&r[0],f=o%9,a=~~(o/9),i=a%5,c=~~(a/5),u=0,t=0;4>t;++t)u+=(255&r[1+t])<<8*t;return u>99999999||!W(n,f,i,c)?0:G(n,u)}function G(n,r){return 0>r?0:(n.A!=r&&(n.A=r,n.m=Math.max(n.A,1),x(n.b,Math.max(n.m,4096))),1)}function W(n,r,u,t){if(r>8||u>4||t>4)return 0;P(n.j,u,r);var f=1<n.e;++n.e)n.I[n.e]=H({},3),n.H[n.e]=H({},3)}function q(n,r,u){if(!Q(r,n.N,0))return S(n.I[u],r);var t=8;return t+=Q(r,n.N,1)?8+S(n.L,r):S(n.H[u],r)}function m(n){return n.N=r(2),n.I=r(16),n.H=r(16),n.L=H({},8),n.e=0,n}function w(n){I(n.N);for(var r=0;n.e>r;++r)I(n.I[r].z),I(n.H[r].z);I(n.L.z)}function P(n,u,t){var f,i;if(null==n.F||n.g!=t||n.B!=u)for(n.B=u,n.X=(1<f;++f)n.F[f]=y({})}function D(n,r,u){return n.F[((r&n.X)<>>8-n.g)]}function Z(n){var r,u;for(u=1<r;++r)I(n.F[r].v)}function E(n,r){var u=1;do u=u<<1|Q(r,n.v,u);while(256>u);return u<<24>>24}function R(n,r,u){var t,f,i=1;do if(f=u>>7&1,u<<=1,t=Q(r,n.v,(1+f<<8)+i),i=i<<1|t,f!=t){for(;256>i;)i=i<<1|Q(r,n.v,i);break}while(256>i);return i<<24>>24}function y(n){return n.v=r(768),n}function H(n,u){return n.C=u,n.z=r(1<t;++t)u=Q(r,n.z,f),f<<=1,f+=u,i|=u<i;++i)f=Q(u,n,r+c),c<<=1,c+=f,a|=f<>>11)*f,(-2147483648^t)>(-2147483648^n.p)?(n.i=t,r[u]=f+(2048-f>>>5)<<16>>16,-16777216&n.i||(n.p=n.p<<8|e(n.K),n.i<<=8),0):(n.i-=t,n.p-=t,r[u]=f-(f>>>5)<<16>>16,-16777216&n.i||(n.p=n.p<<8|e(n.K),n.i<<=8),1)}function T(n,r){var u,t,f=0;for(u=r;0!=u;--u)n.i>>>=1,t=n.p-n.i>>>31,n.p-=n.i&t-1,f=f<<1|1-t,-16777216&n.i||(n.p=n.p<<8|e(n.K),n.i<<=8);return f}function K(n){n.p=0,n.i=-1;for(var r=0;5>r;++r)n.p=n.p<<8|e(n.K)}function I(n){for(var r=n.length-1;r>=0;--r)n[r]=1024}function _(n){for(var r,u,t,f=0,i=0,c=n.length,a=[],o=[];c>f;++f,++i){if(r=255&n[f],128&r)if(192==(224&r)){if(f+1>=n.length)return n;if(u=255&n[++f],128!=(192&u))return n;o[i]=(31&r)<<6|63&u}else{if(224!=(240&r))return n;if(f+2>=n.length)return n;if(u=255&n[++f],128!=(192&u))return n;if(t=255&n[++f],128!=(192&t))return n;o[i]=(15&r)<<12|(63&u)<<6|63&t}else{if(!r)return n;o[i]=r}65535==i&&(a.push(String.fromCharCode.apply(String,o)),i=-1)}return i>0&&(o.length=i,a.push(String.fromCharCode.apply(String,o))),a.join("")}function $(n){return n>64&&91>n?n-65:n>96&&123>n?n-71:n>47&&58>n?n+4:43===n?62:47===n?63:0}function nn(r){for(var u,t,f=r.length,i=3*f+1>>>2,c=("Uint8Array"in n?new n.Uint8Array(i):new Array(i)),a=0,o=0,e=0;f>e;e++)if(t=3&e,a|=$(r.charCodeAt(e))<<18-6*t,3===t||f-e===1){for(u=0;3>u&&i>o;u++,o++)c[o]=a>>>(16>>>u&24)&255;a=0}return c}function rn(n){n=nn(n);var r={};for(r.d=z({},n);k(r.d.S););return _(s(r.d.Y))}var un=4294967296,tn=[4294967295,-un],fn=[0,0],cn=[1,0];return rn}(this)("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"));
\ No newline at end of file
+var hprose=Object.create(null);hprose.global="object"==typeof global?global:"object"==typeof window?window:"object"==typeof self?self:this,function(e,t){"use strict";function r(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return function(t){return e.apply(t,Array.prototype.slice.call(arguments,1))}}function n(e){for(var t=e.length,r=new Array(t),n=0;n>15,i=new Array(r?n+1:n),o=0;o=0?n=i:(n=r+i)<0&&(n=0);for(var o;n>>0,i=arguments[1],o=0;o>>0,i=arguments[1],o=0;o>>0,n=arguments[1],i=n>>0,o=i<0?Math.max(r+i,0):Math.min(i,r),a=arguments[2],u=void 0===a?r:a>>0,s=u<0?Math.max(r+u,0):Math.min(u,r);o>>0,i=e>>0,o=i<0?Math.max(n+i,0):Math.min(i,n),a=t>>0,u=a<0?Math.max(n+a,0):Math.min(a,n),s=arguments[2],c=void 0===s?n:s>>0,f=c<0?Math.max(n+c,0):Math.min(c,n),l=Math.min(f-u,n-o),h=1;for(u0;)u in r?r[o]=r[u]:delete r[o],u+=h,o+=h,l--;return r}}),Array.from||Object.defineProperty(Array,"from",{value:function(){var e=Object.prototype.toString,t=function(t){return"function"==typeof t||"[object Function]"===e.call(t)},r=function(e){var t=Number(e);return isNaN(t)?0:0!==t&&isFinite(t)?(t>0?1:-1)*Math.floor(Math.abs(t)):t},n=Math.pow(2,53)-1,i=function(e){var t=r(e);return Math.min(Math.max(t,0),n)};return function(e){var r=this,n=Object(e);if(null===e||void 0===e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var o,a=arguments.length>1?arguments[1]:void 0;if(void 0!==a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(o=arguments[2])}for(var u,s=i(n.length),c=t(r)?Object(new r(s)):new Array(s),f=0;fr.length)&&(t=r.length),t-=e.length;var n=r.indexOf(e,t);return-1!==n&&n===t}}),String.prototype.includes||Object.defineProperty(String.prototype,"includes",{value:function(){return"number"==typeof arguments[1]?!(this.length=1<<28)throw new RangeError("repeat count must not overflow maximum string size");for(var r="";1==(1&e)&&(r+=t),0!==(e>>>=1);)t+=t;return r}}),String.prototype.trim||Object.defineProperty(String.prototype,"trim",{value:function(){return this.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")}}),String.prototype.trimLeft||Object.defineProperty(String.prototype,"trimLeft",{value:function(){return this.toString().replace(/^[\s\xa0]+/,"")}}),String.prototype.trimRight||Object.defineProperty(String.prototype,"trimRight",{value:function(){return this.toString().replace(/[\s\xa0]+$/,"")}}),Object.keys||Object.defineProperty(Object,"keys",{value:function(){var e=Object.prototype.hasOwnProperty,t=!{toString:null}.propertyIsEnumerable("toString"),r=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=r.length;return function(i){if("object"!=typeof i&&"function"!=typeof i||null===i)throw new TypeError("Object.keys called on non-object");var o=[];for(var a in i)e.call(i,a)&&o.push(a);if(t)for(var u=0;u0&&Array.isArray(arguments[0]))for(var s=arguments[0],c=0,f=s.length;c0&&Array.isArray(arguments[0]))for(var o=arguments[0],a=0,f=o.length;a0&&Array.isArray(arguments[0]))for(var o=arguments[0],a=0,u=o.length;a0;)i(e.shift())}).observe(t,{characterData:!0}),function(){var r=o(arguments);return e.push(r),t.data=1&r,r}},s.messageChannel=function(){var t=new e.MessageChannel;return t.port1.onmessage=function(e){i(Number(e.data))},function(){var e=o(arguments);return t.port2.postMessage(e),e}},s.nextTick=function(){return function(){var t=o(arguments);return e.process.nextTick(r(i,t)),t}},s.postMessage=function(){var e=a.createElement("iframe");e.style.display="none",a.documentElement.appendChild(e);var t=e.contentWindow;t.document.write('');
+ iwin.document.close();
+ var queue = [];
+ window.addEventListener('message', function() {
+ while (queue.length > 0) {
+ run(queue.shift());
+ }
+ });
+ return function() {
+ var handleId = create(arguments);
+ queue.push(handleId);
+ iwin.postMessage(1, "*");
+ return handleId;
+ };
+ };
+
+ polifill.readyStateChange = function() {
+ var html = doc.documentElement;
+
+ return function() {
+ var handleId = create(arguments);
+ var script = doc.createElement('script');
+
+ script.onreadystatechange = function() {
+ run(handleId);
+ script.onreadystatechange = null;
+ html.removeChild(script);
+ script = null;
+ };
+
+ html.appendChild(script);
+
+ return handleId;
+ };
+ };
+
+ // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
+ var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
+ attachTo = (attachTo && attachTo.setTimeout ? attachTo : global);
+
+ polifill.setTimeout = function() {
+ return function() {
+ var handleId = create(arguments);
+ attachTo.setTimeout( wrap( run, handleId ), 0 );
+ return handleId;
+ };
+ };
+
+ // Don't get fooled by e.g. browserify environments.
+ // For Node.js before 0.9
+ if (typeof(global.process) !== 'undefined' &&
+ Object.prototype.toString.call(global.process) === '[object process]' &&
+ !global.process.browser) {
+ attachTo.setImmediate = polifill.nextTick();
+ }
+ // For IE 6–9
+ else if (doc && ('onreadystatechange' in doc.createElement('script'))) {
+ attachTo.setImmediate = polifill.readyStateChange();
+ }
+ // For MutationObserver, where supported
+ else if (doc && MutationObserver) {
+ attachTo.setImmediate = polifill.mutationObserver();
+ }
+ // For web workers, where supported
+ else if (global.MessageChannel) {
+ attachTo.setImmediate = polifill.messageChannel();
+ }
+ // For non-IE modern browsers
+ else if (doc && 'postMessage' in global && 'addEventListener' in global) {
+ attachTo.setImmediate = polifill.postMessage();
+ }
+ // For older browsers
+ else {
+ attachTo.setImmediate = polifill.setTimeout();
+ }
+
+ attachTo.clearImmediate = clear;
+})(hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Future.js *
+ * *
+ * hprose Future for HTML5. *
+ * *
+ * LastModified: Dec 5, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var PENDING = 0;
+ var FULFILLED = 1;
+ var REJECTED = 2;
+
+ var hasPromise = 'Promise' in global;
+ var setImmediate = global.setImmediate;
+ var setTimeout = global.setTimeout;
+ var clearTimeout = global.clearTimeout;
+ var TimeoutError = global.TimeoutError;
+
+ var foreach = Array.prototype.forEach;
+ var slice = Array.prototype.slice;
+
+ function Future(computation) {
+ var self = this;
+ Object.defineProperties(this, {
+ _subscribers: { value: [] },
+ resolve: { value: this.resolve.bind(this) },
+ reject: { value: this.reject.bind(this) }
+ });
+ if (typeof computation === 'function') {
+ setImmediate(function() {
+ try {
+ self.resolve(computation());
+ }
+ catch(e) {
+ self.reject(e);
+ }
+ });
+ }
+ }
+
+ function isFuture(obj) {
+ return obj instanceof Future;
+ }
+
+ function toFuture(obj) {
+ return isFuture(obj) ? obj : value(obj);
+ }
+
+ function isPromise(obj) {
+ return 'function' === typeof obj.then;
+ }
+
+ function delayed(duration, value) {
+ var computation = (typeof value === 'function') ?
+ value :
+ function() { return value; };
+ var future = new Future();
+ setTimeout(function() {
+ try {
+ future.resolve(computation());
+ }
+ catch(e) {
+ future.reject(e);
+ }
+ }, duration);
+ return future;
+ }
+
+ function error(e) {
+ var future = new Future();
+ future.reject(e);
+ return future;
+ }
+
+ function value(v) {
+ var future = new Future();
+ future.resolve(v);
+ return future;
+ }
+
+ function sync(computation) {
+ try {
+ var result = computation();
+ return value(result);
+ }
+ catch(e) {
+ return error(e);
+ }
+ }
+
+ function promise(executor) {
+ var future = new Future();
+ executor(future.resolve, future.reject);
+ return future;
+ }
+
+ function arraysize(array) {
+ var size = 0;
+ foreach.call(array, function() { ++size; });
+ return size;
+ }
+
+ function all(array) {
+ return toFuture(array).then(function(array) {
+ var n = array.length;
+ var count = arraysize(array);
+ var result = new Array(n);
+ if (count === 0) { return result; }
+ var future = new Future();
+ foreach.call(array, function(element, index) {
+ toFuture(element).then(function(value) {
+ result[index] = value;
+ if (--count === 0) {
+ future.resolve(result);
+ }
+ },
+ future.reject);
+ });
+ return future;
+ });
+ }
+
+ function join() {
+ return all(arguments);
+ }
+
+ function race(array) {
+ return toFuture(array).then(function(array) {
+ var future = new Future();
+ foreach.call(array, function(element) {
+ toFuture(element).fill(future);
+ });
+ return future;
+ });
+ }
+
+ function any(array) {
+ return toFuture(array).then(function(array) {
+ var n = array.length;
+ var count = arraysize(array);
+ if (count === 0) {
+ throw new RangeError('any(): array must not be empty');
+ }
+ var reasons = new Array(n);
+ var future = new Future();
+ foreach.call(array, function(element, index) {
+ toFuture(element).then(future.resolve, function(e) {
+ reasons[index] = e;
+ if (--count === 0) {
+ future.reject(reasons);
+ }
+ });
+ });
+ return future;
+ });
+ }
+
+ function settle(array) {
+ return toFuture(array).then(function(array) {
+ var n = array.length;
+ var count = arraysize(array);
+ var result = new Array(n);
+ if (count === 0) { return result; }
+ var future = new Future();
+ foreach.call(array, function(element, index) {
+ var f = toFuture(element);
+ f.complete(function() {
+ result[index] = f.inspect();
+ if (--count === 0) {
+ future.resolve(result);
+ }
+ });
+ });
+ return future;
+ });
+ }
+
+ function attempt(handler/*, arg1, arg2, ... */) {
+ var thisArg = (function() { return this; })();
+ var args = slice.call(arguments, 1);
+ return all(args).then(function(args) {
+ return handler.apply(thisArg, args);
+ });
+ }
+
+ function run(handler, thisArg/*, arg1, arg2, ... */) {
+ var args = slice.call(arguments, 2);
+ return all(args).then(function(args) {
+ return handler.apply(thisArg, args);
+ });
+ }
+
+ function isGenerator(obj) {
+ if (!obj) {
+ return false;
+ }
+ return 'function' == typeof obj.next && 'function' == typeof obj['throw'];
+ }
+
+ function isGeneratorFunction(obj) {
+ if (!obj) {
+ return false;
+ }
+ var constructor = obj.constructor;
+ if (!constructor) {
+ return false;
+ }
+ if ('GeneratorFunction' === constructor.name ||
+ 'GeneratorFunction' === constructor.displayName) {
+ return true;
+ }
+ return isGenerator(constructor.prototype);
+ }
+
+ function getThunkCallback(future) {
+ return function(err, res) {
+ if (err instanceof Error) {
+ return future.reject(err);
+ }
+ if (arguments.length < 2) {
+ return future.resolve(err);
+ }
+ if (err === null || err === undefined) {
+ res = slice.call(arguments, 1);
+ }
+ else {
+ res = slice.call(arguments, 0);
+ }
+ if (res.length == 1) {
+ future.resolve(res[0]);
+ }
+ else {
+ future.resolve(res);
+ }
+ };
+ }
+
+ function thunkToPromise(fn) {
+ if (isGeneratorFunction(fn) || isGenerator(fn)) {
+ return co(fn);
+ }
+ var thisArg = (function() { return this; })();
+ var future = new Future();
+ fn.call(thisArg, getThunkCallback(future));
+ return future;
+ }
+
+ function thunkify(fn) {
+ return function() {
+ var args = slice.call(arguments, 0);
+ var thisArg = this;
+ var results = new Future();
+ args.push(function() {
+ thisArg = this;
+ results.resolve(arguments);
+ });
+ try {
+ fn.apply(this, args);
+ }
+ catch (err) {
+ results.resolve([err]);
+ }
+ return function(done) {
+ results.then(function(results) {
+ done.apply(thisArg, results);
+ });
+ };
+ };
+ }
+
+ function promisify(fn) {
+ return function() {
+ var args = slice.call(arguments, 0);
+ var future = new Future();
+ args.push(getThunkCallback(future));
+ try {
+ fn.apply(this, args);
+ }
+ catch (err) {
+ future.reject(err);
+ }
+ return future;
+ };
+ }
+
+ function toPromise(obj) {
+ if (isGeneratorFunction(obj) || isGenerator(obj)) {
+ return co(obj);
+ }
+ return toFuture(obj);
+ }
+
+ function co(gen) {
+ var thisArg = (function() { return this; })();
+ if (typeof gen === 'function') {
+ var args = slice.call(arguments, 1);
+ gen = gen.apply(thisArg, args);
+ }
+
+ if (!gen || typeof gen.next !== 'function') {
+ return toFuture(gen);
+ }
+
+ var future = new Future();
+
+ function onFulfilled(res) {
+ try {
+ next(gen.next(res));
+ }
+ catch (e) {
+ future.reject(e);
+ }
+ }
+
+ function onRejected(err) {
+ try {
+ next(gen['throw'](err));
+ }
+ catch (e) {
+ future.reject(e);
+ }
+ }
+
+ function next(ret) {
+ if (ret.done) {
+ future.resolve(ret.value);
+ }
+ else {
+ (('function' == typeof ret.value) ?
+ thunkToPromise(ret.value) :
+ toPromise(ret.value)).then(onFulfilled, onRejected);
+ }
+ }
+
+ onFulfilled();
+
+ return future;
+ }
+
+ function wrap(handler, thisArg) {
+ return function() {
+ thisArg = thisArg || this;
+ return all(arguments).then(function(args) {
+ var result = handler.apply(thisArg, args);
+ if (isGeneratorFunction(result) || isGenerator(result)) {
+ return co.call(thisArg, result);
+ }
+ return result;
+ });
+ };
+ }
+
+ co.wrap = wrap;
+
+ function forEach(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.forEach(callback, thisArg);
+ });
+ }
+
+ function every(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.every(callback, thisArg);
+ });
+ }
+
+ function some(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.some(callback, thisArg);
+ });
+ }
+
+ function filter(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.filter(callback, thisArg);
+ });
+ }
+
+ function map(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.map(callback, thisArg);
+ });
+ }
+
+ function reduce(array, callback, initialValue) {
+ if (arguments.length > 2) {
+ return all(array).then(function(array) {
+ return toFuture(initialValue).then(function(value) {
+ return array.reduce(callback, value);
+ });
+ });
+ }
+ return all(array).then(function(array) {
+ return array.reduce(callback);
+ });
+ }
+
+ function reduceRight(array, callback, initialValue) {
+ if (arguments.length > 2) {
+ return all(array).then(function(array) {
+ return toFuture(initialValue).then(function(value) {
+ return array.reduceRight(callback, value);
+ });
+ });
+ }
+ return all(array).then(function(array) {
+ return array.reduceRight(callback);
+ });
+ }
+
+ function indexOf(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ return array.indexOf(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function lastIndexOf(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ if (fromIndex === undefined) {
+ fromIndex = array.length - 1;
+ }
+ return array.lastIndexOf(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function includes(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ return array.includes(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function find(array, predicate, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.find(predicate, thisArg);
+ });
+ }
+
+ function findIndex(array, predicate, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.findIndex(predicate, thisArg);
+ });
+ }
+
+ Object.defineProperties(Future, {
+ // port from Dart
+ delayed: { value: delayed },
+ error: { value: error },
+ sync: { value: sync },
+ value: { value: value },
+ // Promise compatible
+ all: { value: all },
+ race: { value: race },
+ resolve: { value: value },
+ reject: { value: error },
+ // extended methods
+ promise: { value: promise },
+ isFuture: { value: isFuture },
+ toFuture: { value: toFuture },
+ isPromise: { value: isPromise },
+ toPromise: { value: toPromise },
+ join: { value: join },
+ any: { value: any },
+ settle: { value: settle },
+ attempt: { value: attempt },
+ run: { value: run },
+ thunkify: { value: thunkify },
+ promisify: { value: promisify },
+ co: { value: co },
+ wrap: { value: wrap },
+ // for array
+ forEach: { value: forEach },
+ every: { value: every },
+ some: { value: some },
+ filter: { value: filter },
+ map: { value: map },
+ reduce: { value: reduce },
+ reduceRight: { value: reduceRight },
+ indexOf: { value: indexOf },
+ lastIndexOf: { value: lastIndexOf },
+ includes: { value: includes },
+ find: { value: find },
+ findIndex: { value: findIndex }
+ });
+
+ function _call(callback, next, x) {
+ setImmediate(function() {
+ try {
+ var r = callback(x);
+ next.resolve(r);
+ }
+ catch(e) {
+ next.reject(e);
+ }
+ });
+ }
+
+ function _resolve(onfulfill, next, x) {
+ if (onfulfill) {
+ _call(onfulfill, next, x);
+ }
+ else {
+ next.resolve(x);
+ }
+ }
+
+ function _reject(onreject, next, e) {
+ if (onreject) {
+ _call(onreject, next, e);
+ }
+ else {
+ next.reject(e);
+ }
+ }
+
+ Object.defineProperties(Future.prototype, {
+ _value: { writable: true },
+ _reason: { writable: true },
+ _state: { value: PENDING, writable: true },
+ resolve: { value: function(value) {
+ if (value === this) {
+ this.reject(new TypeError('Self resolution'));
+ return;
+ }
+ if (isFuture(value)) {
+ value.fill(this);
+ return;
+ }
+ if ((value !== null) &&
+ (typeof value === 'object') ||
+ (typeof value === 'function')) {
+ var then;
+ try {
+ then = value.then;
+ }
+ catch (e) {
+ this.reject(e);
+ return;
+ }
+ if (typeof then === 'function') {
+ var notrun = true;
+ try {
+ var self = this;
+ then.call(value, function(y) {
+ if (notrun) {
+ notrun = false;
+ self.resolve(y);
+ }
+ }, function(r) {
+ if (notrun) {
+ notrun = false;
+ self.reject(r);
+ }
+ });
+ return;
+ }
+ catch (e) {
+ if (notrun) {
+ notrun = false;
+ this.reject(e);
+ }
+ }
+ return;
+ }
+ }
+ if (this._state === PENDING) {
+ this._state = FULFILLED;
+ this._value = value;
+ var subscribers = this._subscribers;
+ while (subscribers.length > 0) {
+ var subscriber = subscribers.shift();
+ _resolve(subscriber.onfulfill, subscriber.next, value);
+ }
+ }
+ } },
+ reject: { value: function(reason) {
+ if (this._state === PENDING) {
+ this._state = REJECTED;
+ this._reason = reason;
+ var subscribers = this._subscribers;
+ while (subscribers.length > 0) {
+ var subscriber = subscribers.shift();
+ _reject(subscriber.onreject, subscriber.next, reason);
+ }
+ }
+ } },
+ then: { value: function(onfulfill, onreject) {
+ if (typeof onfulfill !== 'function') { onfulfill = null; }
+ if (typeof onreject !== 'function') { onreject = null; }
+ var next = new Future();
+ if (this._state === FULFILLED) {
+ _resolve(onfulfill, next, this._value);
+ }
+ else if (this._state === REJECTED) {
+ _reject(onreject, next, this._reason);
+ }
+ else {
+ this._subscribers.push({
+ onfulfill: onfulfill,
+ onreject: onreject,
+ next: next
+ });
+ }
+ return next;
+ } },
+ done: { value: function(onfulfill, onreject) {
+ this.then(onfulfill, onreject).then(null, function(error) {
+ setImmediate(function() { throw error; });
+ });
+ } },
+ inspect: { value: function() {
+ switch (this._state) {
+ case PENDING: return { state: 'pending' };
+ case FULFILLED: return { state: 'fulfilled', value: this._value };
+ case REJECTED: return { state: 'rejected', reason: this._reason };
+ }
+ } },
+ catchError: { value: function(onreject, test) {
+ if (typeof test === 'function') {
+ var self = this;
+ return this['catch'](function(e) {
+ if (test(e)) {
+ return self['catch'](onreject);
+ }
+ else {
+ throw e;
+ }
+ });
+ }
+ return this['catch'](onreject);
+ } },
+ 'catch': { value: function(onreject) {
+ return this.then(null, onreject);
+ } },
+ fail: { value: function(onreject) {
+ this.done(null, onreject);
+ } },
+ whenComplete: { value: function(action) {
+ return this.then(
+ function(v) { action(); return v; },
+ function(e) { action(); throw e; }
+ );
+ } },
+ complete: { value: function(oncomplete) {
+ oncomplete = oncomplete || function(v) { return v; };
+ return this.then(oncomplete, oncomplete);
+ } },
+ always: { value: function(oncomplete) {
+ this.done(oncomplete, oncomplete);
+ } },
+ fill: { value: function(future) {
+ this.then(future.resolve, future.reject);
+ } },
+ timeout: { value: function(duration, reason) {
+ var future = new Future();
+ var timeoutId = setTimeout(function() {
+ future.reject(reason || new TimeoutError('timeout'));
+ }, duration);
+ this.whenComplete(function() { clearTimeout(timeoutId); })
+ .fill(future);
+ return future;
+ } },
+ delay: { value: function(duration) {
+ var future = new Future();
+ this.then(function(result) {
+ setTimeout(function() {
+ future.resolve(result);
+ }, duration);
+ },
+ future.reject);
+ return future;
+ } },
+ tap: { value: function(onfulfilledSideEffect, thisArg) {
+ return this.then(function(result) {
+ onfulfilledSideEffect.call(thisArg, result);
+ return result;
+ });
+ } },
+ spread: { value: function(onfulfilledArray, thisArg) {
+ return this.then(function(array) {
+ return onfulfilledArray.apply(thisArg, array);
+ });
+ } },
+ get: { value: function(key) {
+ return this.then(function(result) {
+ return result[key];
+ });
+ } },
+ set: { value: function(key, value) {
+ return this.then(function(result) {
+ result[key] = value;
+ return result;
+ });
+ } },
+ apply: { value: function(method, args) {
+ args = args || [];
+ return this.then(function(result) {
+ return all(args).then(function(args) {
+ return result[method].apply(result, args);
+ });
+ });
+ } },
+ call: { value: function(method) {
+ var args = slice.call(arguments, 1);
+ return this.then(function(result) {
+ return all(args).then(function(args) {
+ return result[method].apply(result, args);
+ });
+ });
+ } },
+ bind: { value: function(method) {
+ var bindargs = slice.call(arguments);
+ if (Array.isArray(method)) {
+ for (var i = 0, n = method.length; i < n; ++i) {
+ bindargs[0] = method[i];
+ this.bind.apply(this, bindargs);
+ }
+ return;
+ }
+ bindargs.shift();
+ var self = this;
+ Object.defineProperty(this, method, { value: function() {
+ var args = slice.call(arguments);
+ return self.then(function(result) {
+ return all(bindargs.concat(args)).then(function(args) {
+ return result[method].apply(result, args);
+ });
+ });
+ } });
+ return this;
+ } },
+ forEach: { value: function(callback, thisArg) {
+ return forEach(this, callback, thisArg);
+ } },
+ every: { value: function(callback, thisArg) {
+ return every(this, callback, thisArg);
+ } },
+ some: { value: function(callback, thisArg) {
+ return some(this, callback, thisArg);
+ } },
+ filter: { value: function(callback, thisArg) {
+ return filter(this, callback, thisArg);
+ } },
+ map: { value: function(callback, thisArg) {
+ return map(this, callback, thisArg);
+ } },
+ reduce: { value: function(callback, initialValue) {
+ if (arguments.length > 1) {
+ return reduce(this, callback, initialValue);
+ }
+ return reduce(this, callback);
+ } },
+ reduceRight: { value: function(callback, initialValue) {
+ if (arguments.length > 1) {
+ return reduceRight(this, callback, initialValue);
+ }
+ return reduceRight(this, callback);
+ } },
+ indexOf: { value: function(searchElement, fromIndex) {
+ return indexOf(this, searchElement, fromIndex);
+ } },
+ lastIndexOf: { value: function(searchElement, fromIndex) {
+ return lastIndexOf(this, searchElement, fromIndex);
+ } },
+ includes: { value: function(searchElement, fromIndex) {
+ return includes(this, searchElement, fromIndex);
+ } },
+ find: { value: function(predicate, thisArg) {
+ return find(this, predicate, thisArg);
+ } },
+ findIndex: { value: function(predicate, thisArg) {
+ return findIndex(this, predicate, thisArg);
+ } }
+ });
+
+ hprose.Future = Future;
+
+ hprose.thunkify = thunkify;
+ hprose.promisify = promisify;
+ hprose.co = co;
+ hprose.co.wrap = hprose.wrap = wrap;
+
+ function Completer() {
+ var future = new Future();
+ Object.defineProperties(this, {
+ future: { value: future },
+ complete: { value: future.resolve },
+ completeError: { value: future.reject },
+ isCompleted: { get: function() {
+ return ( future._state !== PENDING );
+ } }
+ });
+ }
+
+ hprose.Completer = Completer;
+
+ hprose.resolved = value;
+
+ hprose.rejected = error;
+
+ hprose.deferred = function() {
+ var self = new Future();
+ return Object.create(null, {
+ promise: { value: self },
+ resolve: { value: self.resolve },
+ reject: { value: self.reject }
+ });
+ };
+
+ if (hasPromise) { return; }
+
+ function MyPromise(executor) {
+ Future.call(this);
+ executor(this.resolve, this.reject);
+ }
+
+ MyPromise.prototype = Object.create(Future.prototype);
+ MyPromise.prototype.constructor = Future;
+
+ Object.defineProperties(MyPromise, {
+ all: { value: all },
+ race: { value: race },
+ resolve: { value: value },
+ reject: { value: error }
+ });
+
+ global.Promise = MyPromise;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * BytesIO.js *
+ * *
+ * hprose BytesIO for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, undefined) {
+ 'use strict';
+
+ var toBinaryString = hprose.toBinaryString;
+
+ var _EMPTY_BYTES = new Uint8Array(0);
+ var _INIT_SIZE = 1024;
+
+ function writeInt32BE(bytes, p, i) {
+ bytes[p++] = i >>> 24 & 0xFF;
+ bytes[p++] = i >>> 16 & 0xFF;
+ bytes[p++] = i >>> 8 & 0xFF;
+ bytes[p++] = i & 0xFF;
+ return p;
+ }
+
+ function writeInt32LE(bytes, p, i) {
+ bytes[p++] = i & 0xFF;
+ bytes[p++] = i >>> 8 & 0xFF;
+ bytes[p++] = i >>> 16 & 0xFF;
+ bytes[p++] = i >>> 24 & 0xFF;
+ return p;
+ }
+
+ function writeString(bytes, p, str) {
+ var n = str.length;
+ for (var i = 0; i < n; ++i) {
+ var codeUnit = str.charCodeAt(i);
+ if (codeUnit < 0x80) {
+ bytes[p++] = codeUnit;
+ }
+ else if (codeUnit < 0x800) {
+ bytes[p++] = 0xC0 | (codeUnit >> 6);
+ bytes[p++] = 0x80 | (codeUnit & 0x3F);
+ }
+ else if (codeUnit < 0xD800 || codeUnit > 0xDFFF) {
+ bytes[p++] = 0xE0 | (codeUnit >> 12);
+ bytes[p++] = 0x80 | ((codeUnit >> 6) & 0x3F);
+ bytes[p++] = 0x80 | (codeUnit & 0x3F);
+ }
+ else {
+ if (i + 1 < n) {
+ var nextCodeUnit = str.charCodeAt(i + 1);
+ if (codeUnit < 0xDC00 && 0xDC00 <= nextCodeUnit && nextCodeUnit <= 0xDFFF) {
+ var rune = (((codeUnit & 0x03FF) << 10) | (nextCodeUnit & 0x03FF)) + 0x010000;
+ bytes[p++] = 0xF0 | (rune >> 18);
+ bytes[p++] = 0x80 | ((rune >> 12) & 0x3F);
+ bytes[p++] = 0x80 | ((rune >> 6) & 0x3F);
+ bytes[p++] = 0x80 | (rune & 0x3F);
+ ++i;
+ continue;
+ }
+ }
+ throw new Error('Malformed string');
+ }
+ }
+ return p;
+ }
+
+ function readShortString(bytes, n) {
+ var charCodes = new Array(n);
+ var i = 0, off = 0;
+ for (var len = bytes.length; i < n && off < len; i++) {
+ var unit = bytes[off++];
+ switch (unit >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ charCodes[i] = unit;
+ break;
+ case 12:
+ case 13:
+ if (off < len) {
+ charCodes[i] = ((unit & 0x1F) << 6) |
+ (bytes[off++] & 0x3F);
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 14:
+ if (off + 1 < len) {
+ charCodes[i] = ((unit & 0x0F) << 12) |
+ ((bytes[off++] & 0x3F) << 6) |
+ (bytes[off++] & 0x3F);
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 15:
+ if (off + 2 < len) {
+ var rune = (((unit & 0x07) << 18) |
+ ((bytes[off++] & 0x3F) << 12) |
+ ((bytes[off++] & 0x3F) << 6) |
+ (bytes[off++] & 0x3F)) - 0x10000;
+ if (0 <= rune && rune <= 0xFFFFF) {
+ charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800);
+ charCodes[i] = ((rune & 0x03FF) | 0xDC00);
+ break;
+ }
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ default:
+ throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
+ }
+ }
+ if (i < n) {
+ charCodes.length = i;
+ }
+ return [String.fromCharCode.apply(String, charCodes), off];
+ }
+
+ function readLongString(bytes, n) {
+ var buf = [];
+ var charCodes = new Array(0x8000);
+ var i = 0, off = 0;
+ for (var len = bytes.length; i < n && off < len; i++) {
+ var unit = bytes[off++];
+ switch (unit >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ charCodes[i] = unit;
+ break;
+ case 12:
+ case 13:
+ if (off < len) {
+ charCodes[i] = ((unit & 0x1F) << 6) |
+ (bytes[off++] & 0x3F);
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 14:
+ if (off + 1 < len) {
+ charCodes[i] = ((unit & 0x0F) << 12) |
+ ((bytes[off++] & 0x3F) << 6) |
+ (bytes[off++] & 0x3F);
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 15:
+ if (off + 2 < len) {
+ var rune = (((unit & 0x07) << 18) |
+ ((bytes[off++] & 0x3F) << 12) |
+ ((bytes[off++] & 0x3F) << 6) |
+ (bytes[off++] & 0x3F)) - 0x10000;
+ if (0 <= rune && rune <= 0xFFFFF) {
+ charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800);
+ charCodes[i] = ((rune & 0x03FF) | 0xDC00);
+ break;
+ }
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ default:
+ throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
+ }
+ if (i >= 0x7FFF - 1) {
+ var size = i + 1;
+ charCodes.length = size;
+ buf.push(String.fromCharCode.apply(String, charCodes));
+ n -= size;
+ i = -1;
+ }
+ }
+ if (i > 0) {
+ charCodes.length = i;
+ buf.push(String.fromCharCode.apply(String, charCodes));
+ }
+ return [buf.join(''), off];
+ }
+
+ function readString(bytes, n) {
+ if (n === undefined || n === null || (n < 0)) { n = bytes.length; }
+ if (n === 0) { return ['', 0]; }
+ return ((n < 0xFFFF) ?
+ readShortString(bytes, n) :
+ readLongString(bytes, n));
+ }
+
+ function readStringAsBytes(bytes, n) {
+ if (n === undefined) { n = bytes.length; }
+ if (n === 0) { return [_EMPTY_BYTES, 0]; }
+ var i = 0, off = 0;
+ for (var len = bytes.length; i < n && off < len; i++) {
+ var unit = bytes[off++];
+ switch (unit >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+ case 12:
+ case 13:
+ if (off < len) {
+ off++;
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 14:
+ if (off + 1 < len) {
+ off += 2;
+ break;
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ case 15:
+ if (off + 2 < len) {
+ var rune = (((unit & 0x07) << 18) |
+ ((bytes[off++] & 0x3F) << 12) |
+ ((bytes[off++] & 0x3F) << 6) |
+ (bytes[off++] & 0x3F)) - 0x10000;
+ if (0 <= rune && rune <= 0xFFFFF) {
+ i++;
+ break;
+ }
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
+ }
+ throw new Error('Unfinished UTF-8 octet sequence');
+ default:
+ throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
+ }
+ }
+ return [bytes.subarray(0, off), off];
+ }
+
+ function pow2roundup(x) {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+ }
+
+ function BytesIO() {
+ var a = arguments;
+ switch (a.length) {
+ case 1:
+ switch (a[0].constructor) {
+ case Uint8Array:
+ this._bytes = a[0];
+ this._length = a[0].length;
+ break;
+ case BytesIO:
+ this._bytes = a[0].toBytes();
+ this._length = a[0].length;
+ break;
+ case String:
+ this.writeString(a[0]);
+ break;
+ case Number:
+ this._bytes = new Uint8Array(a[0]);
+ break;
+ default:
+ this._bytes = new Uint8Array(a[0]);
+ this._length = this._bytes.length;
+ break;
+ }
+ break;
+ case 2:
+ this._bytes = new Uint8Array(a[0], a[1]);
+ this._length = a[1];
+ break;
+ case 3:
+ this._bytes = new Uint8Array(a[0], a[1], a[2]);
+ this._length = a[2];
+ break;
+ }
+ this.mark();
+ }
+
+ Object.defineProperties(BytesIO.prototype, {
+ _bytes: { value: null, writable: true },
+ _length: { value: 0, writable: true },
+ _wmark: { value: 0, writable: true },
+ _off: { value: 0, writable: true },
+ _rmark: { value: 0, writable: true },
+ _grow: { value: function(n) {
+ var bytes = this._bytes;
+ var required = this._length + n;
+ var size = pow2roundup(required);
+ if (bytes) {
+ size *= 2;
+ if (size > bytes.length) {
+ var buf = new Uint8Array(size);
+ buf.set(bytes);
+ this._bytes = buf;
+ }
+ }
+ else {
+ size = Math.max(size, _INIT_SIZE);
+ this._bytes = new Uint8Array(size);
+ }
+ } },
+ length: { get: function() { return this._length; } },
+ capacity: { get: function() {
+ return this._bytes ? this._bytes.length : 0;
+ } },
+ position: { get: function() { return this._off; } },
+ // returns a view of the the internal buffer.
+ bytes: { get : function() {
+ return (this._bytes === null) ?
+ _EMPTY_BYTES :
+ this._bytes.subarray(0, this._length);
+ } },
+ buffer: { get : function() {
+ if (this._bytes === null) {
+ return _EMPTY_BYTES.buffer;
+ }
+ if (this._bytes.buffer.slice) {
+ return this._bytes.buffer.slice(0, this._length);
+ }
+ var buf = new Uint8Array(this._length);
+ buf.set(this._bytes.subarray(0, this._length));
+ return buf.buffer;
+ } },
+ mark: { value: function() {
+ this._wmark = this._length;
+ this._rmark = this._off;
+ } },
+ reset: { value: function() {
+ this._length = this._wmark;
+ this._off = this._rmark;
+ } },
+ clear: { value: function() {
+ this._bytes = null;
+ this._length = 0;
+ this._wmark = 0;
+ this._off = 0;
+ this._rmark = 0;
+ } },
+ writeByte: { value: function(b) {
+ this._grow(1);
+ this._bytes[this._length++] = b;
+ } },
+ writeInt32BE: { value: function(i) {
+ if ((i === (i | 0)) && (i <= 2147483647)) {
+ this._grow(4);
+ this._length = writeInt32BE(this._bytes, this._length, i);
+ return;
+ }
+ throw new TypeError('value is out of bounds');
+ } },
+ writeUInt32BE: { value: function(i) {
+ if (((i & 0x7FFFFFFF) + 0x80000000 === i) && (i >= 0)) {
+ this._grow(4);
+ this._length = writeInt32BE(this._bytes, this._length, i | 0);
+ return;
+ }
+ throw new TypeError('value is out of bounds');
+ } },
+ writeInt32LE: { value: function(i) {
+ if ((i === (i | 0)) && (i <= 2147483647)) {
+ this._grow(4);
+ this._length = writeInt32LE(this._bytes, this._length, i);
+ return;
+ }
+ throw new TypeError('value is out of bounds');
+ } },
+ writeUInt32LE: { value: function(i) {
+ if (((i & 0x7FFFFFFF) + 0x80000000 === i) && (i >= 0)) {
+ this._grow(4);
+ this._length = writeInt32LE(this._bytes, this._length, i | 0);
+ return;
+ }
+ throw new TypeError('value is out of bounds');
+ } },
+ write: { value: function(data) {
+ var n = data.byteLength || data.length;
+ if (n === 0) { return; }
+ this._grow(n);
+ var bytes = this._bytes;
+ var length = this._length;
+ switch (data.constructor) {
+ case ArrayBuffer:
+ bytes.set(new Uint8Array(data), length);
+ break;
+ case Uint8Array:
+ bytes.set(data, length);
+ break;
+ case BytesIO:
+ bytes.set(data.bytes, length);
+ break;
+ default:
+ for (var i = 0; i < n; i++) {
+ bytes[length + i] = data[i];
+ }
+ break;
+ }
+ this._length += n;
+ } },
+ writeAsciiString: { value: function(str) {
+ var n = str.length;
+ if (n === 0) { return; }
+ this._grow(n);
+ var bytes = this._bytes;
+ var l = this._length;
+ for (var i = 0; i < n; ++i, ++l) {
+ bytes[l] = str.charCodeAt(i);
+ }
+ this._length = l;
+ } },
+ writeString: { value: function(str) {
+ var n = str.length;
+ if (n === 0) { return; }
+ // A single code unit uses at most 3 bytes.
+ // Two code units at most 4.
+ this._grow(n * 3);
+ this._length = writeString(this._bytes, this._length, str);
+ } },
+ readByte: { value: function() {
+ if (this._off < this._length) {
+ return this._bytes[this._off++];
+ }
+ return -1;
+ } },
+ readInt32BE: { value: function() {
+ var bytes = this._bytes;
+ var off = this._off;
+ if (off + 3 < this._length) {
+ var result = bytes[off++] << 24 |
+ bytes[off++] << 16 |
+ bytes[off++] << 8 |
+ bytes[off++];
+ this._off = off;
+ return result;
+ }
+ throw new Error('EOF');
+ } },
+ readUInt32BE: { value: function() {
+ var value = this.readInt32BE();
+ if (value < 0) {
+ return (value & 0x7FFFFFFF) + 0x80000000;
+ }
+ return value;
+ } },
+ readInt32LE: { value: function() {
+ var bytes = this._bytes;
+ var off = this._off;
+ if (off + 3 < this._length) {
+ var result = bytes[off++] |
+ bytes[off++] << 8 |
+ bytes[off++] << 16 |
+ bytes[off++] << 24;
+ this._off = off;
+ return result;
+ }
+ throw new Error('EOF');
+ } },
+ readUInt32LE: { value: function() {
+ var value = this.readInt32LE();
+ if (value < 0) {
+ return (value & 0x7FFFFFFF) + 0x80000000;
+ }
+ return value;
+ } },
+ read: { value: function(n) {
+ if (this._off + n > this._length) {
+ n = this._length - this._off;
+ }
+ if (n === 0) { return _EMPTY_BYTES; }
+ return this._bytes.subarray(this._off, this._off += n);
+ } },
+ skip: { value: function(n) {
+ if (this._off + n > this._length) {
+ n = this._length - this._off;
+ this._off = this._length;
+ }
+ else {
+ this._off += n;
+ }
+ return n;
+ } },
+ // the result is an Uint8Array, and includes tag.
+ readBytes: { value: function(tag) {
+ var pos = Array.indexOf(this._bytes, tag, this._off);
+ var buf;
+ if (pos === -1) {
+ buf = this._bytes.subarray(this._off, this._length);
+ this._off = this._length;
+ }
+ else {
+ buf = this._bytes.subarray(this._off, pos + 1);
+ this._off = pos + 1;
+ }
+ return buf;
+ } },
+ // the result is a String, and doesn't include tag.
+ // but the position is the same as readBytes
+ readUntil: { value: function(tag) {
+ var pos = Array.indexOf(this._bytes, tag, this._off);
+ var str = '';
+ if (pos === this._off) {
+ this._off++;
+ }
+ else if (pos === -1) {
+ str = readString(this._bytes.subarray(this._off, this._length))[0];
+ this._off = this._length;
+ }
+ else {
+ str = readString(this._bytes.subarray(this._off, pos))[0];
+ this._off = pos + 1;
+ }
+ return str;
+ } },
+ readAsciiString: { value: function(n) {
+ if (this._off + n > this._length) {
+ n = this._length - this._off;
+ }
+ if (n === 0) { return ''; }
+ return toBinaryString(this._bytes.subarray(this._off, this._off += n));
+ } },
+ // n is the UTF16 length
+ readStringAsBytes: { value: function(n) {
+ var r = readStringAsBytes(this._bytes.subarray(this._off, this._length), n);
+ this._off += r[1];
+ return r[0];
+ } },
+ // n is the UTF16 length
+ readString: { value: function(n) {
+ var r = readString(this._bytes.subarray(this._off, this._length), n);
+ this._off += r[1];
+ return r[0];
+ } },
+ // returns a view of the the internal buffer and clears `this`.
+ takeBytes: { value: function() {
+ var buffer = this.bytes;
+ this.clear();
+ return buffer;
+ } },
+ // returns a copy of the current contents and leaves `this` intact.
+ toBytes: { value: function() {
+ return new Uint8Array(this.bytes);
+ } },
+ toString: { value: function() {
+ return readString(this.bytes, this._length)[0];
+ } },
+ clone: { value: function() {
+ return new BytesIO(this.toBytes());
+ } },
+ trunc: { value: function() {
+ this._bytes = this._bytes.subarray(this._off, this._length);
+ this._length = this._bytes.length;
+ this._off = 0;
+ this._wmark = 0;
+ this._rmark = 0;
+ } }
+ });
+
+ function toString(data) {
+ /* jshint -W086 */
+ if (data.length === 0) { return ''; }
+ switch(data.constructor) {
+ case String: return data;
+ case BytesIO: data = data.bytes;
+ case ArrayBuffer: data = new Uint8Array(data);
+ case Uint8Array: return readString(data, data.length)[0];
+ default: return String.fromCharCode.apply(String, data);
+ }
+ }
+
+ Object.defineProperty(BytesIO, 'toString', { value: toString });
+
+ hprose.BytesIO = BytesIO;
+
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * Tags.js *
+ * *
+ * hprose tags enum for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose) {
+ 'use strict';
+
+ hprose.Tags = {
+ /* Serialize Tags */
+ TagInteger : 0x69, // 'i'
+ TagLong : 0x6C, // 'l'
+ TagDouble : 0x64, // 'd'
+ TagNull : 0x6E, // 'n'
+ TagEmpty : 0x65, // 'e'
+ TagTrue : 0x74, // 't'
+ TagFalse : 0x66, // 'f'
+ TagNaN : 0x4E, // 'N'
+ TagInfinity : 0x49, // 'I'
+ TagDate : 0x44, // 'D'
+ TagTime : 0x54, // 'T'
+ TagUTC : 0x5A, // 'Z'
+ TagBytes : 0x62, // 'b'
+ TagUTF8Char : 0x75, // 'u'
+ TagString : 0x73, // 's'
+ TagGuid : 0x67, // 'g'
+ TagList : 0x61, // 'a'
+ TagMap : 0x6d, // 'm'
+ TagClass : 0x63, // 'c'
+ TagObject : 0x6F, // 'o'
+ TagRef : 0x72, // 'r'
+ /* Serialize Marks */
+ TagPos : 0x2B, // '+'
+ TagNeg : 0x2D, // '-'
+ TagSemicolon : 0x3B, // ','
+ TagOpenbrace : 0x7B, // '{'
+ TagClosebrace : 0x7D, // '}'
+ TagQuote : 0x22, // '"'
+ TagPoint : 0x2E, // '.'
+ /* Protocol Tags */
+ TagFunctions : 0x46, // 'F'
+ TagCall : 0x43, // 'C'
+ TagResult : 0x52, // 'R'
+ TagArgument : 0x41, // 'A'
+ TagError : 0x45, // 'E'
+ TagEnd : 0x7A // 'z'
+ };
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * ClassManager.js *
+ * *
+ * hprose ClassManager for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global) {
+ 'use strict';
+
+ var WeakMap = global.WeakMap;
+
+ var classCache = Object.create(null);
+ var aliasCache = new WeakMap();
+
+ function register(cls, alias) {
+ aliasCache.set(cls, alias);
+ classCache[alias] = cls;
+ }
+
+ function getClassAlias(cls) {
+ return aliasCache.get(cls);
+ }
+
+ function getClass(alias) {
+ return classCache[alias];
+ }
+
+ hprose.ClassManager = Object.create(null, {
+ register: { value: register },
+ getClassAlias: { value: getClassAlias },
+ getClass: { value: getClass }
+ });
+
+ hprose.register = register;
+
+ register(Object, 'Object');
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Writer.js *
+ * *
+ * hprose Writer for HTML5. *
+ * *
+ * LastModified: Feb 13, 2017 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Map = global.Map;
+ var BytesIO = hprose.BytesIO;
+ var Tags = hprose.Tags;
+ var ClassManager = hprose.ClassManager;
+
+ function getClassName(obj) {
+ var cls = obj.constructor;
+ if (!cls) {
+ return 'Object';
+ }
+ var classname = ClassManager.getClassAlias(cls);
+ if (classname) { return classname; }
+ if (cls.name) {
+ classname = cls.name;
+ }
+ else {
+ var ctor = cls.toString();
+ classname = ctor.substr(0, ctor.indexOf('(')).replace(/(^\s*function\s*)|(\s*$)/ig, '');
+ if (classname === '' || classname === 'Object') {
+ return (typeof(obj.getClassName) === 'function') ? obj.getClassName() : 'Object';
+ }
+ }
+ if (classname !== 'Object') {
+ ClassManager.register(cls, classname);
+ }
+ return classname;
+ }
+
+ var fakeWriterRefer = Object.create(null, {
+ set: { value: function () {} },
+ write: { value: function () { return false; } },
+ reset: { value: function () {} }
+ });
+
+ function RealWriterRefer(stream) {
+ Object.defineProperties(this, {
+ _stream: { value: stream },
+ _ref: { value: new Map(), writable: true }
+ });
+ }
+
+ Object.defineProperties(RealWriterRefer.prototype, {
+ _refcount: { value: 0, writable: true },
+ set: { value: function (val) {
+ this._ref.set(val, this._refcount++);
+ } },
+ write: { value: function (val) {
+ var index = this._ref.get(val);
+ if (index !== undefined) {
+ this._stream.writeByte(Tags.TagRef);
+ this._stream.writeString('' + index);
+ this._stream.writeByte(Tags.TagSemicolon);
+ return true;
+ }
+ return false;
+ } },
+ reset: { value: function () {
+ this._ref = new Map();
+ this._refcount = 0;
+ } }
+ });
+
+ function realWriterRefer(stream) {
+ return new RealWriterRefer(stream);
+ }
+
+ function Writer(stream, simple) {
+ Object.defineProperties(this, {
+ stream: { value: stream },
+ _classref: { value: Object.create(null), writable: true },
+ _fieldsref: { value: [], writable: true },
+ _refer: { value: simple ? fakeWriterRefer : realWriterRefer(stream) }
+ });
+ }
+
+ function serialize(writer, value) {
+ var stream = writer.stream;
+ if (value === undefined || value === null) {
+ stream.writeByte(Tags.TagNull);
+ return;
+ }
+ switch (value.constructor) {
+ case Function:
+ stream.writeByte(Tags.TagNull);
+ return;
+ case Number:
+ writeNumber(writer, value);
+ return;
+ case Boolean:
+ writeBoolean(writer, value);
+ return;
+ case String:
+ switch (value.length) {
+ case 0:
+ stream.writeByte(Tags.TagEmpty);
+ return;
+ case 1:
+ stream.writeByte(Tags.TagUTF8Char);
+ stream.writeString(value);
+ return;
+ }
+ writer.writeStringWithRef(value);
+ return;
+ case Date:
+ writer.writeDateWithRef(value);
+ return;
+ case Map:
+ writer.writeMapWithRef(value);
+ return;
+ case ArrayBuffer:
+ case Uint8Array:
+ case BytesIO:
+ writer.writeBytesWithRef(value);
+ return;
+ case Int8Array:
+ case Int16Array:
+ case Int32Array:
+ case Uint16Array:
+ case Uint32Array:
+ writeIntListWithRef(writer, value);
+ return;
+ case Float32Array:
+ case Float64Array:
+ writeDoubleListWithRef(writer, value);
+ return;
+ default:
+ if (Array.isArray(value)) {
+ writer.writeListWithRef(value);
+ }
+ else {
+ var classname = getClassName(value);
+ if (classname === 'Object') {
+ writer.writeMapWithRef(value);
+ }
+ else {
+ writer.writeObjectWithRef(value);
+ }
+ }
+ break;
+ }
+ }
+
+ function writeNumber(writer, n) {
+ var stream = writer.stream;
+ n = n.valueOf();
+ if (n === (n | 0)) {
+ if (0 <= n && n <= 9) {
+ stream.writeByte(n + 0x30);
+ }
+ else {
+ stream.writeByte(Tags.TagInteger);
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagSemicolon);
+ }
+ }
+ else if (isNaN(n)) {
+ stream.writeByte(Tags.TagNaN);
+ }
+ else if (isFinite(n)) {
+ stream.writeByte(Tags.TagDouble);
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagSemicolon);
+ }
+ else {
+ stream.writeByte(Tags.TagInfinity);
+ stream.writeByte((n > 0) ? Tags.TagPos : Tags.TagNeg);
+ }
+ }
+
+ function writeInteger(writer, n) {
+ var stream = writer.stream;
+ if (0 <= n && n <= 9) {
+ stream.writeByte(n + 0x30);
+ }
+ else {
+ if (n < -2147483648 || n > 2147483647) {
+ stream.writeByte(Tags.TagLong);
+ }
+ else {
+ stream.writeByte(Tags.TagInteger);
+ }
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagSemicolon);
+ }
+ }
+
+ function writeDouble(writer, n) {
+ var stream = writer.stream;
+ if (isNaN(n)) {
+ stream.writeByte(Tags.TagNaN);
+ }
+ else if (isFinite(n)) {
+ stream.writeByte(Tags.TagDouble);
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagSemicolon);
+ }
+ else {
+ stream.writeByte(Tags.TagInfinity);
+ stream.writeByte((n > 0) ? Tags.TagPos : Tags.TagNeg);
+ }
+ }
+
+ function writeBoolean(writer, b) {
+ writer.stream.writeByte(b.valueOf() ? Tags.TagTrue : Tags.TagFalse);
+ }
+
+ function writeUTCDate(writer, date) {
+ writer._refer.set(date);
+ var stream = writer.stream;
+ var year = ('0000' + date.getUTCFullYear()).slice(-4);
+ var month = ('00' + (date.getUTCMonth() + 1)).slice(-2);
+ var day = ('00' + date.getUTCDate()).slice(-2);
+ var hour = ('00' + date.getUTCHours()).slice(-2);
+ var minute = ('00' + date.getUTCMinutes()).slice(-2);
+ var second = ('00' + date.getUTCSeconds()).slice(-2);
+ var millisecond = ('000' + date.getUTCMilliseconds()).slice(-3);
+ stream.writeByte(Tags.TagDate);
+ stream.writeAsciiString(year + month + day);
+ stream.writeByte(Tags.TagTime);
+ stream.writeAsciiString(hour + minute + second);
+ if (millisecond !== '000') {
+ stream.writeByte(Tags.TagPoint);
+ stream.writeAsciiString(millisecond);
+ }
+ stream.writeByte(Tags.TagUTC);
+ }
+
+ function writeDate(writer, date) {
+ writer._refer.set(date);
+ var stream = writer.stream;
+ var year = ('0000' + date.getFullYear()).slice(-4);
+ var month = ('00' + (date.getMonth() + 1)).slice(-2);
+ var day = ('00' + date.getDate()).slice(-2);
+ var hour = ('00' + date.getHours()).slice(-2);
+ var minute = ('00' + date.getMinutes()).slice(-2);
+ var second = ('00' + date.getSeconds()).slice(-2);
+ var millisecond = ('000' + date.getMilliseconds()).slice(-3);
+ if ((hour === '00') && (minute === '00') &&
+ (second === '00') && (millisecond === '000')) {
+ stream.writeByte(Tags.TagDate);
+ stream.writeAsciiString(year + month + day);
+ }
+ else if ((year === '1970') && (month === '01') && (day === '01')) {
+ stream.writeByte(Tags.TagTime);
+ stream.writeAsciiString(hour + minute + second);
+ if (millisecond !== '000') {
+ stream.writeByte(Tags.TagPoint);
+ stream.writeAsciiString(millisecond);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagDate);
+ stream.writeAsciiString(year + month + day);
+ stream.writeByte(Tags.TagTime);
+ stream.writeAsciiString(hour + minute + second);
+ if (millisecond !== '000') {
+ stream.writeByte(Tags.TagPoint);
+ stream.writeAsciiString(millisecond);
+ }
+ }
+ stream.writeByte(Tags.TagSemicolon);
+ }
+
+ function writeTime(writer, time) {
+ writer._refer.set(time);
+ var stream = writer.stream;
+ var hour = ('00' + time.getHours()).slice(-2);
+ var minute = ('00' + time.getMinutes()).slice(-2);
+ var second = ('00' + time.getSeconds()).slice(-2);
+ var millisecond = ('000' + time.getMilliseconds()).slice(-3);
+ stream.writeByte(Tags.TagTime);
+ stream.writeAsciiString(hour + minute + second);
+ if (millisecond !== '000') {
+ stream.writeByte(Tags.TagPoint);
+ stream.writeAsciiString(millisecond);
+ }
+ stream.writeByte(Tags.TagSemicolon);
+ }
+
+ function writeBytes(writer, bytes) {
+ writer._refer.set(bytes);
+ var stream = writer.stream;
+ stream.writeByte(Tags.TagBytes);
+ var n = bytes.byteLength || bytes.length;
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagQuote);
+ stream.write(bytes);
+ }
+ else {
+ stream.writeByte(Tags.TagQuote);
+ }
+ stream.writeByte(Tags.TagQuote);
+ }
+
+ function writeString(writer, str) {
+ writer._refer.set(str);
+ var stream = writer.stream;
+ var n = str.length;
+ stream.writeByte(Tags.TagString);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagQuote);
+ stream.writeString(str);
+ }
+ else {
+ stream.writeByte(Tags.TagQuote);
+ }
+ stream.writeByte(Tags.TagQuote);
+ }
+
+ function writeArray(writer, array, writeElem) {
+ writer._refer.set(array);
+ var stream = writer.stream;
+ var n = array.length;
+ stream.writeByte(Tags.TagList);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ writeElem(writer, array[i]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
+ }
+ stream.writeByte(Tags.TagClosebrace);
+ }
+
+ function writeIntListWithRef(writer, list) {
+ if (!writer._refer.write(list)) {
+ writeArray(writer, list, writeInteger);
+ }
+ }
+
+ function writeDoubleListWithRef(writer, list) {
+ if (!writer._refer.write(list)) {
+ writeArray(writer, list, writeDouble);
+ }
+ }
+
+ function writeMap(writer, map) {
+ writer._refer.set(map);
+ var stream = writer.stream;
+ var fields = [];
+ for (var key in map) {
+ if (map.hasOwnProperty(key) &&
+ typeof(map[key]) !== 'function') {
+ fields[fields.length] = key;
+ }
+ }
+ var n = fields.length;
+ stream.writeByte(Tags.TagMap);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ serialize(writer, fields[i]);
+ serialize(writer, map[fields[i]]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
+ }
+ stream.writeByte(Tags.TagClosebrace);
+ }
+
+ function writeHarmonyMap(writer, map) {
+ writer._refer.set(map);
+ var stream = writer.stream;
+ var n = map.size;
+ stream.writeByte(Tags.TagMap);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ map.forEach(function(value, key) {
+ serialize(writer, key);
+ serialize(writer, value);
+ });
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
+ }
+ stream.writeByte(Tags.TagClosebrace);
+ }
+
+ function writeObject(writer, obj) {
+ var stream = writer.stream;
+ var classname = getClassName(obj);
+ var fields, index;
+ if (classname in writer._classref) {
+ index = writer._classref[classname];
+ fields = writer._fieldsref[index];
+ }
+ else {
+ fields = [];
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key) &&
+ typeof(obj[key]) !== 'function') {
+ fields[fields.length] = key.toString();
+ }
+ }
+ index = writeClass(writer, classname, fields);
+ }
+ stream.writeByte(Tags.TagObject);
+ stream.writeAsciiString('' + index);
+ stream.writeByte(Tags.TagOpenbrace);
+ writer._refer.set(obj);
+ var n = fields.length;
+ for (var i = 0; i < n; i++) {
+ serialize(writer, obj[fields[i]]);
+ }
+ stream.writeByte(Tags.TagClosebrace);
+ }
+
+ function writeClass(writer, classname, fields) {
+ var stream = writer.stream;
+ var n = fields.length;
+ stream.writeByte(Tags.TagClass);
+ stream.writeAsciiString('' + classname.length);
+ stream.writeByte(Tags.TagQuote);
+ stream.writeString(classname);
+ stream.writeByte(Tags.TagQuote);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ writeString(writer, fields[i]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
+ }
+ stream.writeByte(Tags.TagClosebrace);
+ var index = writer._fieldsref.length;
+ writer._classref[classname] = index;
+ writer._fieldsref[index] = fields;
+ return index;
+ }
+
+ Object.defineProperties(Writer.prototype, {
+ serialize: { value: function(value) {
+ serialize(this, value);
+ } },
+ writeInteger: { value: function(value) {
+ writeInteger(this, value);
+ } },
+ writeDouble: { value: function(value) {
+ writeDouble(this, value);
+ } },
+ writeBoolean: { value: function(value) {
+ writeBoolean(this, value);
+ } },
+ writeUTCDate: { value: function(value) {
+ writeUTCDate(this, value);
+ } },
+ writeUTCDateWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeUTCDate(this, value);
+ }
+ } },
+ writeDate: { value: function(value) {
+ writeDate(this, value);
+ } },
+ writeDateWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeDate(this, value);
+ }
+ } },
+ writeTime: { value: function(value) {
+ writeTime(this, value);
+ } },
+ writeTimeWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeTime(this, value);
+ }
+ } },
+ writeBytes: { value: function(value) {
+ writeBytes(this, value);
+ } },
+ writeBytesWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeBytes(this, value);
+ }
+ } },
+ writeString: { value: function(value) {
+ writeString(this, value);
+ } },
+ writeStringWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeString(this, value);
+ }
+ } },
+ writeList: { value: function(value) {
+ writeArray(this, value, serialize);
+ } },
+ writeListWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeArray(this, value, serialize);
+ }
+ } },
+ writeMap: { value: function(value) {
+ if (value instanceof Map) {
+ writeHarmonyMap(this, value);
+ }
+ else {
+ writeMap(this, value);
+ }
+ } },
+ writeMapWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ if (value instanceof Map) {
+ writeHarmonyMap(this, value);
+ }
+ else {
+ writeMap(this, value);
+ }
+ }
+ } },
+ writeObject: { value: function(value) {
+ writeObject(this, value);
+ } },
+ writeObjectWithRef: { value: function(value) {
+ if (!this._refer.write(value)) {
+ writeObject(this, value);
+ }
+ } },
+ reset: { value: function() {
+ this._classref = Object.create(null);
+ this._fieldsref.length = 0;
+ this._refer.reset();
+ } }
+ });
+
+ hprose.Writer = Writer;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Reader.js *
+ * *
+ * hprose Reader for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Map = global.Map;
+ var BytesIO = hprose.BytesIO;
+ var Tags = hprose.Tags;
+ var ClassManager = hprose.ClassManager;
+
+ function unexpectedTag(tag, expectTags) {
+ if (tag && expectTags) {
+ var expectTagStr = '';
+ if (typeof(expectTags) === 'number') {
+ expectTagStr = String.fromCharCode(expectTags);
+ }
+ else {
+ expectTagStr = String.fromCharCode.apply(String, expectTags);
+ }
+ throw new Error('Tag "' + expectTagStr + '" expected, but "' + String.fromCharCode(tag) + '" found in stream');
+ }
+ else if (tag) {
+ throw new Error('Unexpected serialize tag "' + String.fromCharCode(tag) + '" in stream');
+ }
+ else {
+ throw new Error('No byte found in stream');
+ }
+ }
+
+ function readRaw(stream) {
+ var ostream = new BytesIO();
+ _readRaw(stream, ostream);
+ return ostream.bytes;
+ }
+
+ function _readRaw(stream, ostream) {
+ __readRaw(stream, ostream, stream.readByte());
+ }
+
+ function __readRaw(stream, ostream, tag) {
+ ostream.writeByte(tag);
+ switch (tag) {
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case Tags.TagNull:
+ case Tags.TagEmpty:
+ case Tags.TagTrue:
+ case Tags.TagFalse:
+ case Tags.TagNaN:
+ break;
+ case Tags.TagInfinity:
+ ostream.writeByte(stream.readByte());
+ break;
+ case Tags.TagInteger:
+ case Tags.TagLong:
+ case Tags.TagDouble:
+ case Tags.TagRef:
+ readNumberRaw(stream, ostream);
+ break;
+ case Tags.TagDate:
+ case Tags.TagTime:
+ readDateTimeRaw(stream, ostream);
+ break;
+ case Tags.TagUTF8Char:
+ readUTF8CharRaw(stream, ostream);
+ break;
+ case Tags.TagBytes:
+ readBytesRaw(stream, ostream);
+ break;
+ case Tags.TagString:
+ readStringRaw(stream, ostream);
+ break;
+ case Tags.TagGuid:
+ readGuidRaw(stream, ostream);
+ break;
+ case Tags.TagList:
+ case Tags.TagMap:
+ case Tags.TagObject:
+ readComplexRaw(stream, ostream);
+ break;
+ case Tags.TagClass:
+ readComplexRaw(stream, ostream);
+ _readRaw(stream, ostream);
+ break;
+ case Tags.TagError:
+ _readRaw(stream, ostream);
+ break;
+ default: unexpectedTag(tag);
+ }
+ }
+ function readNumberRaw(stream, ostream) {
+ var tag;
+ do {
+ tag = stream.readByte();
+ ostream.writeByte(tag);
+ } while (tag !== Tags.TagSemicolon);
+ }
+ function readDateTimeRaw(stream, ostream) {
+ var tag;
+ do {
+ tag = stream.readByte();
+ ostream.writeByte(tag);
+ } while (tag !== Tags.TagSemicolon &&
+ tag !== Tags.TagUTC);
+ }
+ function readUTF8CharRaw(stream, ostream) {
+ ostream.writeString(stream.readString(1));
+ }
+ function readBytesRaw(stream, ostream) {
+ var count = 0;
+ var tag = 48;
+ do {
+ count *= 10;
+ count += tag - 48;
+ tag = stream.readByte();
+ ostream.writeByte(tag);
+ } while (tag !== Tags.TagQuote);
+ ostream.write(stream.read(count + 1));
+ }
+ function readStringRaw(stream, ostream) {
+ var count = 0;
+ var tag = 48;
+ do {
+ count *= 10;
+ count += tag - 48;
+ tag = stream.readByte();
+ ostream.writeByte(tag);
+ } while (tag !== Tags.TagQuote);
+ ostream.write(stream.readStringAsBytes(count + 1));
+ }
+ function readGuidRaw(stream, ostream) {
+ ostream.write(stream.read(38));
+ }
+ function readComplexRaw(stream, ostream) {
+ var tag;
+ do {
+ tag = stream.readByte();
+ ostream.writeByte(tag);
+ } while (tag !== Tags.TagOpenbrace);
+ while ((tag = stream.readByte()) !== Tags.TagClosebrace) {
+ __readRaw(stream, ostream, tag);
+ }
+ ostream.writeByte(tag);
+ }
+
+ function RawReader(stream) {
+ Object.defineProperties(this, {
+ stream: { value : stream },
+ readRaw: { value: function() { return readRaw(stream); } }
+ });
+ }
+
+ hprose.RawReader = RawReader;
+
+ var fakeReaderRefer = Object.create(null, {
+ set: { value: function() {} },
+ read: { value: function() { unexpectedTag(Tags.TagRef); } },
+ reset: { value: function() {} }
+ });
+
+ function RealReaderRefer() {
+ Object.defineProperties(this, {
+ ref: { value: [] }
+ });
+ }
+
+ Object.defineProperties(RealReaderRefer.prototype, {
+ set: { value: function(val) { this.ref.push(val); } },
+ read: { value: function(index) { return this.ref[index]; } },
+ reset: { value: function() { this.ref.length = 0; } }
+ });
+
+ function realReaderRefer() {
+ return new RealReaderRefer();
+ }
+
+ function getter(str) {
+ var obj = global;
+ var names = str.split('.');
+ var i;
+ for (i = 0; i < names.length; i++) {
+ obj = obj[names[i]];
+ if (obj === undefined) {
+ return null;
+ }
+ }
+ return obj;
+ }
+ function findClass(cn, poslist, i, c) {
+ if (i < poslist.length) {
+ var pos = poslist[i];
+ cn[pos] = c;
+ var cls = findClass(cn, poslist, i + 1, '.');
+ if (i + 1 < poslist.length) {
+ if (cls === null) {
+ cls = findClass(cn, poslist, i + 1, '_');
+ }
+ }
+ return cls;
+ }
+ var classname = cn.join('');
+ try {
+ var cl = getter(classname);
+ return ((typeof(cl) === 'function') ? cl : null);
+ } catch (e) {
+ return null;
+ }
+ }
+
+ function getClass(classname) {
+ var cls = ClassManager.getClass(classname);
+ if (cls) { return cls; }
+ cls = getter(classname);
+ if (typeof(cls) === 'function') {
+ ClassManager.register(cls, classname);
+ return cls;
+ }
+ var poslist = [];
+ var pos = classname.indexOf('_');
+ while (pos >= 0) {
+ poslist[poslist.length] = pos;
+ pos = classname.indexOf('_', pos + 1);
+ }
+ if (poslist.length > 0) {
+ var cn = classname.split('');
+ cls = findClass(cn, poslist, 0, '.');
+ if (cls === null) {
+ cls = findClass(cn, poslist, 0, '_');
+ }
+ if (typeof(cls) === 'function') {
+ ClassManager.register(cls, classname);
+ return cls;
+ }
+ }
+ cls = function () {};
+ Object.defineProperty(cls.prototype, 'getClassName', { value: function () {
+ return classname;
+ }});
+ ClassManager.register(cls, classname);
+ return cls;
+ }
+
+
+ function readInt(stream, tag) {
+ var s = stream.readUntil(tag);
+ if (s.length === 0) { return 0; }
+ return parseInt(s, 10);
+ }
+ function unserialize(reader) {
+ var stream = reader.stream;
+ var tag = stream.readByte();
+ switch (tag) {
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57: return tag - 48;
+ case Tags.TagInteger: return readIntegerWithoutTag(stream);
+ case Tags.TagLong: return readLongWithoutTag(stream);
+ case Tags.TagDouble: return readDoubleWithoutTag(stream);
+ case Tags.TagNull: return null;
+ case Tags.TagEmpty: return '';
+ case Tags.TagTrue: return true;
+ case Tags.TagFalse: return false;
+ case Tags.TagNaN: return NaN;
+ case Tags.TagInfinity: return readInfinityWithoutTag(stream);
+ case Tags.TagDate: return readDateWithoutTag(reader);
+ case Tags.TagTime: return readTimeWithoutTag(reader);
+ case Tags.TagBytes: return readBytesWithoutTag(reader);
+ case Tags.TagUTF8Char: return readUTF8CharWithoutTag(reader);
+ case Tags.TagString: return readStringWithoutTag(reader);
+ case Tags.TagGuid: return readGuidWithoutTag(reader);
+ case Tags.TagList: return readListWithoutTag(reader);
+ case Tags.TagMap: return reader.useHarmonyMap ? readHarmonyMapWithoutTag(reader) : readMapWithoutTag(reader);
+ case Tags.TagClass: readClass(reader); return readObject(reader);
+ case Tags.TagObject: return readObjectWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ case Tags.TagError: throw new Error(readString(reader));
+ default: unexpectedTag(tag);
+ }
+ }
+ function readIntegerWithoutTag(stream) {
+ return readInt(stream, Tags.TagSemicolon);
+ }
+ function readInteger(stream) {
+ var tag = stream.readByte();
+ switch (tag) {
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57: return tag - 48;
+ case Tags.TagInteger: return readIntegerWithoutTag(stream);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readLongWithoutTag(stream) {
+ var s = stream.readUntil(Tags.TagSemicolon);
+ var l = parseInt(s, 10);
+ if (l.toString() === s) { return l; }
+ return s;
+ }
+ function readLong(stream) {
+ var tag = stream.readByte();
+ switch (tag) {
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57: return tag - 48;
+ case Tags.TagInteger:
+ case Tags.TagLong: return readLongWithoutTag(stream);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readDoubleWithoutTag(stream) {
+ return parseFloat(stream.readUntil(Tags.TagSemicolon));
+ }
+ function readDouble(stream) {
+ var tag = stream.readByte();
+ switch (tag) {
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57: return tag - 48;
+ case Tags.TagInteger:
+ case Tags.TagLong:
+ case Tags.TagDouble: return readDoubleWithoutTag(stream);
+ case Tags.TagNaN: return NaN;
+ case Tags.TagInfinity: return readInfinityWithoutTag(stream);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readInfinityWithoutTag(stream) {
+ return ((stream.readByte() === Tags.TagNeg) ? -Infinity : Infinity);
+ }
+ function readBoolean(stream) {
+ var tag = stream.readByte();
+ switch (tag) {
+ case Tags.TagTrue: return true;
+ case Tags.TagFalse: return false;
+ default: unexpectedTag(tag);
+ }
+ }
+ function readDateWithoutTag(reader) {
+ var stream = reader.stream;
+ var year = parseInt(stream.readAsciiString(4), 10);
+ var month = parseInt(stream.readAsciiString(2), 10) - 1;
+ var day = parseInt(stream.readAsciiString(2), 10);
+ var date;
+ var tag = stream.readByte();
+ if (tag === Tags.TagTime) {
+ var hour = parseInt(stream.readAsciiString(2), 10);
+ var minute = parseInt(stream.readAsciiString(2), 10);
+ var second = parseInt(stream.readAsciiString(2), 10);
+ var millisecond = 0;
+ tag = stream.readByte();
+ if (tag === Tags.TagPoint) {
+ millisecond = parseInt(stream.readAsciiString(3), 10);
+ tag = stream.readByte();
+ if ((tag >= 48) && (tag <= 57)) {
+ stream.skip(2);
+ tag = stream.readByte();
+ if ((tag >= 48) && (tag <= 57)) {
+ stream.skip(2);
+ tag = stream.readByte();
+ }
+ }
+ }
+ if (tag === Tags.TagUTC) {
+ date = new Date(Date.UTC(year, month, day, hour, minute, second, millisecond));
+ }
+ else {
+ date = new Date(year, month, day, hour, minute, second, millisecond);
+ }
+ }
+ else if (tag === Tags.TagUTC) {
+ date = new Date(Date.UTC(year, month, day));
+ }
+ else {
+ date = new Date(year, month, day);
+ }
+ reader.refer.set(date);
+ return date;
+ }
+ function readDate(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagDate: return readDateWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readTimeWithoutTag(reader) {
+ var stream = reader.stream;
+ var time;
+ var hour = parseInt(stream.readAsciiString(2), 10);
+ var minute = parseInt(stream.readAsciiString(2), 10);
+ var second = parseInt(stream.readAsciiString(2), 10);
+ var millisecond = 0;
+ var tag = stream.readByte();
+ if (tag === Tags.TagPoint) {
+ millisecond = parseInt(stream.readAsciiString(3), 10);
+ tag = stream.readByte();
+ if ((tag >= 48) && (tag <= 57)) {
+ stream.skip(2);
+ tag = stream.readByte();
+ if ((tag >= 48) && (tag <= 57)) {
+ stream.skip(2);
+ tag = stream.readByte();
+ }
+ }
+ }
+ if (tag === Tags.TagUTC) {
+ time = new Date(Date.UTC(1970, 0, 1, hour, minute, second, millisecond));
+ }
+ else {
+ time = new Date(1970, 0, 1, hour, minute, second, millisecond);
+ }
+ reader.refer.set(time);
+ return time;
+ }
+ function readTime(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagTime: return readTimeWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readBytesWithoutTag(reader) {
+ var stream = reader.stream;
+ var count = readInt(stream, Tags.TagQuote);
+ var bytes = stream.read(count);
+ stream.skip(1);
+ reader.refer.set(bytes);
+ return bytes;
+ }
+ function readBytes(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagEmpty: return new Uint8Array(0);
+ case Tags.TagBytes: return readBytesWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readUTF8CharWithoutTag(reader) {
+ return reader.stream.readString(1);
+ }
+ function _readString(reader) {
+ var stream = reader.stream;
+ var s = stream.readString(readInt(stream, Tags.TagQuote));
+ stream.skip(1);
+ return s;
+ }
+ function readStringWithoutTag(reader) {
+ var s = _readString(reader);
+ reader.refer.set(s);
+ return s;
+ }
+ function readString(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagEmpty: return '';
+ case Tags.TagUTF8Char: return readUTF8CharWithoutTag(reader);
+ case Tags.TagString: return readStringWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readGuidWithoutTag(reader) {
+ var stream = reader.stream;
+ stream.skip(1);
+ var s = stream.readAsciiString(36);
+ stream.skip(1);
+ reader.refer.set(s);
+ return s;
+ }
+ function readGuid(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagGuid: return readGuidWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readListWithoutTag(reader) {
+ var stream = reader.stream;
+ var list = [];
+ reader.refer.set(list);
+ var count = readInt(stream, Tags.TagOpenbrace);
+ for (var i = 0; i < count; i++) {
+ list[i] = unserialize(reader);
+ }
+ stream.skip(1);
+ return list;
+ }
+ function readList(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagList: return readListWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readMapWithoutTag(reader) {
+ var stream = reader.stream;
+ var map = {};
+ reader.refer.set(map);
+ var count = readInt(stream, Tags.TagOpenbrace);
+ for (var i = 0; i < count; i++) {
+ var key = unserialize(reader);
+ var value = unserialize(reader);
+ map[key] = value;
+ }
+ stream.skip(1);
+ return map;
+ }
+ function readMap(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagMap: return readMapWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readHarmonyMapWithoutTag(reader) {
+ var stream = reader.stream;
+ var map = new Map();
+ reader.refer.set(map);
+ var count = readInt(stream, Tags.TagOpenbrace);
+ for (var i = 0; i < count; i++) {
+ var key = unserialize(reader);
+ var value = unserialize(reader);
+ map.set(key, value);
+ }
+ stream.skip(1);
+ return map;
+ }
+ function readHarmonyMap(reader) {
+ var tag = reader.stream.readByte();
+ switch (tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagMap: return readHarmonyMapWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readObjectWithoutTag(reader) {
+ var stream = reader.stream;
+ var cls = reader.classref[readInt(stream, Tags.TagOpenbrace)];
+ var obj = new cls.classname();
+ reader.refer.set(obj);
+ for (var i = 0; i < cls.count; i++) {
+ obj[cls.fields[i]] = unserialize(reader);
+ }
+ stream.skip(1);
+ return obj;
+ }
+ function readObject(reader) {
+ var tag = reader.stream.readByte();
+ switch(tag) {
+ case Tags.TagNull: return null;
+ case Tags.TagClass: readClass(reader); return readObject(reader);
+ case Tags.TagObject: return readObjectWithoutTag(reader);
+ case Tags.TagRef: return readRef(reader);
+ default: unexpectedTag(tag);
+ }
+ }
+ function readClass(reader) {
+ var stream = reader.stream;
+ var classname = _readString(reader);
+ var count = readInt(stream, Tags.TagOpenbrace);
+ var fields = [];
+ for (var i = 0; i < count; i++) {
+ fields[i] = readString(reader);
+ }
+ stream.skip(1);
+ classname = getClass(classname);
+ reader.classref.push({
+ classname: classname,
+ count: count,
+ fields: fields
+ });
+ }
+ function readRef(reader) {
+ return reader.refer.read(readInt(reader.stream, Tags.TagSemicolon));
+ }
+
+ function Reader(stream, simple, useHarmonyMap) {
+ RawReader.call(this, stream);
+ this.useHarmonyMap = !!useHarmonyMap;
+ Object.defineProperties(this, {
+ classref: { value: [] },
+ refer: { value: simple ? fakeReaderRefer : realReaderRefer() }
+ });
+ }
+
+ Reader.prototype = Object.create(RawReader.prototype);
+ Reader.prototype.constructor = Reader;
+
+ Object.defineProperties(Reader.prototype, {
+ useHarmonyMap: { value: false, writable: true },
+ checkTag: { value: function(expectTag, tag) {
+ if (tag === undefined) { tag = this.stream.readByte(); }
+ if (tag !== expectTag) { unexpectedTag(tag, expectTag); }
+ } },
+ checkTags: { value: function(expectTags, tag) {
+ if (tag === undefined) { tag = this.stream.readByte(); }
+ if (expectTags.indexOf(tag) >= 0) { return tag; }
+ unexpectedTag(tag, expectTags);
+ } },
+ unserialize: { value: function() {
+ return unserialize(this);
+ } },
+ readInteger: { value: function() {
+ return readInteger(this.stream);
+ } },
+ readLong: { value: function() {
+ return readLong(this.stream);
+ } },
+ readDouble: { value: function() {
+ return readDouble(this.stream);
+ } },
+ readBoolean: { value: function() {
+ return readBoolean(this.stream);
+ } },
+ readDateWithoutTag: { value: function() {
+ return readDateWithoutTag(this);
+ } },
+ readDate: { value: function() {
+ return readDate(this);
+ } },
+ readTimeWithoutTag: { value: function() {
+ return readTimeWithoutTag(this);
+ } },
+ readTime: { value: function() {
+ return readTime(this);
+ } },
+ readBytesWithoutTag: { value: function() {
+ return readBytesWithoutTag(this);
+ } },
+ readBytes: { value: function() {
+ return readBytes(this);
+ } },
+ readStringWithoutTag: { value: function() {
+ return readStringWithoutTag(this);
+ } },
+ readString: { value: function() {
+ return readString(this);
+ } },
+ readGuidWithoutTag: { value: function() {
+ return readGuidWithoutTag(this);
+ } },
+ readGuid: { value: function() {
+ return readGuid(this);
+ } },
+ readListWithoutTag: { value: function() {
+ return readListWithoutTag(this);
+ } },
+ readList: { value: function() {
+ return readList(this);
+ } },
+ readMapWithoutTag: { value: function() {
+ return this.useHarmonyMap ?
+ readHarmonyMapWithoutTag(this) :
+ readMapWithoutTag(this);
+ } },
+ readMap: { value: function() {
+ return this.useHarmonyMap ?
+ readHarmonyMap(this) :
+ readMap(this);
+ } },
+ readObjectWithoutTag: { value: function() {
+ return readObjectWithoutTag(this);
+ } },
+ readObject: { value: function() {
+ return readObject(this);
+ } },
+ reset: { value: function() {
+ this.classref.length = 0;
+ this.refer.reset();
+ } }
+ });
+
+ hprose.Reader = Reader;
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Formatter.js *
+ * *
+ * hprose Formatter for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose) {
+ 'use strict';
+
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
+
+ function serialize(value, simple) {
+ var stream = new BytesIO();
+ var writer = new Writer(stream, simple);
+ writer.serialize(value);
+ return stream;
+ }
+
+ function unserialize(stream, simple, useHarmonyMap) {
+ if (!(stream instanceof BytesIO)) {
+ stream = new BytesIO(stream);
+ }
+ return new Reader(stream, simple, useHarmonyMap).unserialize();
+ }
+
+ hprose.Formatter = {
+ serialize: function (value, simple) {
+ return serialize(value, simple).bytes;
+ },
+ unserialize: unserialize
+ };
+
+ hprose.serialize = serialize;
+
+ hprose.unserialize = unserialize;
+
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * ResultMode.js *
+ * *
+ * hprose ResultMode for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose) {
+ 'use strict';
+
+ hprose.ResultMode = {
+ Normal: 0,
+ Serialized: 1,
+ Raw: 2,
+ RawWithEndTag: 3
+ };
+ hprose.Normal = hprose.ResultMode.Normal;
+ hprose.Serialized = hprose.ResultMode.Serialized;
+ hprose.Raw = hprose.ResultMode.Raw;
+ hprose.RawWithEndTag = hprose.ResultMode.RawWithEndTag;
+
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * Client.js *
+ * *
+ * hprose client for HTML5. *
+ * *
+ * LastModified: Apr 24, 2018 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+/* global Proxy */
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var setImmediate = global.setImmediate;
+ var Tags = hprose.Tags;
+ var ResultMode = hprose.ResultMode;
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
+ var Future = hprose.Future;
+ var parseuri = hprose.parseuri;
+ var isObjectEmpty = hprose.isObjectEmpty;
+
+ var GETFUNCTIONS = new Uint8Array(1);
+ GETFUNCTIONS[0] = Tags.TagEnd;
+
+ function noop(){}
+
+ var s_boolean = 'boolean';
+ var s_string = 'string';
+ var s_number = 'number';
+ var s_function = 'function';
+ var s_object = 'object';
+
+ function HproseProxy(setFunction, ns) {
+ var settings = {};
+ this.get = function(target, prop/*, receiver*/) {
+ var name = prop.toString();
+ if (ns) { name = ns + '_' + name; }
+ if (name === 'then') { return undefined; }
+ if (!target.hasOwnProperty(name)) {
+ settings[name] = {};
+ var handler = new HproseProxy(setFunction, name);
+ var func = setFunction(settings, name);
+ handler.apply = function(target, thisArg, argumentsList) {
+ return func.apply(null, argumentsList);
+ }
+ handler.set = function(target, prop, value/*, receiver*/) {
+ settings[name][prop] = value;
+ return true;
+ };
+ target[name] = new Proxy(function() {}, handler);
+ }
+ return target[name];
+ };
+ }
+
+ function Client(uri, functions, settings) {
+
+ // private members
+ var _uri,
+ _uriList = [],
+ _index = -1,
+ _byref = false,
+ _simple = false,
+ _timeout = 30000,
+ _retry = 10,
+ _idempotent = false,
+ _failswitch = false,
+ _failround = 0,
+ _lock = false,
+ _tasks = [],
+ _useHarmonyMap = false,
+ _onerror = noop,
+ _onfailswitch = noop,
+ _filters = [],
+ _batch = false,
+ _batches = [],
+ _ready = new Future(),
+ _topics = Object.create(null),
+ _id = null,
+ _keepAlive = true,
+ _invokeHandler = invokeHandler,
+ _batchInvokeHandler = batchInvokeHandler,
+ _beforeFilterHandler = beforeFilterHandler,
+ _afterFilterHandler = afterFilterHandler,
+ _invokeHandlers = [],
+ _batchInvokeHandlers = [],
+ _beforeFilterHandlers = [],
+ _afterFilterHandlers = [],
+
+ self = this;
+
+ function outputFilter(request, context) {
+ for (var i = 0, n = _filters.length; i < n; i++) {
+ request = _filters[i].outputFilter(request, context);
+ }
+ return request;
+ }
+
+ function inputFilter(response, context) {
+ for (var i = _filters.length - 1; i >= 0; i--) {
+ response = _filters[i].inputFilter(response, context);
+ }
+ return response;
+ }
+
+ function beforeFilterHandler(request, context) {
+ request = outputFilter(request, context);
+ return _afterFilterHandler(request, context)
+ .then(function(response) {
+ if (context.oneway) { return; }
+ return inputFilter(response, context);
+ });
+ }
+
+ function afterFilterHandler(request, context) {
+ return self.sendAndReceive(request, context).catchError(function(e) {
+ var response = retry(request, context);
+ if (response !== null) {
+ return response;
+ }
+ throw e;
+ });
+ }
+
+ function sendAndReceive(request, context, onsuccess, onerror) {
+ _beforeFilterHandler(request, context).then(onsuccess, onerror);
+ }
+
+ function failswitch() {
+ var n = _uriList.length;
+ if (n > 1) {
+ var i = _index + 1;
+ if (i >= n) {
+ i = 0;
+ _failround++;
+ }
+ _index = i;
+ _uri = _uriList[_index];
+ }
+ else {
+ _failround++;
+ }
+ _onfailswitch(self);
+ }
+
+ function retry(data, context) {
+ if (context.failswitch) {
+ failswitch();
+ }
+ if (context.idempotent && (context.retried < context.retry)) {
+ var interval = ++context.retried * 500;
+ if (context.failswitch) {
+ interval -= (_uriList.length - 1) * 500;
+ }
+ if (interval > 5000) {
+ interval = 5000;
+ }
+ if (interval > 0) {
+ return Future.delayed(interval, function() {
+ return afterFilterHandler(data, context);
+ });
+ }
+ else {
+ return afterFilterHandler(data, context);
+ }
+ }
+ return null;
+ }
+
+ function normalizeFunctions(functions) {
+ var root = [Object.create(null)];
+ for (var i in functions) {
+ var func = functions[i].split('_');
+ var n = func.length - 1;
+ if (n > 0) {
+ var node = root;
+ for (var j = 0; j < n; j++) {
+ var f = func[j];
+ if (node[0][f] === undefined) {
+ node[0][f] = [Object.create(null)];
+ }
+ node = node[0][f];
+ }
+ node.push(func[n]);
+ }
+ root.push(functions[i]);
+ }
+ return root;
+ }
+
+ function initService(stub) {
+ var context = {
+ retry: _retry,
+ retried: 0,
+ idempotent: true,
+ failswitch: true,
+ timeout: _timeout,
+ client: self,
+ userdata: {}
+ };
+ var onsuccess = function(data) {
+ var error = null;
+ try {
+ var stream = new BytesIO(data);
+ var reader = new Reader(stream, true);
+ var tag = stream.readByte();
+ switch (tag) {
+ case Tags.TagError:
+ error = new Error(reader.readString());
+ break;
+ case Tags.TagFunctions:
+ var functions = normalizeFunctions(reader.readList());
+ reader.checkTag(Tags.TagEnd);
+ setFunctions(stub, functions);
+ break;
+ default:
+ error = new Error('Wrong Response:\r\n' + BytesIO.toString(data));
+ break;
+ }
+ }
+ catch (e) {
+ error = e;
+ }
+ if (error !== null) {
+ _ready.reject(error);
+ }
+ else {
+ _ready.resolve(stub);
+ }
+ };
+ sendAndReceive(GETFUNCTIONS, context, onsuccess, _ready.reject);
+ }
+
+ function setFunction(stub, name) {
+ return function() {
+ if (_batch) {
+ return _invoke(stub, name, Array.slice(arguments), true);
+ }
+ else {
+ return Future.all(arguments).then(function(args) {
+ return _invoke(stub, name, args, false);
+ });
+ }
+ };
+ }
+
+ function setMethods(stub, obj, namespace, name, methods) {
+ if (obj[name] !== undefined) { return; }
+ obj[name] = {};
+ if (typeof(methods) === s_string || methods.constructor === Object) {
+ methods = [methods];
+ }
+ if (Array.isArray(methods)) {
+ for (var i = 0; i < methods.length; i++) {
+ var m = methods[i];
+ if (typeof(m) === s_string) {
+ obj[name][m] = setFunction(stub, namespace + name + '_' + m);
+ }
+ else {
+ for (var n in m) {
+ setMethods(stub, obj[name], namespace + name + '_', n, m[n]);
+ }
+ }
+ }
+ }
+ }
+
+ function setFunctions(stub, functions) {
+ for (var i = 0; i < functions.length; i++) {
+ var f = functions[i];
+ if (typeof(f) === s_string) {
+ if (stub[f] === undefined) {
+ stub[f] = setFunction(stub, f);
+ }
+ }
+ else {
+ for (var name in f) {
+ setMethods(stub, stub, '', name, f[name]);
+ }
+ }
+ }
+ }
+
+ function copyargs(src, dest) {
+ var n = Math.min(src.length, dest.length);
+ for (var i = 0; i < n; ++i) { dest[i] = src[i]; }
+ }
+
+ function initContext(batch) {
+ if (batch) {
+ return {
+ mode: ResultMode.Normal,
+ byref: _byref,
+ simple: _simple,
+ onsuccess: undefined,
+ onerror: undefined,
+ useHarmonyMap: _useHarmonyMap,
+ client: self,
+ userdata: {}
+ };
+ }
+ return {
+ mode: ResultMode.Normal,
+ byref: _byref,
+ simple: _simple,
+ timeout: _timeout,
+ retry: _retry,
+ retried: 0,
+ idempotent: _idempotent,
+ failswitch: _failswitch,
+ oneway: false,
+ sync: false,
+ onsuccess: undefined,
+ onerror: undefined,
+ useHarmonyMap: _useHarmonyMap,
+ client: self,
+ userdata: {}
+ };
+ }
+
+ function getContext(stub, name, args, batch) {
+ var context = initContext(batch);
+ if (name in stub) {
+ var method = stub[name];
+ for (var key in method) {
+ if (key in context) {
+ context[key] = method[key];
+ }
+ }
+ }
+ var i = 0, n = args.length;
+ for (; i < n; ++i) {
+ if (typeof args[i] === s_function) { break; }
+ }
+ if (i === n) { return context; }
+ var extra = args.splice(i, n - i);
+ context.onsuccess = extra[0];
+ n = extra.length;
+ for (i = 1; i < n; ++i) {
+ var arg = extra[i];
+ switch (typeof arg) {
+ case s_function:
+ context.onerror = arg; break;
+ case s_boolean:
+ context.byref = arg; break;
+ case s_number:
+ context.mode = arg; break;
+ case s_object:
+ for (var k in arg) {
+ if (k in context) {
+ context[k] = arg[k];
+ }
+ }
+ break;
+ }
+ }
+ return context;
+ }
+
+ function encode(name, args, context) {
+ var stream = new BytesIO();
+ stream.writeByte(Tags.TagCall);
+ var writer = new Writer(stream, context.simple);
+ writer.writeString(name);
+ if (args.length > 0 || context.byref) {
+ writer.reset();
+ writer.writeList(args);
+ if (context.byref) {
+ writer.writeBoolean(true);
+ }
+ }
+ return stream;
+ }
+
+ function __invoke(name, args, context, batch) {
+ if (_lock) {
+ return Future.promise(function(resolve, reject) {
+ _tasks.push({
+ batch: batch,
+ name: name,
+ args: args,
+ context: context,
+ resolve: resolve,
+ reject: reject
+ });
+ });
+ }
+ if (batch) {
+ return multicall(name, args, context);
+ }
+ return call(name, args, context);
+ }
+
+ function _invoke(stub, name, args, batch) {
+ return __invoke(name, args, getContext(stub, name, args, batch), batch);
+ }
+
+ function errorHandling(name, error, context, reject) {
+ try {
+ if (context.onerror) {
+ context.onerror(name, error);
+ }
+ else {
+ _onerror(name, error);
+ }
+ reject(error);
+ }
+ catch (e) {
+ reject(e);
+ }
+ }
+
+ function invokeHandler(name, args, context) {
+ var request = encode(name, args, context);
+ request.writeByte(Tags.TagEnd);
+ return Future.promise(function(resolve, reject) {
+ sendAndReceive(request.bytes, context, function(response) {
+ if (context.oneway) {
+ resolve();
+ return;
+ }
+ var result = null;
+ var error = null;
+ try {
+ if (context.mode === ResultMode.RawWithEndTag) {
+ result = response;
+ }
+ else if (context.mode === ResultMode.Raw) {
+ result = response.subarray(0, response.byteLength - 1);
+ }
+ else {
+ var stream = new BytesIO(response);
+ var reader = new Reader(stream, false, context.useHarmonyMap);
+ var tag = stream.readByte();
+ if (tag === Tags.TagResult) {
+ if (context.mode === ResultMode.Serialized) {
+ result = reader.readRaw();
+ }
+ else {
+ result = reader.unserialize();
+ }
+ tag = stream.readByte();
+ if (tag === Tags.TagArgument) {
+ reader.reset();
+ var _args = reader.readList();
+ copyargs(_args, args);
+ tag = stream.readByte();
+ }
+ }
+ else if (tag === Tags.TagError) {
+ error = new Error(reader.readString());
+ tag = stream.readByte();
+ }
+ if (tag !== Tags.TagEnd) {
+ error = new Error('Wrong Response:\r\n' + BytesIO.toString(response));
+ }
+ }
+ }
+ catch (e) {
+ error = e;
+ }
+ if (error) {
+ reject(error);
+ }
+ else {
+ resolve(result);
+ }
+ }, reject);
+ });
+ }
+
+ function unlock(sync) {
+ return function() {
+ if (sync) {
+ _lock = false;
+ setImmediate(function(tasks) {
+ tasks.forEach(function(task) {
+ if ('settings' in task) {
+ endBatch(task.settings)
+ .then(task.resolve, task.reject);
+ }
+ else {
+ __invoke(task.name, task.args, task.context, task.batch).then(task.resolve, task.reject);
+ }
+ });
+ }, _tasks);
+ _tasks = [];
+ }
+ };
+ }
+
+ function call(name, args, context) {
+ if (context.sync) { _lock = true; }
+ var promise = Future.promise(function(resolve, reject) {
+ _invokeHandler(name, args, context).then(function(result) {
+ try {
+ if (context.onsuccess) {
+ try {
+ context.onsuccess(result, args);
+ }
+ catch (e) {
+ if (context.onerror) {
+ context.onerror(name, e);
+ }
+ reject(e);
+ }
+ }
+ resolve(result);
+ }
+ catch (e) {
+ reject(e);
+ }
+ }, function(error) {
+ errorHandling(name, error, context, reject);
+ });
+ });
+ promise.whenComplete(unlock(context.sync));
+ return promise;
+ }
+
+ function multicall(name, args, context) {
+ return Future.promise(function(resolve, reject) {
+ _batches.push({
+ args: args,
+ name: name,
+ context: context,
+ resolve: resolve,
+ reject: reject
+ });
+ });
+ }
+
+ function getBatchContext(settings) {
+ var context = {
+ timeout: _timeout,
+ retry: _retry,
+ retried: 0,
+ idempotent: _idempotent,
+ failswitch: _failswitch,
+ oneway: false,
+ sync: false,
+ client: self,
+ userdata: {}
+ };
+ for (var k in settings) {
+ if (k in context) {
+ context[k] = settings[k];
+ }
+ }
+ return context;
+ }
+
+ function batchInvokeHandler(batches, context) {
+ var request = batches.reduce(function(stream, item) {
+ stream.write(encode(item.name, item.args, item.context));
+ return stream;
+ }, new BytesIO());
+ request.writeByte(Tags.TagEnd);
+ return Future.promise(function(resolve, reject) {
+ sendAndReceive(request.bytes, context, function(response) {
+ if (context.oneway) {
+ resolve(batches);
+ return;
+ }
+ var i = -1;
+ var stream = new BytesIO(response);
+ var reader = new Reader(stream, false);
+ var tag = stream.readByte();
+ try {
+ while (tag !== Tags.TagEnd) {
+ var result = null;
+ var error = null;
+ var mode = batches[++i].context.mode;
+ if (mode >= ResultMode.Raw) {
+ result = new BytesIO();
+ }
+ if (tag === Tags.TagResult) {
+ if (mode === ResultMode.Serialized) {
+ result = reader.readRaw();
+ }
+ else if (mode >= ResultMode.Raw) {
+ result.writeByte(Tags.TagResult);
+ result.write(reader.readRaw());
+ }
+ else {
+ reader.useHarmonyMap = batches[i].context.useHarmonyMap;
+ reader.reset();
+ result = reader.unserialize();
+ }
+ tag = stream.readByte();
+ if (tag === Tags.TagArgument) {
+ if (mode >= ResultMode.Raw) {
+ result.writeByte(Tags.TagArgument);
+ result.write(reader.readRaw());
+ }
+ else {
+ reader.reset();
+ var _args = reader.readList();
+ copyargs(_args, batches[i].args);
+ }
+ tag = stream.readByte();
+ }
+ }
+ else if (tag === Tags.TagError) {
+ if (mode >= ResultMode.Raw) {
+ result.writeByte(Tags.TagError);
+ result.write(reader.readRaw());
+ }
+ else {
+ reader.reset();
+ error = new Error(reader.readString());
+ }
+ tag = stream.readByte();
+ }
+ if ([Tags.TagEnd,
+ Tags.TagResult,
+ Tags.TagError].indexOf(tag) < 0) {
+ reject(new Error('Wrong Response:\r\n' + BytesIO.toString(response)));
+ return;
+ }
+ if (mode >= ResultMode.Raw) {
+ if (mode === ResultMode.RawWithEndTag) {
+ result.writeByte(Tags.TagEnd);
+ }
+ batches[i].result = result.bytes;
+ }
+ else {
+ batches[i].result = result;
+ }
+ batches[i].error = error;
+ }
+ }
+ catch (e) {
+ reject(e);
+ return;
+ }
+ resolve(batches);
+ }, reject);
+ });
+ }
+
+ function beginBatch() {
+ _batch = true;
+ }
+
+ function endBatch(settings) {
+ settings = settings || {};
+ _batch = false;
+ if (_lock) {
+ return Future.promise(function(resolve, reject) {
+ _tasks.push({
+ batch: true,
+ settings: settings,
+ resolve: resolve,
+ reject: reject
+ });
+ });
+ }
+ var batchSize = _batches.length;
+ if (batchSize === 0) { return Future.value([]); }
+ var context = getBatchContext(settings);
+ if (context.sync) { _lock = true; }
+ var batches = _batches;
+ _batches = [];
+ var promise = Future.promise(function(resolve, reject) {
+ _batchInvokeHandler(batches, context).then(function(batches) {
+ batches.forEach(function(i) {
+ if (i.error) {
+ errorHandling(i.name, i.error, i.context, i.reject);
+ }
+ else {
+ try {
+ if (i.context.onsuccess) {
+ try {
+ i.context.onsuccess(i.result, i.args);
+ }
+ catch (e) {
+ if (i.context.onerror) {
+ i.context.onerror(i.name, e);
+ }
+ i.reject(e);
+ }
+ }
+ i.resolve(i.result);
+ }
+ catch (e) {
+ i.reject(e);
+ }
+ }
+ delete i.context;
+ delete i.resolve;
+ delete i.reject;
+ });
+ resolve(batches);
+ }, function(error) {
+ batches.forEach(function(i) {
+ if ('reject' in i) {
+ errorHandling(i.name, error, i.context, i.reject);
+ }
+ });
+ reject(error);
+ });
+ });
+ promise.whenComplete(unlock(context.sync));
+ return promise;
+ }
+
+ function getOnError() {
+ return _onerror;
+ }
+ function setOnError(value) {
+ if (typeof(value) === s_function) {
+ _onerror = value;
+ }
+ }
+ function getOnFailswitch() {
+ return _onfailswitch;
+ }
+ function setOnFailswitch(value) {
+ if (typeof(value) === s_function) {
+ _onfailswitch = value;
+ }
+ }
+ function getUri() {
+ return _uri;
+ }
+ function getUriList() {
+ return _uriList;
+ }
+ function setUriList(uriList) {
+ if (typeof(uriList) === s_string) {
+ _uriList = [uriList];
+ }
+ else if (Array.isArray(uriList)) {
+ _uriList = uriList.slice(0);
+ _uriList.sort(function() { return Math.random() - 0.5; });
+ }
+ else {
+ return;
+ }
+ _index = 0;
+ _uri = _uriList[_index];
+ }
+ function getFailswitch() {
+ return _failswitch;
+ }
+ function setFailswitch(value) {
+ _failswitch = !!value;
+ }
+ function getFailround() {
+ return _failround;
+ }
+ function getTimeout() {
+ return _timeout;
+ }
+ function setTimeout(value) {
+ if (typeof(value) === 'number') {
+ _timeout = value | 0;
+ }
+ else {
+ _timeout = 0;
+ }
+ }
+ function getRetry() {
+ return _retry;
+ }
+ function setRetry(value) {
+ if (typeof(value) === 'number') {
+ _retry = value | 0;
+ }
+ else {
+ _retry = 0;
+ }
+ }
+ function getIdempotent() {
+ return _idempotent;
+ }
+ function setIdempotent(value) {
+ _idempotent = !!value;
+ }
+ function setKeepAlive(value) {
+ _keepAlive = !!value;
+ }
+ function getKeepAlive() {
+ return _keepAlive;
+ }
+ function getByRef() {
+ return _byref;
+ }
+ function setByRef(value) {
+ _byref = !!value;
+ }
+ function getSimpleMode() {
+ return _simple;
+ }
+ function setSimpleMode(value) {
+ _simple = !!value;
+ }
+ function getUseHarmonyMap() {
+ return _useHarmonyMap;
+ }
+ function setUseHarmonyMap(value) {
+ _useHarmonyMap = !!value;
+ }
+ function getFilter() {
+ if (_filters.length === 0) {
+ return null;
+ }
+ if (_filters.length === 1) {
+ return _filters[0];
+ }
+ return _filters.slice();
+ }
+ function setFilter(filter) {
+ _filters.length = 0;
+ if (Array.isArray(filter)) {
+ filter.forEach(function(filter) {
+ addFilter(filter);
+ });
+ }
+ else {
+ addFilter(filter);
+ }
+ }
+ function addFilter(filter) {
+ if (filter &&
+ typeof filter.inputFilter === 'function' &&
+ typeof filter.outputFilter === 'function') {
+ _filters.push(filter);
+ }
+ }
+ function removeFilter(filter) {
+ var i = _filters.indexOf(filter);
+ if (i === -1) {
+ return false;
+ }
+ _filters.splice(i, 1);
+ return true;
+ }
+ function filters() {
+ return _filters;
+ }
+ function useService(uri, functions, create) {
+ if (create === undefined) {
+ if (typeof(functions) === s_boolean) {
+ create = functions;
+ functions = false;
+ }
+ if (!functions) {
+ if (typeof(uri) === s_boolean) {
+ create = uri;
+ uri = false;
+ }
+ else if (uri && uri.constructor === Object ||
+ Array.isArray(uri)) {
+ functions = uri;
+ uri = false;
+ }
+ }
+ }
+ var stub = self;
+ if (create) {
+ stub = {};
+ }
+ if (!uri && !_uri) {
+ return new Error('You should set server uri first!');
+ }
+ if (uri) {
+ _uri = uri;
+ }
+ if (typeof(functions) === s_string ||
+ (functions && functions.constructor === Object)) {
+ functions = [functions];
+ }
+ if (Array.isArray(functions)) {
+ setFunctions(stub, functions);
+ }
+ else if (typeof(Proxy) === 'undefined') {
+ setImmediate(initService, stub);
+ return _ready;
+ }
+ else {
+ stub = new Proxy({}, new HproseProxy(setFunction));
+ }
+ _ready.resolve(stub);
+ return stub;
+ }
+ function invoke(name, args, onsuccess/*, onerror, settings*/) {
+ var argc = arguments.length;
+ if ((argc < 1) || (typeof name !== s_string)) {
+ throw new Error('name must be a string');
+ }
+ if (argc === 1) { args = []; }
+ if (argc === 2) {
+ if (!Array.isArray(args)) {
+ var _args = [];
+ if (typeof args !== s_function) {
+ _args.push(noop);
+ }
+ _args.push(args);
+ args = _args;
+ }
+ }
+ if (argc > 2) {
+ if (typeof onsuccess !== s_function) {
+ args.push(noop);
+ }
+ for (var i = 2; i < argc; i++) {
+ args.push(arguments[i]);
+ }
+ }
+ return _invoke(self, name, args, _batch);
+ }
+ function ready(onComplete, onError) {
+ return _ready.then(onComplete, onError);
+ }
+ function getTopic(name, id) {
+ if (_topics[name]) {
+ var topics = _topics[name];
+ if (topics[id]) {
+ return topics[id];
+ }
+ }
+ return null;
+ }
+ // subscribe(name, callback, timeout, failswitch)
+ // subscribe(name, id, callback, timeout, failswitch)
+ function subscribe(name, id, callback, timeout, failswitch) {
+ if (typeof name !== s_string) {
+ throw new TypeError('topic name must be a string.');
+ }
+ if (id === undefined || id === null) {
+ if (typeof callback === s_function) {
+ id = callback;
+ }
+ else {
+ throw new TypeError('callback must be a function.');
+ }
+ }
+ if (!_topics[name]) {
+ _topics[name] = Object.create(null);
+ }
+ if (typeof id === s_function) {
+ timeout = callback;
+ callback = id;
+ autoId().then(function(id) {
+ subscribe(name, id, callback, timeout, failswitch);
+ });
+ return;
+ }
+ if (typeof callback !== s_function) {
+ throw new TypeError('callback must be a function.');
+ }
+ if (Future.isPromise(id)) {
+ id.then(function(id) {
+ subscribe(name, id, callback, timeout, failswitch);
+ });
+ return;
+ }
+ // Default subscribe timeout is 5 minutes.
+ if (timeout === undefined) { timeout = 300000; }
+ var topic = getTopic(name, id);
+ if (topic === null) {
+ var cb = function() {
+ _invoke(self, name, [id, topic.handler, cb, {
+ idempotent: true,
+ failswitch: failswitch,
+ timeout: timeout
+ }], false);
+ };
+ topic = {
+ handler: function(result) {
+ var topic = getTopic(name, id);
+ if (topic) {
+ if (result !== null) {
+ var callbacks = topic.callbacks;
+ for (var i = 0, n = callbacks.length; i < n; ++i) {
+ try {
+ callbacks[i](result);
+ }
+ catch (e) {}
+ }
+ }
+ if (getTopic(name, id) !== null) { cb(); }
+ }
+ },
+ callbacks: [callback]
+ };
+ _topics[name][id] = topic;
+ cb();
+ }
+ else if (topic.callbacks.indexOf(callback) < 0) {
+ topic.callbacks.push(callback);
+ }
+ }
+ function delTopic(topics, id, callback) {
+ if (topics) {
+ if (typeof callback === s_function) {
+ var topic = topics[id];
+ if (topic) {
+ var callbacks = topic.callbacks;
+ var p = callbacks.indexOf(callback);
+ if (p >= 0) {
+ callbacks[p] = callbacks[callbacks.length - 1];
+ callbacks.length--;
+ }
+ if (callbacks.length === 0) {
+ delete topics[id];
+ }
+ }
+ }
+ else {
+ delete topics[id];
+ }
+ }
+ }
+ // unsubscribe(name)
+ // unsubscribe(name, callback)
+ // unsubscribe(name, id)
+ // unsubscribe(name, id, callback)
+ function unsubscribe(name, id, callback) {
+ if (typeof name !== s_string) {
+ throw new TypeError('topic name must be a string.');
+ }
+ if (id === undefined || id === null) {
+ if (typeof callback === s_function) {
+ id = callback;
+ }
+ else {
+ delete _topics[name];
+ return;
+ }
+ }
+ if (typeof id === s_function) {
+ callback = id;
+ id = null;
+ }
+ if (id === null) {
+ if (_id === null) {
+ if (_topics[name]) {
+ var topics = _topics[name];
+ for (id in topics) {
+ delTopic(topics, id, callback);
+ }
+ }
+ }
+ else {
+ _id.then(function(id) {
+ unsubscribe(name, id, callback);
+ });
+ }
+ }
+ else if (Future.isPromise(id)) {
+ id.then(function(id) {
+ unsubscribe(name, id, callback);
+ });
+ }
+ else {
+ delTopic(_topics[name], id, callback);
+ }
+ if (isObjectEmpty(_topics[name])) {
+ delete _topics[name];
+ }
+ }
+ function isSubscribed(name) {
+ return !!_topics[name];
+ }
+ function subscribedList() {
+ var list = [];
+ for (var name in _topics) {
+ list.push(name);
+ }
+ return list;
+ }
+ function getId() {
+ return _id;
+ }
+ function autoId() {
+ if (_id === null) {
+ _id = _invoke(self, '#', [], false);
+ }
+ return _id;
+ }
+ autoId.sync = true;
+ autoId.idempotent = true;
+ autoId.failswitch = true;
+ function addInvokeHandler(handler) {
+ _invokeHandlers.push(handler);
+ _invokeHandler = _invokeHandlers.reduceRight(
+ function(next, handler) {
+ return function(name, args, context) {
+ return Future.toPromise(handler(name, args, context, next));
+ };
+ }, invokeHandler);
+ }
+ function addBatchInvokeHandler(handler) {
+ _batchInvokeHandlers.push(handler);
+ _batchInvokeHandler = _batchInvokeHandlers.reduceRight(
+ function(next, handler) {
+ return function(batches, context) {
+ return Future.toPromise(handler(batches, context, next));
+ };
+ }, batchInvokeHandler);
+ }
+ function addBeforeFilterHandler(handler) {
+ _beforeFilterHandlers.push(handler);
+ _beforeFilterHandler = _beforeFilterHandlers.reduceRight(
+ function(next, handler) {
+ return function(request, context) {
+ return Future.toPromise(handler(request, context, next));
+ };
+ }, beforeFilterHandler);
+ }
+ function addAfterFilterHandler(handler) {
+ _afterFilterHandlers.push(handler);
+ _afterFilterHandler = _afterFilterHandlers.reduceRight(
+ function(next, handler) {
+ return function(request, context) {
+ return Future.toPromise(handler(request, context, next));
+ };
+ }, afterFilterHandler);
+ }
+ function use(handler) {
+ addInvokeHandler(handler);
+ return self;
+ }
+ var batch = Object.create(null, {
+ begin: { value: beginBatch },
+ end: { value: endBatch },
+ use: { value: function(handler) {
+ addBatchInvokeHandler(handler);
+ return batch;
+ } }
+ });
+ var beforeFilter = Object.create(null, {
+ use: { value: function(handler) {
+ addBeforeFilterHandler(handler);
+ return beforeFilter;
+ } }
+ });
+ var afterFilter = Object.create(null, {
+ use: { value: function(handler) {
+ addAfterFilterHandler(handler);
+ return afterFilter;
+ } }
+ });
+ Object.defineProperties(this, {
+ '#': { value: autoId },
+ onerror: { get: getOnError, set: setOnError },
+ onfailswitch: { get: getOnFailswitch, set: setOnFailswitch },
+ uri: { get: getUri },
+ uriList: { get: getUriList, set: setUriList },
+ id: { get: getId },
+ failswitch: { get: getFailswitch, set: setFailswitch },
+ failround: { get: getFailround },
+ timeout: { get: getTimeout, set: setTimeout },
+ retry: { get: getRetry, set: setRetry },
+ idempotent: { get: getIdempotent, set: setIdempotent },
+ keepAlive: { get: getKeepAlive, set: setKeepAlive },
+ byref: { get: getByRef, set: setByRef },
+ simple: { get: getSimpleMode, set: setSimpleMode },
+ useHarmonyMap: { get: getUseHarmonyMap, set: setUseHarmonyMap },
+ filter: { get: getFilter, set: setFilter },
+ addFilter: { value: addFilter },
+ removeFilter: { value: removeFilter },
+ filters: { get: filters },
+ useService: { value: useService },
+ invoke: { value: invoke },
+ ready: { value: ready },
+ subscribe: { value: subscribe },
+ unsubscribe: { value: unsubscribe },
+ isSubscribed: { value : isSubscribed },
+ subscribedList: { value : subscribedList },
+ use: { value: use },
+ batch: { value: batch },
+ beforeFilter: { value: beforeFilter },
+ afterFilter: { value: afterFilter }
+ });
+ /* function constructor */ {
+ if ((settings) && (typeof settings === s_object)) {
+ ['failswitch', 'timeout', 'retry', 'idempotent',
+ 'keepAlive', 'byref', 'simple','useHarmonyMap',
+ 'filter'].forEach(function(key) {
+ if (key in settings) {
+ self[key] = settings[key];
+ }
+ });
+ }
+ if (uri) {
+ setUriList(uri);
+ useService(functions);
+ }
+ }
+ }
+
+ function checkuri(uri) {
+ var parser = parseuri(uri);
+ var protocol = parser.protocol;
+ if (protocol === 'http:' ||
+ protocol === 'https:' ||
+ protocol === 'tcp:' ||
+ protocol === 'tcp4:'||
+ protocol === 'tcp6:' ||
+ protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:' ||
+ protocol === 'ws:' ||
+ protocol === 'wss:') {
+ return;
+ }
+ throw new Error('The ' + protocol + ' client isn\'t implemented.');
+ }
+
+ function create(uri, functions, settings) {
+ try {
+ return hprose.HttpClient.create(uri, functions, settings);
+ }
+ catch(e) {}
+ try {
+ return hprose.TcpClient.create(uri, functions, settings);
+ }
+ catch(e) {}
+ try {
+ return hprose.WebSocketClient.create(uri, functions, settings);
+ }
+ catch(e) {}
+ if (typeof uri === 'string') {
+ checkuri(uri);
+ }
+ else if (Array.isArray(uri)) {
+ uri.forEach(function(uri) { checkuri(uri); });
+ throw new Error('Not support multiple protocol.');
+ }
+ throw new Error('You should set server uri first!');
+ }
+
+ Object.defineProperty(Client, 'create', { value: create });
+
+ hprose.Client = Client;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * CookieManager.js *
+ * *
+ * hprose CookieManager for HTML5. *
+ * *
+ * LastModified: Dec 2, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose) {
+ 'use strict';
+
+ var parseuri = hprose.parseuri;
+
+ var s_cookieManager = {};
+
+ function setCookie(headers, uri) {
+ var parser = parseuri(uri);
+ var host = parser.host;
+ var name, values;
+ function _setCookie(value) {
+ var cookies, cookie, i;
+ cookies = value.replace(/(^\s*)|(\s*$)/g, '').split(';');
+ cookie = {};
+ value = cookies[0].replace(/(^\s*)|(\s*$)/g, '').split('=', 2);
+ if (value[1] === undefined) { value[1] = null; }
+ cookie.name = value[0];
+ cookie.value = value[1];
+ for (i = 1; i < cookies.length; i++) {
+ value = cookies[i].replace(/(^\s*)|(\s*$)/g, '').split('=', 2);
+ if (value[1] === undefined) { value[1] = null; }
+ cookie[value[0].toUpperCase()] = value[1];
+ }
+ // Tomcat can return SetCookie2 with path wrapped in "
+ if (cookie.PATH) {
+ if (cookie.PATH.charAt(0) === '"') {
+ cookie.PATH = cookie.PATH.substr(1);
+ }
+ if (cookie.PATH.charAt(cookie.PATH.length - 1) === '"') {
+ cookie.PATH = cookie.PATH.substr(0, cookie.PATH.length - 1);
+ }
+ }
+ else {
+ cookie.PATH = '/';
+ }
+ if (cookie.EXPIRES) {
+ cookie.EXPIRES = Date.parse(cookie.EXPIRES);
+ }
+ if (cookie.DOMAIN) {
+ cookie.DOMAIN = cookie.DOMAIN.toLowerCase();
+ }
+ else {
+ cookie.DOMAIN = host;
+ }
+ cookie.SECURE = (cookie.SECURE !== undefined);
+ if (s_cookieManager[cookie.DOMAIN] === undefined) {
+ s_cookieManager[cookie.DOMAIN] = {};
+ }
+ s_cookieManager[cookie.DOMAIN][cookie.name] = cookie;
+ }
+ for (name in headers) {
+ values = headers[name];
+ name = name.toLowerCase();
+ if ((name === 'set-cookie') || (name === 'set-cookie2')) {
+ if (typeof(values) === 'string') {
+ values = [values];
+ }
+ values.forEach(_setCookie);
+ }
+ }
+ }
+
+ function getCookie(uri) {
+ var parser = parseuri(uri);
+ var host = parser.host;
+ var path = parser.path;
+ var secure = (parser.protocol === 'https:');
+ var cookies = [];
+ for (var domain in s_cookieManager) {
+ if (host.indexOf(domain) > -1) {
+ var names = [];
+ for (var name in s_cookieManager[domain]) {
+ var cookie = s_cookieManager[domain][name];
+ if (cookie.EXPIRES && ((new Date()).getTime() > cookie.EXPIRES)) {
+ names.push(name);
+ }
+ else if (path.indexOf(cookie.PATH) === 0) {
+ if (((secure && cookie.SECURE) ||
+ !cookie.SECURE) && (cookie.value !== null)) {
+ cookies.push(cookie.name + '=' + cookie.value);
+ }
+ }
+ }
+ for (var i in names) {
+ delete s_cookieManager[domain][names[i]];
+ }
+ }
+ }
+ if (cookies.length > 0) {
+ return cookies.join('; ');
+ }
+ return '';
+ }
+
+ hprose.cookieManager = {
+ setCookie: setCookie,
+ getCookie: getCookie
+ };
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * HttpClient.js *
+ * *
+ * hprose http client for HTML5. *
+ * *
+ * LastModified: Dec 2, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Client = hprose.Client;
+ var Future = hprose.Future;
+ var BytesIO = hprose.BytesIO;
+ var TimeoutError = global.TimeoutError;
+ var localfile = (global.location !== undefined && global.location.protocol === 'file:');
+ var XMLHttpRequest = global.XMLHttpRequest;
+ var nativeXHR = (typeof(XMLHttpRequest) !== 'undefined');
+ var corsSupport = (!localfile && nativeXHR && 'withCredentials' in new XMLHttpRequest());
+ var parseuri = hprose.parseuri;
+ var cookieManager = hprose.cookieManager;
+
+ function noop(){}
+
+ function getResponseHeader(headers) {
+ var header = Object.create(null);
+ if (headers) {
+ headers = headers.split("\r\n");
+ for (var i = 0, n = headers.length; i < n; i++) {
+ if (headers[i] !== "") {
+ var kv = headers[i].split(": ", 2);
+ var k = kv[0].trim();
+ var v = kv[1].trim();
+ if (k in header) {
+ if (Array.isArray(header[k])) {
+ header[k].push(v);
+ }
+ else {
+ header[k] = [header[k], v];
+ }
+ }
+ else {
+ header[k] = v;
+ }
+ }
+ }
+ }
+ return header;
+ }
+
+ function HttpClient(uri, functions, settings) {
+ if (this.constructor !== HttpClient) {
+ return new HttpClient(uri, functions, settings);
+ }
+ Client.call(this, uri, functions, settings);
+ var _header = Object.create(null);
+ var _onreqprogress = noop;
+ var _onresprogress = noop;
+
+ var self = this;
+
+ function getRequestHeader(headers) {
+ var header = Object.create(null);
+ var name, value;
+ for (name in _header) {
+ header[name] = _header[name];
+ }
+ if (headers) {
+ for (name in headers) {
+ value = headers[name];
+ if (Array.isArray(value)) {
+ header[name] = value.join(', ');
+ }
+ else {
+ header[name] = value;
+ }
+ }
+ }
+ return header;
+ }
+
+ function xhrPost(request, context) {
+ var future = new Future();
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', self.uri, true);
+ if (corsSupport) {
+ xhr.withCredentials = 'true';
+ }
+ xhr.responseType = 'arraybuffer';
+ var header = getRequestHeader(context.httpHeader);
+ for (var name in header) {
+ xhr.setRequestHeader(name, header[name]);
+ }
+ xhr.onload = function() {
+ xhr.onload = noop;
+ if (xhr.status) {
+ var headers = xhr.getAllResponseHeaders();
+ context.httpHeader = getResponseHeader(headers);
+ if (xhr.status === 200) {
+ future.resolve(new Uint8Array(xhr.response));
+ }
+ else {
+ future.reject(new Error(xhr.status + ':' + xhr.statusText));
+ }
+ }
+ };
+ xhr.onerror = function() {
+ future.reject(new Error('error'));
+ };
+ if (xhr.upload !== undefined) {
+ xhr.upload.onprogress = _onreqprogress;
+ }
+ xhr.onprogress = _onresprogress;
+ if (context.timeout > 0) {
+ future = future.timeout(context.timeout).catchError(function(e) {
+ xhr.onload = noop;
+ xhr.onerror = noop;
+ xhr.abort();
+ throw e;
+ },
+ function(e) {
+ return e instanceof TimeoutError;
+ });
+ }
+ if (request.constructor === String || ArrayBuffer.isView) {
+ xhr.send(request);
+ }
+ else if (request.buffer.slice) {
+ xhr.send(request.buffer.slice(0, request.length));
+ }
+ else {
+ var buf = new Uint8Array(request.length);
+ buf.set(request);
+ xhr.send(buf.buffer);
+ }
+ return future;
+ }
+
+ function apiPost(request, context) {
+ var future = new Future();
+ var header = getRequestHeader(context.httpHeader);
+ var cookie = cookieManager.getCookie(self.uri());
+ if (cookie !== '') {
+ header['Cookie'] = cookie;
+ }
+ global.api.ajax({
+ url: self.uri,
+ method: 'post',
+ data: { body: BytesIO.toString(request) },
+ timeout: context.timeout,
+ dataType: 'text',
+ headers: header,
+ returnAll: true,
+ certificate: self.certificate
+ }, function(ret, err) {
+ if (ret) {
+ context.httpHeader = ret.headers;
+ if (ret.statusCode === 200) {
+ cookieManager.setCookie(ret.headers, self.uri);
+ future.resolve((new BytesIO(ret.body)).takeBytes());
+ }
+ else {
+ future.reject(new Error(ret.statusCode+':'+ret.body));
+ }
+ }
+ else {
+ future.reject(new Error(err.msg));
+ }
+ });
+ return future;
+ }
+
+ function sendAndReceive(request, context) {
+ var apicloud = (typeof(global.api) !== "undefined" &&
+ typeof(global.api.ajax) !== "undefined");
+ var future = apicloud ? apiPost(request, context) :
+ xhrPost(request, context);
+ if (context.oneway) { future.resolve(); }
+ return future;
+ }
+
+ function setOnRequestProgress(value) {
+ if (typeof(value) === 'function') {
+ _onreqprogress = value;
+ }
+ }
+ function getOnRequestProgress() {
+ return _onreqprogress;
+ }
+ function setOnResponseProgress(value) {
+ if (typeof(value) === 'function') {
+ _onresprogress = value;
+ }
+ }
+ function getOnResponseProgress() {
+ return _onresprogress;
+ }
+ function setHeader(name, value) {
+ if (name.toLowerCase() !== 'content-type' &&
+ name.toLowerCase() !== 'content-length') {
+ if (value) {
+ _header[name] = value;
+ }
+ else {
+ delete _header[name];
+ }
+ }
+ }
+ Object.defineProperties(this, {
+ onprogress: { get: getOnRequestProgress, set: setOnRequestProgress },
+ onRequestProgress: { get: getOnRequestProgress, set: setOnRequestProgress },
+ onResponseProgress: { get: getOnResponseProgress, set: setOnResponseProgress },
+ setHeader: { value: setHeader },
+ sendAndReceive: { value: sendAndReceive }
+ });
+ }
+
+ function checkuri(uri) {
+ var parser = parseuri(uri);
+ if (parser.protocol === 'http:' ||
+ parser.protocol === 'https:') {
+ return;
+ }
+ throw new Error('This client desn\'t support ' + parser.protocol + ' scheme.');
+ }
+
+ function create(uri, functions, settings) {
+ if (typeof uri === 'string') {
+ checkuri(uri);
+ }
+ else if (Array.isArray(uri)) {
+ uri.forEach(function(uri) { checkuri(uri); });
+ }
+ else {
+ throw new Error('You should set server uri first!');
+ }
+ return new HttpClient(uri, functions, settings);
+ }
+
+ Object.defineProperty(HttpClient, 'create', { value: create });
+
+ hprose.HttpClient = HttpClient;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * WebSocketClient.js *
+ * *
+ * hprose websocket client for HTML5. *
+ * *
+ * LastModified: Aug 20, 2017 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var BytesIO = hprose.BytesIO;
+ var Client = hprose.Client;
+ var Future = hprose.Future;
+ var TimeoutError = global.TimeoutError;
+ var parseuri = hprose.parseuri;
+
+ var WebSocket = global.WebSocket || global.MozWebSocket;
+
+ function noop(){}
+ function WebSocketClient(uri, functions, settings) {
+ if (typeof(WebSocket) === "undefined") {
+ throw new Error('WebSocket is not supported by this browser.');
+ }
+ if (this.constructor !== WebSocketClient) {
+ return new WebSocketClient(uri, functions, settings);
+ }
+
+ Client.call(this, uri, functions, settings);
+
+ var _id = 0;
+ var _count = 0;
+ var _futures = [];
+ var _requests = [];
+ var _ready = null;
+ var ws = null;
+
+ var self = this;
+
+ function getNextId() {
+ return (_id < 0x7fffffff) ? ++_id : _id = 0;
+ }
+ function send(id, request) {
+ var bytes = new BytesIO();
+ bytes.writeInt32BE(id);
+ if (request.constructor === String) {
+ bytes.writeString(request);
+ }
+ else {
+ bytes.write(request);
+ }
+ var message = bytes.bytes;
+ if (ArrayBuffer.isView) {
+ ws.send(message);
+ }
+ else if (message.buffer.slice) {
+ ws.send(message.buffer.slice(0, message.length));
+ }
+ else {
+ ws.send(message.buffer);
+ }
+ }
+ function onopen(e) {
+ _ready.resolve(e);
+ }
+ function onmessage(e) {
+ var bytes = new BytesIO(e.data);
+ var id = bytes.readInt32BE();
+ var future = _futures[id];
+ delete _futures[id];
+ if (future !== undefined) {
+ --_count;
+ future.resolve(bytes.read(bytes.length - 4));
+ }
+ if ((_count < 100) && (_requests.length > 0)) {
+ ++_count;
+ var request = _requests.pop();
+ _ready.then(function() { send(request[0], request[1]); });
+ }
+ if (_count === 0 && !self.keepAlive) {
+ close();
+ }
+ }
+ function onclose(e) {
+ _futures.forEach(function(future, id) {
+ future.reject(new Error(e.code + ':' + e.reason));
+ delete _futures[id];
+ });
+ _count = 0;
+ ws = null;
+ }
+ function connect() {
+ _ready = new Future();
+ ws = new WebSocket(self.uri);
+ ws.binaryType = 'arraybuffer';
+ ws.onopen = onopen;
+ ws.onmessage = onmessage;
+ ws.onerror = noop;
+ ws.onclose = onclose;
+ }
+ function sendAndReceive(request, context) {
+ var id = getNextId();
+ var future = new Future();
+ _futures[id] = future;
+ if (context.timeout > 0) {
+ future = future.timeout(context.timeout).catchError(function(e) {
+ delete _futures[id];
+ --_count;
+ close();
+ throw e;
+ },
+ function(e) {
+ return e instanceof TimeoutError;
+ });
+ }
+ if (ws === null ||
+ ws.readyState === WebSocket.CLOSING ||
+ ws.readyState === WebSocket.CLOSED) {
+ connect();
+ }
+ if (_count < 100) {
+ ++_count;
+ _ready.then(function() { send(id, request); });
+ }
+ else {
+ _requests.push([id, request]);
+ }
+ if (context.oneway) { future.resolve(); }
+ return future;
+ }
+ function close() {
+ if (ws !== null) {
+ ws.onopen = noop;
+ ws.onmessage = noop;
+ ws.onclose = noop;
+ ws.close();
+ }
+ }
+
+ Object.defineProperties(this, {
+ sendAndReceive: { value: sendAndReceive },
+ close: { value: close }
+ });
+ }
+
+ function checkuri(uri) {
+ var parser = parseuri(uri);
+ if (parser.protocol === 'ws:' ||
+ parser.protocol === 'wss:') {
+ return;
+ }
+ throw new Error('This client desn\'t support ' + parser.protocol + ' scheme.');
+ }
+
+ function create(uri, functions, settings) {
+ if (typeof uri === 'string') {
+ checkuri(uri);
+ }
+ else if (Array.isArray(uri)) {
+ uri.forEach(function(uri) { checkuri(uri); });
+ }
+ else {
+ throw new Error('You should set server uri first!');
+ }
+ return new WebSocketClient(uri, functions, settings);
+ }
+
+ Object.defineProperty(WebSocketClient, 'create', { value: create });
+
+ hprose.WebSocketClient = WebSocketClient;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * ChromeTcpSocket.js *
+ * *
+ * chrome tcp socket for JavaScript. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Future = hprose.Future;
+
+ function noop(){}
+
+ var socketPool = {};
+ var socketManager = null;
+
+ function receiveListener(info) {
+ var socket = socketPool[info.socketId];
+ socket.onreceive(info.data);
+ }
+
+ function receiveErrorListener(info) {
+ var socket = socketPool[info.socketId];
+ socket.onerror(info.resultCode);
+ socket.destroy();
+ }
+
+ function ChromeTcpSocket() {
+ if (socketManager === null) {
+ socketManager = global.chrome.sockets.tcp;
+ socketManager.onReceive.addListener(receiveListener);
+ socketManager.onReceiveError.addListener(receiveErrorListener);
+ }
+ this.socketId = new Future();
+ this.connected = false;
+ this.timeid = undefined;
+ this.onclose = noop;
+ this.onconnect = noop;
+ this.onreceive = noop;
+ this.onerror = noop;
+ }
+
+ Object.defineProperties(ChromeTcpSocket.prototype, {
+ connect: { value: function(address, port, options) {
+ var self = this;
+ socketManager.create({ persistent: options && options.persistent }, function(createInfo) {
+ if (options) {
+ if ('noDelay' in options) {
+ socketManager.setNoDelay(createInfo.socketId, options.noDelay, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ });
+ }
+ if ('keepAlive' in options) {
+ socketManager.setKeepAlive(createInfo.socketId, options.keepAlive, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ });
+ }
+ }
+ if (options && options.tls) {
+ socketManager.setPaused(createInfo.socketId, true, function() {
+ socketManager.connect(createInfo.socketId, address, port, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ socketManager.secure(createInfo.socketId, function(secureResult) {
+ if (secureResult !== 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ socketManager.setPaused(createInfo.socketId, false, function() {
+ self.socketId.resolve(createInfo.socketId);
+ });
+ }
+ });
+ }
+ });
+ });
+ }
+ else {
+ socketManager.connect(createInfo.socketId, address, port, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ self.socketId.resolve(createInfo.socketId);
+ }
+ });
+ }
+ });
+ this.socketId.then(function(socketId) {
+ socketPool[socketId] = self;
+ self.connected = true;
+ self.onconnect(socketId);
+ }, function(reason) {
+ self.onerror(reason);
+ });
+ } },
+ send: { value: function(data) {
+ var self = this;
+ var promise = new Future();
+ this.socketId.then(function(socketId) {
+ socketManager.send(socketId, data, function(sendInfo) {
+ if (sendInfo.resultCode < 0) {
+ self.onerror(sendInfo.resultCode);
+ promise.reject(sendInfo.resultCode);
+ self.destroy();
+ }
+ else {
+ promise.resolve(sendInfo.bytesSent);
+ }
+ });
+ });
+ return promise;
+ } },
+ destroy: { value: function() {
+ var self = this;
+ this.connected = false;
+ this.socketId.then(function(socketId) {
+ socketManager.disconnect(socketId);
+ socketManager.close(socketId);
+ delete socketPool[socketId];
+ self.onclose();
+ });
+ } },
+ ref: { value: function() {
+ this.socketId.then(function(socketId) {
+ socketManager.setPaused(socketId, false);
+ });
+ } },
+ unref: { value: function() {
+ this.socketId.then(function(socketId) {
+ socketManager.setPaused(socketId, true);
+ });
+ } },
+ clearTimeout: { value: function() {
+ if (this.timeid !== undefined) {
+ global.clearTimeout(this.timeid);
+ }
+ } },
+ setTimeout: { value: function(timeout, fn) {
+ this.clearTimeout();
+ this.timeid = global.setTimeout(fn, timeout);
+ } }
+ });
+
+ hprose.ChromeTcpSocket = ChromeTcpSocket;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * APICloudTcpSocket.js *
+ * *
+ * APICloud tcp socket for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Future = hprose.Future;
+ var atob = global.atob;
+ var btoa = global.btoa;
+ var toUint8Array = hprose.toUint8Array;
+ var toBinaryString = hprose.toBinaryString;
+
+ function noop(){}
+
+ var socketPool = {};
+ var socketManager = null;
+
+ function APICloudTcpSocket() {
+ if (socketManager === null) {
+ socketManager = global.api.require('socketManager');
+ }
+ this.socketId = new Future();
+ this.connected = false;
+ this.timeid = undefined;
+ this.onclose = noop;
+ this.onconnect = noop;
+ this.onreceive = noop;
+ this.onerror = noop;
+ }
+
+ Object.defineProperties(APICloudTcpSocket.prototype, {
+ connect: { value: function(address, port, options) {
+ var self = this;
+ socketManager.createSocket({
+ type: 'tcp',
+ host: address,
+ port: port,
+ timeout: options.timeout,
+ returnBase64: true
+ },
+ function(ret/*, err*/) {
+ if (ret) {
+ switch(ret.state) {
+ case 101: break;
+ case 102: self.socketId.resolve(ret.sid); break;
+ case 103: self.onreceive(toUint8Array(atob(ret.data.replace(/\s+/g, '')))); break;
+ case 201: self.socketId.reject(new Error('Create TCP socket failed')); break;
+ case 202: self.socketId.reject(new Error('TCP connection failed')); break;
+ case 203: self.onclose(); self.onerror(new Error('Abnormal disconnect connection')); break;
+ case 204: self.onclose(); break;
+ case 205: self.onclose(); self.onerror(new Error('Unknown error')); break;
+ }
+ }
+ });
+ this.socketId.then(function(socketId) {
+ socketPool[socketId] = self;
+ self.connected = true;
+ self.onconnect(socketId);
+ }, function(reason) {
+ self.onerror(reason);
+ });
+ } },
+ send: { value: function(data) {
+ var self = this;
+ var promise = new Future();
+ this.socketId.then(function(socketId) {
+ socketManager.write({
+ sid: socketId,
+ data: btoa(toBinaryString(data)),
+ base64: true
+ },
+ function(ret, err) {
+ if (ret.status) {
+ promise.resolve();
+ }
+ else {
+ self.onerror(new Error(err.msg));
+ promise.reject(err.msg);
+ self.destroy();
+ }
+ });
+ });
+ return promise;
+ } },
+ destroy: { value: function() {
+ var self = this;
+ this.connected = false;
+ this.socketId.then(function(socketId) {
+ socketManager.closeSocket({
+ sid: socketId
+ },
+ function(ret, err) {
+ if (!ret.status) {
+ self.onerror(new Error(err.msg));
+ }
+ });
+ delete socketPool[socketId];
+ //self.onclose();
+ });
+ } },
+ ref: { value: noop },
+ unref: { value: noop },
+ clearTimeout: { value: function() {
+ if (this.timeid !== undefined) {
+ global.clearTimeout(this.timeid);
+ }
+ } },
+ setTimeout: { value: function(timeout, fn) {
+ this.clearTimeout();
+ this.timeid = global.setTimeout(fn, timeout);
+ } }
+ });
+
+ hprose.APICloudTcpSocket = APICloudTcpSocket;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * TcpClient.js *
+ * *
+ * hprose tcp client for HTML5. *
+ * *
+ * LastModified: Dec 2, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var ChromeTcpSocket = hprose.ChromeTcpSocket;
+ var APICloudTcpSocket = hprose.APICloudTcpSocket;
+ var Client = hprose.Client;
+ var BytesIO = hprose.BytesIO;
+ var Future = hprose.Future;
+ var TimeoutError = global.TimeoutError;
+ var parseuri = hprose.parseuri;
+
+ function noop(){}
+
+ function setReceiveHandler(socket, onreceive) {
+ socket.onreceive = function(data) {
+ if (!('receiveEntry' in socket)) {
+ socket.receiveEntry = {
+ stream: new BytesIO(),
+ headerLength: 4,
+ dataLength: -1,
+ id: null
+ };
+ }
+ var entry = socket.receiveEntry;
+ var stream = entry.stream;
+ var headerLength = entry.headerLength;
+ var dataLength = entry.dataLength;
+ var id = entry.id;
+ stream.write(data);
+ while (true) {
+ if ((dataLength < 0) && (stream.length >= headerLength)) {
+ dataLength = stream.readInt32BE();
+ if ((dataLength & 0x80000000) !== 0) {
+ dataLength &= 0x7fffffff;
+ headerLength = 8;
+ }
+ }
+ if ((headerLength === 8) && (id === null) && (stream.length >= headerLength)) {
+ id = stream.readInt32BE();
+ }
+ if ((dataLength >= 0) && ((stream.length - headerLength) >= dataLength)) {
+ onreceive(stream.read(dataLength), id);
+ headerLength = 4;
+ id = null;
+ stream.trunc();
+ dataLength = -1;
+ }
+ else {
+ break;
+ }
+ }
+ entry.stream = stream;
+ entry.headerLength = headerLength;
+ entry.dataLength = dataLength;
+ entry.id = id;
+ };
+ }
+
+ function TcpTransporter(client) {
+ if (client) {
+ this.client = client;
+ this.uri = this.client.uri;
+ this.size = 0;
+ this.pool = [];
+ this.requests = [];
+ }
+ }
+
+ Object.defineProperties(TcpTransporter.prototype, {
+ create: { value: function() {
+ var parser = parseuri(this.uri);
+ var protocol = parser.protocol;
+ var address = parser.hostname;
+ var port = parseInt(parser.port, 10);
+ var tls;
+ if (protocol === 'tcp:' ||
+ protocol === 'tcp4:' ||
+ protocol === 'tcp6:') {
+ tls = false;
+ }
+ else if (protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:') {
+ tls = true;
+ }
+ else {
+ throw new Error('Unsupported ' + protocol + ' protocol!');
+ }
+ var conn;
+ if (global.chrome && global.chrome.sockets && global.chrome.sockets.tcp) {
+ conn = new ChromeTcpSocket();
+ }
+ else if (global.api && global.api.require) {
+ conn = new APICloudTcpSocket();
+ }
+ else {
+ throw new Error('TCP Socket is not supported by this browser or platform.');
+ }
+ var self = this;
+ conn.connect(address, port, {
+ persistent: true,
+ tls: tls,
+ timeout: this.client.timeout,
+ noDelay: this.client.noDelay,
+ keepAlive: this.client.keepAlive
+ });
+ conn.onclose = function() { --self.size; };
+ ++this.size;
+ return conn;
+ } }
+ });
+
+ function FullDuplexTcpTransporter(client) {
+ TcpTransporter.call(this, client);
+ }
+
+ FullDuplexTcpTransporter.prototype = Object.create(
+ TcpTransporter.prototype, {
+ fetch: { value: function() {
+ var pool = this.pool;
+ while (pool.length > 0) {
+ var conn = pool.pop();
+ if (conn.connected) {
+ if (conn.count === 0) {
+ conn.clearTimeout();
+ conn.ref();
+ }
+ return conn;
+ }
+ }
+ return null;
+ } },
+ init: { value: function(conn) {
+ var self = this;
+ conn.count = 0;
+ conn.futures = {};
+ conn.timeoutIds = {};
+ setReceiveHandler(conn, function(data, id) {
+ var future = conn.futures[id];
+ if (future) {
+ self.clean(conn, id);
+ if (conn.count === 0) {
+ self.recycle(conn);
+ }
+ future.resolve(data);
+ }
+ });
+ conn.onerror = function (e) {
+ var futures = conn.futures;
+ for (var id in futures) {
+ var future = futures[id];
+ self.clean(conn, id);
+ future.reject(e);
+ }
+ };
+ } },
+ recycle: { value: function(conn) {
+ conn.unref();
+ conn.setTimeout(this.client.poolTimeout, function() {
+ conn.destroy();
+ });
+ } },
+ clean: { value: function(conn, id) {
+ if (conn.timeoutIds[id] !== undefined) {
+ global.clearTimeout(conn.timeoutIds[id]);
+ delete conn.timeoutIds[id];
+ }
+ delete conn.futures[id];
+ --conn.count;
+ this.sendNext(conn);
+ } },
+ sendNext: { value: function(conn) {
+ if (conn.count < 10) {
+ if (this.requests.length > 0) {
+ var request = this.requests.pop();
+ request.push(conn);
+ this.send.apply(this, request);
+ }
+ else {
+ if (this.pool.lastIndexOf(conn) < 0) {
+ this.pool.push(conn);
+ }
+ }
+ }
+ } },
+ send: { value: function(request, future, id, context, conn) {
+ var self = this;
+ var timeout = context.timeout;
+ if (timeout > 0) {
+ conn.timeoutIds[id] = global.setTimeout(function() {
+ self.clean(conn, id);
+ if (conn.count === 0) {
+ self.recycle(conn);
+ }
+ future.reject(new TimeoutError('timeout'));
+ }, timeout);
+ }
+ conn.count++;
+ conn.futures[id] = future;
+
+ var len = request.length;
+ var buf = new BytesIO(8 + len);
+ buf.writeInt32BE(len | 0x80000000);
+ buf.writeInt32BE(id);
+ buf.write(request);
+ conn.send(buf.buffer).then(function() {
+ self.sendNext(conn);
+ });
+ } },
+ getNextId: { value: function() {
+ return (this.nextid < 0x7fffffff) ? ++this.nextid : this.nextid = 0;
+ } },
+ sendAndReceive: { value: function(request, future, context) {
+ var conn = this.fetch();
+ var id = this.getNextId();
+ if (conn) {
+ this.send(request, future, id, context, conn);
+ }
+ else if (this.size < this.client.maxPoolSize) {
+ conn = this.create();
+ conn.onerror = function(e) {
+ future.reject(e);
+ };
+ var self = this;
+ conn.onconnect = function() {
+ self.init(conn);
+ self.send(request, future, id, context, conn);
+ };
+ }
+ else {
+ this.requests.push([request, future, id, context]);
+ }
+ } }
+ });
+
+ FullDuplexTcpTransporter.prototype.constructor = TcpTransporter;
+
+ function HalfDuplexTcpTransporter(client) {
+ TcpTransporter.call(this, client);
+ }
+
+ HalfDuplexTcpTransporter.prototype = Object.create(
+ TcpTransporter.prototype, {
+ fetch: { value: function() {
+ var pool = this.pool;
+ while (pool.length > 0) {
+ var conn = pool.pop();
+ if (conn.connected) {
+ conn.clearTimeout();
+ conn.ref();
+ return conn;
+ }
+ }
+ return null;
+ } },
+ recycle: { value: function(conn) {
+ if (this.pool.lastIndexOf(conn) < 0) {
+ conn.unref();
+ conn.setTimeout(this.client.poolTimeout, function() {
+ conn.destroy();
+ });
+ this.pool.push(conn);
+ }
+ } },
+ clean: { value: function(conn) {
+ conn.onreceive = noop;
+ conn.onerror = noop;
+ if (conn.timeoutId !== undefined) {
+ global.clearTimeout(conn.timeoutId);
+ delete conn.timeoutId;
+ }
+ } },
+ sendNext: { value: function(conn) {
+ if (this.requests.length > 0) {
+ var request = this.requests.pop();
+ request.push(conn);
+ this.send.apply(this, request);
+ }
+ else {
+ this.recycle(conn);
+ }
+ } },
+ send: { value: function(request, future, context, conn) {
+ var self = this;
+ var timeout = context.timeout;
+ if (timeout > 0) {
+ conn.timeoutId = global.setTimeout(function() {
+ self.clean(conn);
+ conn.destroy();
+ future.reject(new TimeoutError('timeout'));
+ }, timeout);
+ }
+ setReceiveHandler(conn, function(data) {
+ self.clean(conn);
+ self.sendNext(conn);
+ future.resolve(data);
+ });
+ conn.onerror = function(e) {
+ self.clean(conn);
+ future.reject(e);
+ };
+
+ var len = request.length;
+ var buf = new BytesIO(4 + len);
+ buf.writeInt32BE(len);
+ buf.write(request);
+ conn.send(buf.buffer);
+ } },
+ sendAndReceive: { value: function(request, future, context) {
+ var conn = this.fetch();
+ if (conn) {
+ this.send(request, future, context, conn);
+ }
+ else if (this.size < this.client.maxPoolSize) {
+ conn = this.create();
+ var self = this;
+ conn.onerror = function(e) {
+ future.reject(e);
+ };
+ conn.onconnect = function() {
+ self.send(request, future, context, conn);
+ };
+ }
+ else {
+ this.requests.push([request, future, context]);
+ }
+ } }
+ });
+
+ HalfDuplexTcpTransporter.prototype.constructor = TcpTransporter;
+
+ function TcpClient(uri, functions, settings) {
+ if (this.constructor !== TcpClient) {
+ return new TcpClient(uri, functions, settings);
+ }
+ Client.call(this, uri, functions, settings);
+
+ var self = this;
+ var _noDelay = true;
+ var _fullDuplex = false;
+ var _maxPoolSize = 10;
+ var _poolTimeout = 30000;
+ var fdtrans = null;
+ var hdtrans = null;
+
+ function getNoDelay() {
+ return _noDelay;
+ }
+
+ function setNoDelay(value) {
+ _noDelay = !!value;
+ }
+
+ function getFullDuplex() {
+ return _fullDuplex;
+ }
+
+ function setFullDuplex(value) {
+ _fullDuplex = !!value;
+ }
+
+ function getMaxPoolSize() {
+ return _maxPoolSize;
+ }
+
+ function setMaxPoolSize(value) {
+ if (typeof(value) === 'number') {
+ _maxPoolSize = value | 0;
+ if (_maxPoolSize < 1) {
+ _maxPoolSize = 10;
+ }
+ }
+ else {
+ _maxPoolSize = 10;
+ }
+ }
+
+ function getPoolTimeout() {
+ return _poolTimeout;
+ }
+
+ function setPoolTimeout(value) {
+ if (typeof(value) === 'number') {
+ _poolTimeout = value | 0;
+ }
+ else {
+ _poolTimeout = 0;
+ }
+ }
+
+ function sendAndReceive(request, context) {
+ var future = new Future();
+ if (_fullDuplex) {
+ if ((fdtrans === null) || (fdtrans.uri !== self.uri)) {
+ fdtrans = new FullDuplexTcpTransporter(self);
+ }
+ fdtrans.sendAndReceive(request, future, context);
+ }
+ else {
+ if ((hdtrans === null) || (hdtrans.uri !== self.uri)) {
+ hdtrans = new HalfDuplexTcpTransporter(self);
+ }
+ hdtrans.sendAndReceive(request, future, context);
+ }
+ if (context.oneway) { future.resolve(); }
+ return future;
+ }
+
+ Object.defineProperties(this, {
+ noDelay: { get: getNoDelay, set: setNoDelay },
+ fullDuplex: { get: getFullDuplex, set: setFullDuplex },
+ maxPoolSize: { get: getMaxPoolSize, set: setMaxPoolSize },
+ poolTimeout: { get: getPoolTimeout, set: setPoolTimeout },
+ sendAndReceive: { value: sendAndReceive }
+ });
+ }
+
+ function checkuri(uri) {
+ var parser = parseuri(uri);
+ var protocol = parser.protocol;
+ if (protocol === 'tcp:' ||
+ protocol === 'tcp4:'||
+ protocol === 'tcp6:' ||
+ protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:') {
+ return;
+ }
+ throw new Error('This client desn\'t support ' + protocol + ' scheme.');
+ }
+
+ function create(uri, functions, settings) {
+ if (typeof uri === 'string') {
+ checkuri(uri);
+ }
+ else if (Array.isArray(uri)) {
+ uri.forEach(function(uri) { checkuri(uri); });
+ }
+ else {
+ throw new Error('You should set server uri first!');
+ }
+ return new TcpClient(uri, functions, settings);
+ }
+
+ Object.defineProperty(TcpClient, 'create', { value: create });
+
+ hprose.TcpClient = TcpClient;
+
+})(hprose, hprose.global);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * JSONRPCClientFilter.js *
+ * *
+ * jsonrpc client filter for JavaScript. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+/* global JSON */
+(function (hprose) {
+ 'use strict';
+
+ var Tags = hprose.Tags;
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
+
+ var s_id = 1;
+
+ function JSONRPCClientFilter(version) {
+ this.version = version || '2.0';
+ }
+
+ JSONRPCClientFilter.prototype.inputFilter = function inputFilter(data/*, context*/) {
+ var json = BytesIO.toString(data);
+ if (json.charAt(0) === '{') {
+ json = '[' + json + ']';
+ }
+ var responses = JSON.parse(json);
+ var stream = new BytesIO();
+ var writer = new Writer(stream, true);
+ for (var i = 0, n = responses.length; i < n; ++i) {
+ var response = responses[i];
+ if (response.error) {
+ stream.writeByte(Tags.TagError);
+ writer.writeString(response.error.message);
+ }
+ else {
+ stream.writeByte(Tags.TagResult);
+ writer.serialize(response.result);
+ }
+ }
+ stream.writeByte(Tags.TagEnd);
+ return stream.bytes;
+ };
+
+ JSONRPCClientFilter.prototype.outputFilter = function outputFilter(data/*, context*/) {
+ var requests = [];
+ var stream = new BytesIO(data);
+ var reader = new Reader(stream, false, false);
+ var tag = stream.readByte();
+ do {
+ var request = {};
+ if (tag === Tags.TagCall) {
+ request.method = reader.readString();
+ tag = stream.readByte();
+ if (tag === Tags.TagList) {
+ request.params = reader.readListWithoutTag();
+ tag = stream.readByte();
+ }
+ if (tag === Tags.TagTrue) {
+ tag = stream.readByte();
+ }
+ }
+ if (this.version === '1.1') {
+ request.version = '1.1';
+ }
+ else if (this.version === '2.0') {
+ request.jsonrpc = '2.0';
+ }
+ request.id = s_id++;
+ requests.push(request);
+ } while (tag === Tags.TagCall);
+ if (requests.length > 1) {
+ return JSON.stringify(requests);
+ }
+ return JSON.stringify(requests[0]);
+ };
+
+ hprose.JSONRPCClientFilter = JSONRPCClientFilter;
+
+})(hprose);
+
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Loader.js *
+ * *
+ * hprose CommonJS/AMD/CMD loader for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+/* global define, module */
+(function (hprose) {
+ 'use strict';
+
+ hprose.common = {
+ Completer: hprose.Completer,
+ Future: hprose.Future,
+ ResultMode: hprose.ResultMode
+ };
+
+ hprose.io = {
+ BytesIO: hprose.BytesIO,
+ ClassManager: hprose.ClassManager,
+ Tags: hprose.Tags,
+ RawReader: hprose.RawReader,
+ Reader: hprose.Reader,
+ Writer: hprose.Writer,
+ Formatter: hprose.Formatter
+ };
+
+ hprose.client = {
+ Client: hprose.Client,
+ HttpClient: hprose.HttpClient,
+ TcpClient: hprose.TcpClient,
+ WebSocketClient: hprose.WebSocketClient
+ };
+
+ hprose.filter = {
+ JSONRPCClientFilter: hprose.JSONRPCClientFilter
+ };
+
+ if (typeof define === 'function') {
+ if (define.cmd) {
+ define('hprose', [], hprose);
+ }
+ else if (define.amd) {
+ define('hprose', [], function() { return hprose; });
+ }
+ }
+ if (typeof module === 'object') {
+ module.exports = hprose;
+ }
+})(hprose);
diff --git a/gulpfile.js b/gulpfile.js
index 4eb13ed..cf47b0a 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,3 +1,4 @@
+/* jshint node:true */
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
@@ -9,8 +10,11 @@ gulp.task('clear', function(){
del(['dist/hprose-html5.js']);
});
-gulp.task('compress', ['clear'], function() {
- return gulp.src(['src/Init.js',
+gulp.task('concat', ['clear'], function() {
+ return gulp.src(['src/CopyRight.js',
+ 'src/Init.js',
+ 'src/Helper.js',
+ 'src/Polyfill.js',
'src/HarmonyMaps.js',
'src/TimeoutError.js',
'src/setImmediate.js',
@@ -23,18 +27,35 @@ gulp.task('compress', ['clear'], function() {
'src/Formatter.js',
'src/ResultMode.js',
'src/Client.js',
+ 'src/CookieManager.js',
'src/HttpClient.js',
'src/WebSocketClient.js',
+ 'src/ChromeTcpSocket.js',
+ 'src/APICloudTcpSocket.js',
+ 'src/TcpClient.js',
'src/JSONRPCClientFilter.js',
'src/Loader.js'])
+ .pipe(concat('hprose-html5.src.js'))
.pipe(jshint())
.pipe(jshint.reporter())
- .pipe(concat('hprose-html5.js'))
- .pipe(uglify())
- .pipe(lzmajs())
.pipe(gulp.dest('dist'));
});
+gulp.task('uglify', ['concat'], function() {
+ return gulp.src(['dist/hprose-html5.src.js',
+ 'utils/regenerator-runtime.js'])
+ .pipe(concat('hprose-html5.js'))
+ .pipe(uglify())
+ .pipe(gulp.dest('dist'));
+});
+
+gulp.task('compress', ['uglify'], function() {
+ return gulp.src(['dist/hprose-html5.js'])
+ .pipe(concat('hprose-html5.min.js'))
+ .pipe(lzmajs())
+ .pipe(gulp.dest('dist'));
+});
+
gulp.task('default', ['compress'], function() {
return gulp.src(['src/CopyRight.js', 'dist/hprose-html5.js'])
.pipe(concat('hprose-html5.js'))
diff --git a/package.json b/package.json
index 420d9f5..2bd539f 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,8 @@
{
"name": "hprose-html5",
- "filename": "hprose-html5.js",
- "version": "2.0.3",
- "description": "Hprose is a High Performance Remote Object Service Engine. It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system.",
- "homepage": "https://github.com/andot/hprose",
+ "version": "2.0.36",
+ "description": "Hprose is a High Performance Remote Object Service Engine.",
+ "homepage": "https://github.com/hprose/hprose-html5",
"keywords": [
"hprose",
"rpc",
@@ -42,25 +41,46 @@
"oneway",
"promises-aplus"
],
- "maintainers": [
- {
- "name" : "Ma Bingyao",
- "email" : "andot@hprose.com",
- "web": "http://hprose.com/"
- }
- ],
- "repositories": [
- {
- "type": "git",
- "url": "https://github.com/hprose/hprose-html5.git"
- }
- ],
+ "author": {
+ "name": "Ma Bingyao",
+ "email": "andot@hprose.com",
+ "url": "http://hprose.com/"
+ },
+ "directories": {
+ "lib": "dist/"
+ },
+ "main": "dist/hprose-html5.src.js",
+ "devDependencies": {
+ "del": "^3.0.0",
+ "gulp": "^3.9.1",
+ "gulp-concat": "^2.6.1",
+ "gulp-jshint": "^2.1.0",
+ "gulp-lzmajs": "^1.2.1",
+ "gulp-uglify": "^2.0.0",
+ "jshint": "^2.9.5",
+ "promises-aplus-tests": "*"
+ },
+ "scripts": {
+ "aplus-tests": "promises-aplus-tests dist/hprose-html5.js"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/hprose/hprose-html5.git"
+ },
"autoupdate": {
"source": "git",
"target": "git://github.com/hprose/hprose-html5.git",
"basePath": "dist/",
"files": [
- "hprose-html5.js"
+ "hprose-html5.src.js"
]
- }
+ },
+ "bugs": {
+ "url": "https://github.com/hprose/hprose-html5/issues",
+ "email": "andot@hprose.com"
+ },
+ "license": "MIT"
}
diff --git a/src/APICloudTcpSocket.js b/src/APICloudTcpSocket.js
new file mode 100644
index 0000000..c943a3a
--- /dev/null
+++ b/src/APICloudTcpSocket.js
@@ -0,0 +1,132 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * APICloudTcpSocket.js *
+ * *
+ * APICloud tcp socket for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Future = hprose.Future;
+ var atob = global.atob;
+ var btoa = global.btoa;
+ var toUint8Array = hprose.toUint8Array;
+ var toBinaryString = hprose.toBinaryString;
+
+ function noop(){}
+
+ var socketPool = {};
+ var socketManager = null;
+
+ function APICloudTcpSocket() {
+ if (socketManager === null) {
+ socketManager = global.api.require('socketManager');
+ }
+ this.socketId = new Future();
+ this.connected = false;
+ this.timeid = undefined;
+ this.onclose = noop;
+ this.onconnect = noop;
+ this.onreceive = noop;
+ this.onerror = noop;
+ }
+
+ Object.defineProperties(APICloudTcpSocket.prototype, {
+ connect: { value: function(address, port, options) {
+ var self = this;
+ socketManager.createSocket({
+ type: 'tcp',
+ host: address,
+ port: port,
+ timeout: options.timeout,
+ returnBase64: true
+ },
+ function(ret/*, err*/) {
+ if (ret) {
+ switch(ret.state) {
+ case 101: break;
+ case 102: self.socketId.resolve(ret.sid); break;
+ case 103: self.onreceive(toUint8Array(atob(ret.data.replace(/\s+/g, '')))); break;
+ case 201: self.socketId.reject(new Error('Create TCP socket failed')); break;
+ case 202: self.socketId.reject(new Error('TCP connection failed')); break;
+ case 203: self.onclose(); self.onerror(new Error('Abnormal disconnect connection')); break;
+ case 204: self.onclose(); break;
+ case 205: self.onclose(); self.onerror(new Error('Unknown error')); break;
+ }
+ }
+ });
+ this.socketId.then(function(socketId) {
+ socketPool[socketId] = self;
+ self.connected = true;
+ self.onconnect(socketId);
+ }, function(reason) {
+ self.onerror(reason);
+ });
+ } },
+ send: { value: function(data) {
+ var self = this;
+ var promise = new Future();
+ this.socketId.then(function(socketId) {
+ socketManager.write({
+ sid: socketId,
+ data: btoa(toBinaryString(data)),
+ base64: true
+ },
+ function(ret, err) {
+ if (ret.status) {
+ promise.resolve();
+ }
+ else {
+ self.onerror(new Error(err.msg));
+ promise.reject(err.msg);
+ self.destroy();
+ }
+ });
+ });
+ return promise;
+ } },
+ destroy: { value: function() {
+ var self = this;
+ this.connected = false;
+ this.socketId.then(function(socketId) {
+ socketManager.closeSocket({
+ sid: socketId
+ },
+ function(ret, err) {
+ if (!ret.status) {
+ self.onerror(new Error(err.msg));
+ }
+ });
+ delete socketPool[socketId];
+ //self.onclose();
+ });
+ } },
+ ref: { value: noop },
+ unref: { value: noop },
+ clearTimeout: { value: function() {
+ if (this.timeid !== undefined) {
+ global.clearTimeout(this.timeid);
+ }
+ } },
+ setTimeout: { value: function(timeout, fn) {
+ this.clearTimeout();
+ this.timeid = global.setTimeout(fn, timeout);
+ } }
+ });
+
+ hprose.APICloudTcpSocket = APICloudTcpSocket;
+
+})(hprose, hprose.global);
diff --git a/src/Base64.js b/src/Base64.js
new file mode 100644
index 0000000..d712887
--- /dev/null
+++ b/src/Base64.js
@@ -0,0 +1,134 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * Base64.js *
+ * *
+ * Base64 for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (global) {
+ 'use strict';
+
+ if (typeof(global.btoa) === "undefined") {
+ global.btoa = (function() {
+ var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
+ return function(str) {
+ var buf, i, j, len, r, l, c;
+ i = j = 0;
+ len = str.length;
+ r = len % 3;
+ len = len - r;
+ l = (len / 3) << 2;
+ if (r > 0) {
+ l += 4;
+ }
+ buf = new Array(l);
+
+ while (i < len) {
+ c = str.charCodeAt(i++) << 16 |
+ str.charCodeAt(i++) << 8 |
+ str.charCodeAt(i++);
+ buf[j++] = base64EncodeChars[c >> 18] +
+ base64EncodeChars[c >> 12 & 0x3f] +
+ base64EncodeChars[c >> 6 & 0x3f] +
+ base64EncodeChars[c & 0x3f] ;
+ }
+ if (r === 1) {
+ c = str.charCodeAt(i++);
+ buf[j++] = base64EncodeChars[c >> 2] +
+ base64EncodeChars[(c & 0x03) << 4] +
+ "==";
+ }
+ else if (r === 2) {
+ c = str.charCodeAt(i++) << 8 |
+ str.charCodeAt(i++);
+ buf[j++] = base64EncodeChars[c >> 10] +
+ base64EncodeChars[c >> 4 & 0x3f] +
+ base64EncodeChars[(c & 0x0f) << 2] +
+ "=";
+ }
+ return buf.join('');
+ };
+ })();
+ }
+
+ if (typeof(global.atob) === "undefined") {
+ global.atob = (function() {
+ var base64DecodeChars = [
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 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, -1, -1, -1, -1, -1,
+ -1, 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, -1, -1, -1, -1, -1
+ ];
+ return function(str) {
+ var c1, c2, c3, c4;
+ var i, j, len, r, l, out;
+
+ len = str.length;
+ if (len % 4 !== 0) {
+ return '';
+ }
+ if (/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+\/\=]/.test(str)) {
+ return '';
+ }
+ if (str.charAt(len - 2) === '=') {
+ r = 1;
+ }
+ else if (str.charAt(len - 1) === '=') {
+ r = 2;
+ }
+ else {
+ r = 0;
+ }
+ l = len;
+ if (r > 0) {
+ l -= 4;
+ }
+ l = (l >> 2) * 3 + r;
+ out = new Array(l);
+
+ i = j = 0;
+ while (i < len) {
+ // c1
+ c1 = base64DecodeChars[str.charCodeAt(i++)];
+ if (c1 === -1) { break; }
+
+ // c2
+ c2 = base64DecodeChars[str.charCodeAt(i++)];
+ if (c2 === -1) { break; }
+
+ out[j++] = String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
+
+ // c3
+ c3 = base64DecodeChars[str.charCodeAt(i++)];
+ if (c3 === -1) { break; }
+
+ out[j++] = String.fromCharCode(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));
+
+ // c4
+ c4 = base64DecodeChars[str.charCodeAt(i++)];
+ if (c4 === -1) { break; }
+
+ out[j++] = String.fromCharCode(((c3 & 0x03) << 6) | c4);
+ }
+ return out.join('');
+ };
+ })();
+ }
+
+})(hprose.global);
diff --git a/src/BytesIO.js b/src/BytesIO.js
index 160be21..fea8658 100644
--- a/src/BytesIO.js
+++ b/src/BytesIO.js
@@ -13,34 +13,32 @@
* *
* hprose BytesIO for HTML5. *
* *
- * LastModified: Aug 21, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, undefined) {
'use strict';
- var Future = global.hprose.Future;
+ var toBinaryString = hprose.toBinaryString;
var _EMPTY_BYTES = new Uint8Array(0);
var _INIT_SIZE = 1024;
- var indexof = Function.prototype.call.bind(Array.prototype.indexOf);
function writeInt32BE(bytes, p, i) {
- bytes[p++] = i >>> 24 & 0xff;
- bytes[p++] = i >>> 16 & 0xff;
- bytes[p++] = i >>> 8 & 0xff;
- bytes[p++] = i & 0xff;
+ bytes[p++] = i >>> 24 & 0xFF;
+ bytes[p++] = i >>> 16 & 0xFF;
+ bytes[p++] = i >>> 8 & 0xFF;
+ bytes[p++] = i & 0xFF;
return p;
}
function writeInt32LE(bytes, p, i) {
- bytes[p++] = i & 0xff;
- bytes[p++] = i >>> 8 & 0xff;
- bytes[p++] = i >>> 16 & 0xff;
- bytes[p++] = i >>> 24 & 0xff;
+ bytes[p++] = i & 0xFF;
+ bytes[p++] = i >>> 8 & 0xFF;
+ bytes[p++] = i >>> 16 & 0xFF;
+ bytes[p++] = i >>> 24 & 0xFF;
return p;
}
@@ -55,7 +53,7 @@
bytes[p++] = 0xC0 | (codeUnit >> 6);
bytes[p++] = 0x80 | (codeUnit & 0x3F);
}
- else if (codeUnit < 0xD800 || codeUnit > 0xDfff) {
+ else if (codeUnit < 0xD800 || codeUnit > 0xDFFF) {
bytes[p++] = 0xE0 | (codeUnit >> 12);
bytes[p++] = 0x80 | ((codeUnit >> 6) & 0x3F);
bytes[p++] = 0x80 | (codeUnit & 0x3F);
@@ -80,7 +78,7 @@
}
function readShortString(bytes, n) {
- var charCodes = new Uint16Array(n);
+ var charCodes = new Array(n);
var i = 0, off = 0;
for (var len = bytes.length; i < n && off < len; i++) {
var unit = bytes[off++];
@@ -100,21 +98,17 @@
if (off < len) {
charCodes[i] = ((unit & 0x1F) << 6) |
(bytes[off++] & 0x3F);
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 14:
if (off + 1 < len) {
charCodes[i] = ((unit & 0x0F) << 12) |
((bytes[off++] & 0x3F) << 6) |
(bytes[off++] & 0x3F);
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 15:
if (off + 2 < len) {
var rune = (((unit & 0x07) << 18) |
@@ -124,28 +118,24 @@
if (0 <= rune && rune <= 0xFFFFF) {
charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800);
charCodes[i] = ((rune & 0x03FF) | 0xDC00);
+ break;
}
- else {
- throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
- }
- }
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
}
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
default:
throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
}
}
if (i < n) {
- charCodes = charCodes.subarray(0, i);
+ charCodes.length = i;
}
return [String.fromCharCode.apply(String, charCodes), off];
}
function readLongString(bytes, n) {
var buf = [];
- var charCodes = new Uint16Array(0xffff);
+ var charCodes = new Array(0x8000);
var i = 0, off = 0;
for (var len = bytes.length; i < n && off < len; i++) {
var unit = bytes[off++];
@@ -165,21 +155,17 @@
if (off < len) {
charCodes[i] = ((unit & 0x1F) << 6) |
(bytes[off++] & 0x3F);
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 14:
if (off + 1 < len) {
charCodes[i] = ((unit & 0x0F) << 12) |
((bytes[off++] & 0x3F) << 6) |
(bytes[off++] & 0x3F);
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 15:
if (off + 2 < len) {
var rune = (((unit & 0x07) << 18) |
@@ -189,42 +175,40 @@
if (0 <= rune && rune <= 0xFFFFF) {
charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800);
charCodes[i] = ((rune & 0x03FF) | 0xDC00);
+ break;
}
- else {
- throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
- }
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
default:
throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
}
- if (i >= 65534) {
+ if (i >= 0x7FFF - 1) {
var size = i + 1;
- buf.push(String.fromCharCode.apply(String, charCodes.subarray(0, size)));
+ charCodes.length = size;
+ buf.push(String.fromCharCode.apply(String, charCodes));
n -= size;
i = -1;
}
}
if (i > 0) {
- buf.push(String.fromCharCode.apply(String, charCodes.subarray(0, i)));
+ charCodes.length = i;
+ buf.push(String.fromCharCode.apply(String, charCodes));
}
return [buf.join(''), off];
}
function readString(bytes, n) {
- if (n === undefined || n === null || (n < 0)) n = bytes.length;
- if (n === 0) return ['', 0];
- return ((n < 100000) ?
+ if (n === undefined || n === null || (n < 0)) { n = bytes.length; }
+ if (n === 0) { return ['', 0]; }
+ return ((n < 0xFFFF) ?
readShortString(bytes, n) :
readLongString(bytes, n));
}
function readStringAsBytes(bytes, n) {
- if (n === undefined) n = bytes.length;
- if (n === 0) return _EMPTY_BYTES;
+ if (n === undefined) { n = bytes.length; }
+ if (n === 0) { return [_EMPTY_BYTES, 0]; }
var i = 0, off = 0;
for (var len = bytes.length; i < n && off < len; i++) {
var unit = bytes[off++];
@@ -242,19 +226,15 @@
case 13:
if (off < len) {
off++;
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 14:
if (off + 1 < len) {
off += 2;
+ break;
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
case 15:
if (off + 2 < len) {
var rune = (((unit & 0x07) << 18) |
@@ -263,15 +243,11 @@
(bytes[off++] & 0x3F)) - 0x10000;
if (0 <= rune && rune <= 0xFFFFF) {
i++;
+ break;
}
- else {
- throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
- }
+ throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16));
}
- else {
- throw new Error('Unfinished UTF-8 octet sequence');
- }
- break;
+ throw new Error('Unfinished UTF-8 octet sequence');
default:
throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16));
}
@@ -360,6 +336,17 @@
_EMPTY_BYTES :
this._bytes.subarray(0, this._length);
} },
+ buffer: { get : function() {
+ if (this._bytes === null) {
+ return _EMPTY_BYTES.buffer;
+ }
+ if (this._bytes.buffer.slice) {
+ return this._bytes.buffer.slice(0, this._length);
+ }
+ var buf = new Uint8Array(this._length);
+ buf.set(this._bytes.subarray(0, this._length));
+ return buf.buffer;
+ } },
mark: { value: function() {
this._wmark = this._length;
this._rmark = this._off;
@@ -388,9 +375,9 @@
throw new TypeError('value is out of bounds');
} },
writeUInt32BE: { value: function(i) {
- if ((i === (i | 0)) && (i >= 0)) {
+ if (((i & 0x7FFFFFFF) + 0x80000000 === i) && (i >= 0)) {
this._grow(4);
- this._length = writeInt32BE(this._bytes, this._length, i);
+ this._length = writeInt32BE(this._bytes, this._length, i | 0);
return;
}
throw new TypeError('value is out of bounds');
@@ -404,16 +391,16 @@
throw new TypeError('value is out of bounds');
} },
writeUInt32LE: { value: function(i) {
- if ((i === (i | 0)) && (i >= 0)) {
+ if (((i & 0x7FFFFFFF) + 0x80000000 === i) && (i >= 0)) {
this._grow(4);
- this._length = writeInt32LE(this._bytes, this._length, i);
+ this._length = writeInt32LE(this._bytes, this._length, i | 0);
return;
}
throw new TypeError('value is out of bounds');
} },
write: { value: function(data) {
var n = data.byteLength || data.length;
- if (n === 0) return;
+ if (n === 0) { return; }
this._grow(n);
var bytes = this._bytes;
var length = this._length;
@@ -437,7 +424,7 @@
} },
writeAsciiString: { value: function(str) {
var n = str.length;
- if (n === 0) return;
+ if (n === 0) { return; }
this._grow(n);
var bytes = this._bytes;
var l = this._length;
@@ -448,7 +435,7 @@
} },
writeString: { value: function(str) {
var n = str.length;
- if (n === 0) return;
+ if (n === 0) { return; }
// A single code unit uses at most 3 bytes.
// Two code units at most 4.
this._grow(n * 3);
@@ -476,7 +463,7 @@
readUInt32BE: { value: function() {
var value = this.readInt32BE();
if (value < 0) {
- return (value & 0x7fffffff) + 0x80000000;
+ return (value & 0x7FFFFFFF) + 0x80000000;
}
return value;
} },
@@ -496,7 +483,7 @@
readUInt32LE: { value: function() {
var value = this.readInt32LE();
if (value < 0) {
- return (value & 0x7fffffff) + 0x80000000;
+ return (value & 0x7FFFFFFF) + 0x80000000;
}
return value;
} },
@@ -504,7 +491,7 @@
if (this._off + n > this._length) {
n = this._length - this._off;
}
- if (n === 0) return _EMPTY_BYTES;
+ if (n === 0) { return _EMPTY_BYTES; }
return this._bytes.subarray(this._off, this._off += n);
} },
skip: { value: function(n) {
@@ -519,7 +506,7 @@
} },
// the result is an Uint8Array, and includes tag.
readBytes: { value: function(tag) {
- var pos = indexof(this._bytes, tag, this._off);
+ var pos = Array.indexOf(this._bytes, tag, this._off);
var buf;
if (pos === -1) {
buf = this._bytes.subarray(this._off, this._length);
@@ -534,7 +521,7 @@
// the result is a String, and doesn't include tag.
// but the position is the same as readBytes
readUntil: { value: function(tag) {
- var pos = indexof(this._bytes, tag, this._off);
+ var pos = Array.indexOf(this._bytes, tag, this._off);
var str = '';
if (pos === this._off) {
this._off++;
@@ -553,21 +540,8 @@
if (this._off + n > this._length) {
n = this._length - this._off;
}
- if (n === 0) return '';
- var bytes = this._bytes.subarray(this._off, this._off += n);
- if (n < 100000) {
- return String.fromCharCode.apply(String, bytes);
- }
- var remain = n & 0xffff;
- var count = n >> 16;
- var a = new Array(remain ? count + 1 : count);
- for (var i = 0; i < count; ++i) {
- a[i] = String.fromCharCode.apply(String, bytes.subarray(i << 16, (i + 1) << 16));
- }
- if (remain) {
- a[count] = String.fromCharCode.apply(String, bytes.subarray(count << 16, n));
- }
- return a.join('');
+ if (n === 0) { return ''; }
+ return toBinaryString(this._bytes.subarray(this._off, this._off += n));
} },
// n is the UTF16 length
readStringAsBytes: { value: function(n) {
@@ -608,7 +582,7 @@
function toString(data) {
/* jshint -W086 */
- if (data.length === 0) return '';
+ if (data.length === 0) { return ''; }
switch(data.constructor) {
case String: return data;
case BytesIO: data = data.bytes;
@@ -620,8 +594,6 @@
Object.defineProperty(BytesIO, 'toString', { value: toString });
- global.hprose.BytesIO = BytesIO;
+ hprose.BytesIO = BytesIO;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/ChromeTcpSocket.js b/src/ChromeTcpSocket.js
new file mode 100644
index 0000000..f7d10b7
--- /dev/null
+++ b/src/ChromeTcpSocket.js
@@ -0,0 +1,181 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * ChromeTcpSocket.js *
+ * *
+ * chrome tcp socket for JavaScript. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var Future = hprose.Future;
+
+ function noop(){}
+
+ var socketPool = {};
+ var socketManager = null;
+
+ function receiveListener(info) {
+ var socket = socketPool[info.socketId];
+ socket.onreceive(info.data);
+ }
+
+ function receiveErrorListener(info) {
+ var socket = socketPool[info.socketId];
+ socket.onerror(info.resultCode);
+ socket.destroy();
+ }
+
+ function ChromeTcpSocket() {
+ if (socketManager === null) {
+ socketManager = global.chrome.sockets.tcp;
+ socketManager.onReceive.addListener(receiveListener);
+ socketManager.onReceiveError.addListener(receiveErrorListener);
+ }
+ this.socketId = new Future();
+ this.connected = false;
+ this.timeid = undefined;
+ this.onclose = noop;
+ this.onconnect = noop;
+ this.onreceive = noop;
+ this.onerror = noop;
+ }
+
+ Object.defineProperties(ChromeTcpSocket.prototype, {
+ connect: { value: function(address, port, options) {
+ var self = this;
+ socketManager.create({ persistent: options && options.persistent }, function(createInfo) {
+ if (options) {
+ if ('noDelay' in options) {
+ socketManager.setNoDelay(createInfo.socketId, options.noDelay, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ });
+ }
+ if ('keepAlive' in options) {
+ socketManager.setKeepAlive(createInfo.socketId, options.keepAlive, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ });
+ }
+ }
+ if (options && options.tls) {
+ socketManager.setPaused(createInfo.socketId, true, function() {
+ socketManager.connect(createInfo.socketId, address, port, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ socketManager.secure(createInfo.socketId, function(secureResult) {
+ if (secureResult !== 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ socketManager.setPaused(createInfo.socketId, false, function() {
+ self.socketId.resolve(createInfo.socketId);
+ });
+ }
+ });
+ }
+ });
+ });
+ }
+ else {
+ socketManager.connect(createInfo.socketId, address, port, function(result) {
+ if (result < 0) {
+ self.socketId.reject(result);
+ socketManager.disconnect(createInfo.socketId);
+ socketManager.close(createInfo.socketId);
+ self.onclose();
+ }
+ else {
+ self.socketId.resolve(createInfo.socketId);
+ }
+ });
+ }
+ });
+ this.socketId.then(function(socketId) {
+ socketPool[socketId] = self;
+ self.connected = true;
+ self.onconnect(socketId);
+ }, function(reason) {
+ self.onerror(reason);
+ });
+ } },
+ send: { value: function(data) {
+ var self = this;
+ var promise = new Future();
+ this.socketId.then(function(socketId) {
+ socketManager.send(socketId, data, function(sendInfo) {
+ if (sendInfo.resultCode < 0) {
+ self.onerror(sendInfo.resultCode);
+ promise.reject(sendInfo.resultCode);
+ self.destroy();
+ }
+ else {
+ promise.resolve(sendInfo.bytesSent);
+ }
+ });
+ });
+ return promise;
+ } },
+ destroy: { value: function() {
+ var self = this;
+ this.connected = false;
+ this.socketId.then(function(socketId) {
+ socketManager.disconnect(socketId);
+ socketManager.close(socketId);
+ delete socketPool[socketId];
+ self.onclose();
+ });
+ } },
+ ref: { value: function() {
+ this.socketId.then(function(socketId) {
+ socketManager.setPaused(socketId, false);
+ });
+ } },
+ unref: { value: function() {
+ this.socketId.then(function(socketId) {
+ socketManager.setPaused(socketId, true);
+ });
+ } },
+ clearTimeout: { value: function() {
+ if (this.timeid !== undefined) {
+ global.clearTimeout(this.timeid);
+ }
+ } },
+ setTimeout: { value: function(timeout, fn) {
+ this.clearTimeout();
+ this.timeid = global.setTimeout(fn, timeout);
+ } }
+ });
+
+ hprose.ChromeTcpSocket = ChromeTcpSocket;
+
+})(hprose, hprose.global);
diff --git a/src/ClassManager.js b/src/ClassManager.js
index ada281b..8e8e165 100644
--- a/src/ClassManager.js
+++ b/src/ClassManager.js
@@ -13,13 +13,12 @@
* *
* hprose ClassManager for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+(function (hprose, global) {
'use strict';
var WeakMap = global.WeakMap;
@@ -40,16 +39,14 @@
return classCache[alias];
}
- global.hprose.ClassManager = Object.create(null, {
+ hprose.ClassManager = Object.create(null, {
register: { value: register },
getClassAlias: { value: getClassAlias },
getClass: { value: getClass }
});
- global.hprose.register = register;
+ hprose.register = register;
register(Object, 'Object');
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose, hprose.global);
diff --git a/src/Client.js b/src/Client.js
index fa3f2fa..2a07533 100644
--- a/src/Client.js
+++ b/src/Client.js
@@ -12,23 +12,24 @@
* *
* hprose client for HTML5. *
* *
- * LastModified: Aug 18, 2015 *
+ * LastModified: Apr 24, 2018 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+/* global Proxy */
+(function (hprose, global, undefined) {
'use strict';
var setImmediate = global.setImmediate;
- var Tags = global.hprose.Tags;
- var ResultMode = global.hprose.ResultMode;
- var BytesIO = global.hprose.BytesIO;
- var Writer = global.hprose.Writer;
- var Reader = global.hprose.Reader;
- var Future = global.hprose.Future;
- var slice = Function.prototype.call.bind(Array.prototype.slice);
+ var Tags = hprose.Tags;
+ var ResultMode = hprose.ResultMode;
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
+ var Future = hprose.Future;
+ var parseuri = hprose.parseuri;
+ var isObjectEmpty = hprose.isObjectEmpty;
var GETFUNCTIONS = new Uint8Array(1);
GETFUNCTIONS[0] = Tags.TagEnd;
@@ -40,13 +41,35 @@
var s_number = 'number';
var s_function = 'function';
var s_object = 'object';
- var s_undefined = 'undefined';
+
+ function HproseProxy(setFunction, ns) {
+ var settings = {};
+ this.get = function(target, prop/*, receiver*/) {
+ var name = prop.toString();
+ if (ns) { name = ns + '_' + name; }
+ if (name === 'then') { return undefined; }
+ if (!target.hasOwnProperty(name)) {
+ settings[name] = {};
+ var handler = new HproseProxy(setFunction, name);
+ var func = setFunction(settings, name);
+ handler.apply = function(target, thisArg, argumentsList) {
+ return func.apply(null, argumentsList);
+ }
+ handler.set = function(target, prop, value/*, receiver*/) {
+ settings[name][prop] = value;
+ return true;
+ };
+ target[name] = new Proxy(function() {}, handler);
+ }
+ return target[name];
+ };
+ }
function Client(uri, functions, settings) {
// private members
var _uri,
- _uris = [],
+ _uriList = [],
_index = -1,
_byref = false,
_simple = false,
@@ -54,10 +77,12 @@
_retry = 10,
_idempotent = false,
_failswitch = false,
+ _failround = 0,
_lock = false,
_tasks = [],
_useHarmonyMap = false,
_onerror = noop,
+ _onfailswitch = noop,
_filters = [],
_batch = false,
_batches = [],
@@ -94,46 +119,91 @@
request = outputFilter(request, context);
return _afterFilterHandler(request, context)
.then(function(response) {
- if (context.oneway) return;
+ if (context.oneway) { return; }
return inputFilter(response, context);
});
}
function afterFilterHandler(request, context) {
- return self.sendAndReceive(request, context);
+ return self.sendAndReceive(request, context).catchError(function(e) {
+ var response = retry(request, context);
+ if (response !== null) {
+ return response;
+ }
+ throw e;
+ });
}
function sendAndReceive(request, context, onsuccess, onerror) {
- _beforeFilterHandler(request, context)
- .then(onsuccess, function(e) {
- if (retry(request, context, onsuccess, onerror)) return;
- onerror(e);
- });
+ _beforeFilterHandler(request, context).then(onsuccess, onerror);
+ }
+
+ function failswitch() {
+ var n = _uriList.length;
+ if (n > 1) {
+ var i = _index + 1;
+ if (i >= n) {
+ i = 0;
+ _failround++;
+ }
+ _index = i;
+ _uri = _uriList[_index];
+ }
+ else {
+ _failround++;
+ }
+ _onfailswitch(self);
}
- function retry(data, context, onsuccess, onerror) {
+ function retry(data, context) {
if (context.failswitch) {
- if (++_index >= _uris.length) {
- _index = 0;
- _uri = _uris[_index];
+ failswitch();
+ }
+ if (context.idempotent && (context.retried < context.retry)) {
+ var interval = ++context.retried * 500;
+ if (context.failswitch) {
+ interval -= (_uriList.length - 1) * 500;
+ }
+ if (interval > 5000) {
+ interval = 5000;
+ }
+ if (interval > 0) {
+ return Future.delayed(interval, function() {
+ return afterFilterHandler(data, context);
+ });
+ }
+ else {
+ return afterFilterHandler(data, context);
}
}
- if (context.idempotent) {
- if (--context.retry >= 0) {
- var interval = (10 - context.retry) * 500;
- if (context.retry > 10) interval = 500;
- global.setTimeout(function() {
- sendAndReceive(data, context, onsuccess, onerror);
- }, interval);
- return true;
+ return null;
+ }
+
+ function normalizeFunctions(functions) {
+ var root = [Object.create(null)];
+ for (var i in functions) {
+ var func = functions[i].split('_');
+ var n = func.length - 1;
+ if (n > 0) {
+ var node = root;
+ for (var j = 0; j < n; j++) {
+ var f = func[j];
+ if (node[0][f] === undefined) {
+ node[0][f] = [Object.create(null)];
+ }
+ node = node[0][f];
+ }
+ node.push(func[n]);
}
+ root.push(functions[i]);
}
- return false;
+ return root;
}
function initService(stub) {
var context = {
retry: _retry,
+ retried: 0,
idempotent: true,
failswitch: true,
timeout: _timeout,
@@ -151,7 +221,7 @@
error = new Error(reader.readString());
break;
case Tags.TagFunctions:
- var functions = reader.readList();
+ var functions = normalizeFunctions(reader.readList());
reader.checkTag(Tags.TagEnd);
setFunctions(stub, functions);
break;
@@ -176,7 +246,7 @@
function setFunction(stub, name) {
return function() {
if (_batch) {
- return _invoke(stub, name, slice(arguments), true);
+ return _invoke(stub, name, Array.slice(arguments), true);
}
else {
return Future.all(arguments).then(function(args) {
@@ -187,7 +257,7 @@
}
function setMethods(stub, obj, namespace, name, methods) {
- if (obj[name] !== undefined) return;
+ if (obj[name] !== undefined) { return; }
obj[name] = {};
if (typeof(methods) === s_string || methods.constructor === Object) {
methods = [methods];
@@ -200,7 +270,7 @@
}
else {
for (var n in m) {
- setMethods(stub, obj[name], name + '_', n, m[n]);
+ setMethods(stub, obj[name], namespace + name + '_', n, m[n]);
}
}
}
@@ -225,7 +295,7 @@
function copyargs(src, dest) {
var n = Math.min(src.length, dest.length);
- for (var i = 0; i < n; ++i) dest[i] = src[i];
+ for (var i = 0; i < n; ++i) { dest[i] = src[i]; }
}
function initContext(batch) {
@@ -247,6 +317,7 @@
simple: _simple,
timeout: _timeout,
retry: _retry,
+ retried: 0,
idempotent: _idempotent,
failswitch: _failswitch,
oneway: false,
@@ -271,9 +342,9 @@
}
var i = 0, n = args.length;
for (; i < n; ++i) {
- if (typeof args[i] === s_function) break;
+ if (typeof args[i] === s_function) { break; }
}
- if (i === n) return context;
+ if (i === n) { return context; }
var extra = args.splice(i, n - i);
context.onsuccess = extra[0];
n = extra.length;
@@ -431,7 +502,7 @@
}
function call(name, args, context) {
- if (context.sync) _lock = true;
+ if (context.sync) { _lock = true; }
var promise = Future.promise(function(resolve, reject) {
_invokeHandler(name, args, context).then(function(result) {
try {
@@ -475,6 +546,7 @@
var context = {
timeout: _timeout,
retry: _retry,
+ retried: 0,
idempotent: _idempotent,
failswitch: _failswitch,
oneway: false,
@@ -597,9 +669,9 @@
});
}
var batchSize = _batches.length;
- if (batchSize === 0) return;
+ if (batchSize === 0) { return Future.value([]); }
var context = getBatchContext(settings);
- if (context.sync) _lock = true;
+ if (context.sync) { _lock = true; }
var batches = _batches;
_batches = [];
var promise = Future.promise(function(resolve, reject) {
@@ -653,15 +725,43 @@
_onerror = value;
}
}
+ function getOnFailswitch() {
+ return _onfailswitch;
+ }
+ function setOnFailswitch(value) {
+ if (typeof(value) === s_function) {
+ _onfailswitch = value;
+ }
+ }
function getUri() {
return _uri;
}
+ function getUriList() {
+ return _uriList;
+ }
+ function setUriList(uriList) {
+ if (typeof(uriList) === s_string) {
+ _uriList = [uriList];
+ }
+ else if (Array.isArray(uriList)) {
+ _uriList = uriList.slice(0);
+ _uriList.sort(function() { return Math.random() - 0.5; });
+ }
+ else {
+ return;
+ }
+ _index = 0;
+ _uri = _uriList[_index];
+ }
function getFailswitch() {
return _failswitch;
}
function setFailswitch(value) {
_failswitch = !!value;
}
+ function getFailround() {
+ return _failround;
+ }
function getTimeout() {
return _timeout;
}
@@ -749,6 +849,9 @@
_filters.splice(i, 1);
return true;
}
+ function filters() {
+ return _filters;
+ }
function useService(uri, functions, create) {
if (create === undefined) {
if (typeof(functions) === s_boolean) {
@@ -781,11 +884,16 @@
(functions && functions.constructor === Object)) {
functions = [functions];
}
- if (!Array.isArray(functions)) {
+ if (Array.isArray(functions)) {
+ setFunctions(stub, functions);
+ }
+ else if (typeof(Proxy) === 'undefined') {
setImmediate(initService, stub);
return _ready;
}
- setFunctions(stub, functions);
+ else {
+ stub = new Proxy({}, new HproseProxy(setFunction));
+ }
_ready.resolve(stub);
return stub;
}
@@ -794,7 +902,7 @@
if ((argc < 1) || (typeof name !== s_string)) {
throw new Error('name must be a string');
}
- if (argc === 1) args = [];
+ if (argc === 1) { args = []; }
if (argc === 2) {
if (!Array.isArray(args)) {
var _args = [];
@@ -818,22 +926,18 @@
function ready(onComplete, onError) {
return _ready.then(onComplete, onError);
}
- function getTopic(name, id, create) {
+ function getTopic(name, id) {
if (_topics[name]) {
var topics = _topics[name];
if (topics[id]) {
return topics[id];
}
- return null;
- }
- if (create) {
- _topics[name] = Object.create(null);
}
return null;
}
- // subscribe(name, callback, timeout)
- // subscribe(name, id, callback, timeout)
- function subscribe(name, id, callback, timeout) {
+ // subscribe(name, callback, timeout, failswitch)
+ // subscribe(name, id, callback, timeout, failswitch)
+ function subscribe(name, id, callback, timeout, failswitch) {
if (typeof name !== s_string) {
throw new TypeError('topic name must be a string.');
}
@@ -845,14 +949,14 @@
throw new TypeError('callback must be a function.');
}
}
+ if (!_topics[name]) {
+ _topics[name] = Object.create(null);
+ }
if (typeof id === s_function) {
timeout = callback;
callback = id;
- if (_id === null) {
- _id = autoId();
- }
- _id.then(function(id) {
- subscribe(name, id, callback, timeout);
+ autoId().then(function(id) {
+ subscribe(name, id, callback, timeout, failswitch);
});
return;
}
@@ -861,23 +965,24 @@
}
if (Future.isPromise(id)) {
id.then(function(id) {
- subscribe(name, id, callback, timeout);
+ subscribe(name, id, callback, timeout, failswitch);
});
return;
}
- if (timeout === undefined) timeout = _timeout;
- var topic = getTopic(name, id, true);
+ // Default subscribe timeout is 5 minutes.
+ if (timeout === undefined) { timeout = 300000; }
+ var topic = getTopic(name, id);
if (topic === null) {
var cb = function() {
_invoke(self, name, [id, topic.handler, cb, {
idempotent: true,
- failswitch: false,
+ failswitch: failswitch,
timeout: timeout
}], false);
};
topic = {
handler: function(result) {
- var topic = getTopic(name, id, false);
+ var topic = getTopic(name, id);
if (topic) {
if (result !== null) {
var callbacks = topic.callbacks;
@@ -888,7 +993,7 @@
catch (e) {}
}
}
- if (getTopic(name, id, false) !== null) cb();
+ if (getTopic(name, id) !== null) { cb(); }
}
},
callbacks: [callback]
@@ -965,12 +1070,28 @@
else {
delTopic(_topics[name], id, callback);
}
+ if (isObjectEmpty(_topics[name])) {
+ delete _topics[name];
+ }
+ }
+ function isSubscribed(name) {
+ return !!_topics[name];
+ }
+ function subscribedList() {
+ var list = [];
+ for (var name in _topics) {
+ list.push(name);
+ }
+ return list;
}
function getId() {
return _id;
}
function autoId() {
- return _invoke(self, '#', [], false);
+ if (_id === null) {
+ _id = _invoke(self, '#', [], false);
+ }
+ return _id;
}
autoId.sync = true;
autoId.idempotent = true;
@@ -980,14 +1101,7 @@
_invokeHandler = _invokeHandlers.reduceRight(
function(next, handler) {
return function(name, args, context) {
- try {
- var result = handler(name, args, context, next);
- if (Future.isFuture(result)) return result;
- return Future.value(result);
- }
- catch (e) {
- return Future.error(e);
- }
+ return Future.toPromise(handler(name, args, context, next));
};
}, invokeHandler);
}
@@ -996,14 +1110,7 @@
_batchInvokeHandler = _batchInvokeHandlers.reduceRight(
function(next, handler) {
return function(batches, context) {
- try {
- var result = handler(batches, context, next);
- if (Future.isFuture(result)) return result;
- return Future.value(result);
- }
- catch (e) {
- return Future.error(e);
- }
+ return Future.toPromise(handler(batches, context, next));
};
}, batchInvokeHandler);
}
@@ -1012,14 +1119,7 @@
_beforeFilterHandler = _beforeFilterHandlers.reduceRight(
function(next, handler) {
return function(request, context) {
- try {
- var response = handler(request, context, next);
- if (Future.isFuture(response)) return response;
- return Future.value(response);
- }
- catch (e) {
- return Future.error(e);
- }
+ return Future.toPromise(handler(request, context, next));
};
}, beforeFilterHandler);
}
@@ -1028,14 +1128,7 @@
_afterFilterHandler = _afterFilterHandlers.reduceRight(
function(next, handler) {
return function(request, context) {
- try {
- var response = handler(request, context, next);
- if (Future.isFuture(response)) return response;
- return Future.value(response);
- }
- catch (e) {
- return Future.error(e);
- }
+ return Future.toPromise(handler(request, context, next));
};
}, afterFilterHandler);
}
@@ -1065,11 +1158,13 @@
});
Object.defineProperties(this, {
'#': { value: autoId },
- onError: { get: getOnError, set: setOnError },
onerror: { get: getOnError, set: setOnError },
+ onfailswitch: { get: getOnFailswitch, set: setOnFailswitch },
uri: { get: getUri },
+ uriList: { get: getUriList, set: setUriList },
id: { get: getId },
failswitch: { get: getFailswitch, set: setFailswitch },
+ failround: { get: getFailround },
timeout: { get: getTimeout, set: setTimeout },
retry: { get: getRetry, set: setRetry },
idempotent: { get: getIdempotent, set: setIdempotent },
@@ -1080,11 +1175,14 @@
filter: { get: getFilter, set: setFilter },
addFilter: { value: addFilter },
removeFilter: { value: removeFilter },
+ filters: { get: filters },
useService: { value: useService },
invoke: { value: invoke },
ready: { value: ready },
subscribe: { value: subscribe },
unsubscribe: { value: unsubscribe },
+ isSubscribed: { value : isSubscribed },
+ subscribedList: { value : subscribedList },
use: { value: use },
batch: { value: batch },
beforeFilter: { value: beforeFilter },
@@ -1100,38 +1198,43 @@
}
});
}
- if (typeof(uri) === s_string) {
- _uris = [uri];
- _index = 0;
- useService(uri, functions);
- }
- else if (Array.isArray(uri)) {
- _uris = uri;
- _index = Math.floor(Math.random() * _uris.length);
- useService(_uris[_index], functions);
+ if (uri) {
+ setUriList(uri);
+ useService(functions);
}
}
}
function checkuri(uri) {
- var parser = document.createElement('a');
- parser.href = uri;
- if (parser.protocol === 'http:' ||
- parser.protocol === 'https:' ||
- parser.protocol === 'ws:' ||
- parser.protocol === 'wss:') {
+ var parser = parseuri(uri);
+ var protocol = parser.protocol;
+ if (protocol === 'http:' ||
+ protocol === 'https:' ||
+ protocol === 'tcp:' ||
+ protocol === 'tcp4:'||
+ protocol === 'tcp6:' ||
+ protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:' ||
+ protocol === 'ws:' ||
+ protocol === 'wss:') {
return;
}
- throw new Error('The ' + parser.protocol + ' client isn\'t implemented.');
+ throw new Error('The ' + protocol + ' client isn\'t implemented.');
}
function create(uri, functions, settings) {
try {
- return global.hprose.HttpClient.create(uri, functions, settings);
+ return hprose.HttpClient.create(uri, functions, settings);
+ }
+ catch(e) {}
+ try {
+ return hprose.TcpClient.create(uri, functions, settings);
}
catch(e) {}
try {
- return global.hprose.WebSocketClient.create(uri, functions, settings);
+ return hprose.WebSocketClient.create(uri, functions, settings);
}
catch(e) {}
if (typeof uri === 'string') {
@@ -1146,8 +1249,6 @@
Object.defineProperty(Client, 'create', { value: create });
- global.hprose.Client = Client;
+ hprose.Client = Client;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose, hprose.global);
diff --git a/src/CookieManager.js b/src/CookieManager.js
new file mode 100644
index 0000000..1414c1a
--- /dev/null
+++ b/src/CookieManager.js
@@ -0,0 +1,120 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * CookieManager.js *
+ * *
+ * hprose CookieManager for HTML5. *
+ * *
+ * LastModified: Dec 2, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose) {
+ 'use strict';
+
+ var parseuri = hprose.parseuri;
+
+ var s_cookieManager = {};
+
+ function setCookie(headers, uri) {
+ var parser = parseuri(uri);
+ var host = parser.host;
+ var name, values;
+ function _setCookie(value) {
+ var cookies, cookie, i;
+ cookies = value.replace(/(^\s*)|(\s*$)/g, '').split(';');
+ cookie = {};
+ value = cookies[0].replace(/(^\s*)|(\s*$)/g, '').split('=', 2);
+ if (value[1] === undefined) { value[1] = null; }
+ cookie.name = value[0];
+ cookie.value = value[1];
+ for (i = 1; i < cookies.length; i++) {
+ value = cookies[i].replace(/(^\s*)|(\s*$)/g, '').split('=', 2);
+ if (value[1] === undefined) { value[1] = null; }
+ cookie[value[0].toUpperCase()] = value[1];
+ }
+ // Tomcat can return SetCookie2 with path wrapped in "
+ if (cookie.PATH) {
+ if (cookie.PATH.charAt(0) === '"') {
+ cookie.PATH = cookie.PATH.substr(1);
+ }
+ if (cookie.PATH.charAt(cookie.PATH.length - 1) === '"') {
+ cookie.PATH = cookie.PATH.substr(0, cookie.PATH.length - 1);
+ }
+ }
+ else {
+ cookie.PATH = '/';
+ }
+ if (cookie.EXPIRES) {
+ cookie.EXPIRES = Date.parse(cookie.EXPIRES);
+ }
+ if (cookie.DOMAIN) {
+ cookie.DOMAIN = cookie.DOMAIN.toLowerCase();
+ }
+ else {
+ cookie.DOMAIN = host;
+ }
+ cookie.SECURE = (cookie.SECURE !== undefined);
+ if (s_cookieManager[cookie.DOMAIN] === undefined) {
+ s_cookieManager[cookie.DOMAIN] = {};
+ }
+ s_cookieManager[cookie.DOMAIN][cookie.name] = cookie;
+ }
+ for (name in headers) {
+ values = headers[name];
+ name = name.toLowerCase();
+ if ((name === 'set-cookie') || (name === 'set-cookie2')) {
+ if (typeof(values) === 'string') {
+ values = [values];
+ }
+ values.forEach(_setCookie);
+ }
+ }
+ }
+
+ function getCookie(uri) {
+ var parser = parseuri(uri);
+ var host = parser.host;
+ var path = parser.path;
+ var secure = (parser.protocol === 'https:');
+ var cookies = [];
+ for (var domain in s_cookieManager) {
+ if (host.indexOf(domain) > -1) {
+ var names = [];
+ for (var name in s_cookieManager[domain]) {
+ var cookie = s_cookieManager[domain][name];
+ if (cookie.EXPIRES && ((new Date()).getTime() > cookie.EXPIRES)) {
+ names.push(name);
+ }
+ else if (path.indexOf(cookie.PATH) === 0) {
+ if (((secure && cookie.SECURE) ||
+ !cookie.SECURE) && (cookie.value !== null)) {
+ cookies.push(cookie.name + '=' + cookie.value);
+ }
+ }
+ }
+ for (var i in names) {
+ delete s_cookieManager[domain][names[i]];
+ }
+ }
+ }
+ if (cookies.length > 0) {
+ return cookies.join('; ');
+ }
+ return '';
+ }
+
+ hprose.cookieManager = {
+ setCookie: setCookie,
+ getCookie: getCookie
+ };
+})(hprose);
diff --git a/src/CopyRight.js b/src/CopyRight.js
index 26fa1eb..6b9a072 100644
--- a/src/CopyRight.js
+++ b/src/CopyRight.js
@@ -1,5 +1,5 @@
-// Hprose for HTML5 v2.0.3
-// Copyright (c) 2008-2015 http://hprose.com
+// Hprose for HTML5 v2.0.36
+// Copyright (c) 2008-2016 http://hprose.com
// Hprose is freely distributable under the MIT license.
// For all details and documentation:
// https://github.com/hprose/hprose-html5
diff --git a/src/Formatter.js b/src/Formatter.js
index 45d5d66..ed8396f 100644
--- a/src/Formatter.js
+++ b/src/Formatter.js
@@ -13,18 +13,17 @@
* *
* hprose Formatter for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+(function (hprose) {
'use strict';
- var BytesIO = global.hprose.BytesIO;
- var Writer = global.hprose.Writer;
- var Reader = global.hprose.Reader;
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
function serialize(value, simple) {
var stream = new BytesIO();
@@ -40,17 +39,15 @@
return new Reader(stream, simple, useHarmonyMap).unserialize();
}
- global.hprose.Formatter = {
+ hprose.Formatter = {
serialize: function (value, simple) {
return serialize(value, simple).bytes;
},
unserialize: unserialize
};
- global.hprose.serialize = serialize;
+ hprose.serialize = serialize;
- global.hprose.unserialize = unserialize;
+ hprose.unserialize = unserialize;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/Future.js b/src/Future.js
index ef2ad4e..898a01c 100644
--- a/src/Future.js
+++ b/src/Future.js
@@ -13,13 +13,12 @@
* *
* hprose Future for HTML5. *
* *
- * LastModified: Jul 28, 2015 *
+ * LastModified: Dec 5, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, global, undefined) {
'use strict';
var PENDING = 0;
@@ -30,16 +29,18 @@
var setImmediate = global.setImmediate;
var setTimeout = global.setTimeout;
var clearTimeout = global.clearTimeout;
- var foreach = Function.prototype.call.bind(Array.prototype.forEach);
- var slice = Function.prototype.call.bind(Array.prototype.slice);
+ var TimeoutError = global.TimeoutError;
+
+ var foreach = Array.prototype.forEach;
+ var slice = Array.prototype.slice;
function Future(computation) {
+ var self = this;
Object.defineProperties(this, {
_subscribers: { value: [] },
resolve: { value: this.resolve.bind(this) },
- reject: { value: this.reject.bind(this) },
+ reject: { value: this.reject.bind(this) }
});
- var self = this;
if (typeof computation === 'function') {
setImmediate(function() {
try {
@@ -56,8 +57,12 @@
return obj instanceof Future;
}
+ function toFuture(obj) {
+ return isFuture(obj) ? obj : value(obj);
+ }
+
function isPromise(obj) {
- return isFuture(obj) || (hasPromise && (obj instanceof global.Promise) && (typeof (obj.then === 'function')));
+ return 'function' === typeof obj.then;
}
function delayed(duration, value) {
@@ -106,21 +111,19 @@
function arraysize(array) {
var size = 0;
- foreach(array, function() { ++size; });
+ foreach.call(array, function() { ++size; });
return size;
}
function all(array) {
- array = isPromise(array) ? array : value(array);
- return array.then(function(array) {
+ return toFuture(array).then(function(array) {
var n = array.length;
var count = arraysize(array);
var result = new Array(n);
- if (count === 0) return value(result);
+ if (count === 0) { return result; }
var future = new Future();
- foreach(array, function(element, index) {
- var f = (isPromise(element) ? element : value(element));
- f.then(function(value) {
+ foreach.call(array, function(element, index) {
+ toFuture(element).then(function(value) {
result[index] = value;
if (--count === 0) {
future.resolve(result);
@@ -137,20 +140,17 @@
}
function race(array) {
- array = isPromise(array) ? array : value(array);
- return array.then(function(array) {
+ return toFuture(array).then(function(array) {
var future = new Future();
- foreach(array, function(element) {
- var f = (isPromise(element) ? element : value(element));
- f.then(future.resolve, future.reject);
+ foreach.call(array, function(element) {
+ toFuture(element).fill(future);
});
return future;
});
}
function any(array) {
- array = isPromise(array) ? array : value(array);
- return array.then(function(array) {
+ return toFuture(array).then(function(array) {
var n = array.length;
var count = arraysize(array);
if (count === 0) {
@@ -158,9 +158,8 @@
}
var reasons = new Array(n);
var future = new Future();
- foreach(array, function(element, index) {
- var f = (isPromise(element) ? element : value(element));
- f.then(future.resolve, function(e) {
+ foreach.call(array, function(element, index) {
+ toFuture(element).then(future.resolve, function(e) {
reasons[index] = e;
if (--count === 0) {
future.reject(reasons);
@@ -172,16 +171,15 @@
}
function settle(array) {
- array = isPromise(array) ? array : value(array);
- return array.then(function(array) {
+ return toFuture(array).then(function(array) {
var n = array.length;
var count = arraysize(array);
var result = new Array(n);
- if (count === 0) return value(result);
+ if (count === 0) { return result; }
var future = new Future();
- foreach(array, function(element, index) {
- var f = (isPromise(element) ? element : value(element));
- f.whenComplete(function() {
+ foreach.call(array, function(element, index) {
+ var f = toFuture(element);
+ f.complete(function() {
result[index] = f.inspect();
if (--count === 0) {
future.resolve(result);
@@ -193,52 +191,212 @@
}
function attempt(handler/*, arg1, arg2, ... */) {
- var args = slice(arguments, 1);
+ var thisArg = (function() { return this; })();
+ var args = slice.call(arguments, 1);
return all(args).then(function(args) {
- return handler.apply(undefined, args);
+ return handler.apply(thisArg, args);
});
}
function run(handler, thisArg/*, arg1, arg2, ... */) {
- var args = slice(arguments, 2);
+ var args = slice.call(arguments, 2);
return all(args).then(function(args) {
return handler.apply(thisArg, args);
});
}
+ function isGenerator(obj) {
+ if (!obj) {
+ return false;
+ }
+ return 'function' == typeof obj.next && 'function' == typeof obj['throw'];
+ }
+
+ function isGeneratorFunction(obj) {
+ if (!obj) {
+ return false;
+ }
+ var constructor = obj.constructor;
+ if (!constructor) {
+ return false;
+ }
+ if ('GeneratorFunction' === constructor.name ||
+ 'GeneratorFunction' === constructor.displayName) {
+ return true;
+ }
+ return isGenerator(constructor.prototype);
+ }
+
+ function getThunkCallback(future) {
+ return function(err, res) {
+ if (err instanceof Error) {
+ return future.reject(err);
+ }
+ if (arguments.length < 2) {
+ return future.resolve(err);
+ }
+ if (err === null || err === undefined) {
+ res = slice.call(arguments, 1);
+ }
+ else {
+ res = slice.call(arguments, 0);
+ }
+ if (res.length == 1) {
+ future.resolve(res[0]);
+ }
+ else {
+ future.resolve(res);
+ }
+ };
+ }
+
+ function thunkToPromise(fn) {
+ if (isGeneratorFunction(fn) || isGenerator(fn)) {
+ return co(fn);
+ }
+ var thisArg = (function() { return this; })();
+ var future = new Future();
+ fn.call(thisArg, getThunkCallback(future));
+ return future;
+ }
+
+ function thunkify(fn) {
+ return function() {
+ var args = slice.call(arguments, 0);
+ var thisArg = this;
+ var results = new Future();
+ args.push(function() {
+ thisArg = this;
+ results.resolve(arguments);
+ });
+ try {
+ fn.apply(this, args);
+ }
+ catch (err) {
+ results.resolve([err]);
+ }
+ return function(done) {
+ results.then(function(results) {
+ done.apply(thisArg, results);
+ });
+ };
+ };
+ }
+
+ function promisify(fn) {
+ return function() {
+ var args = slice.call(arguments, 0);
+ var future = new Future();
+ args.push(getThunkCallback(future));
+ try {
+ fn.apply(this, args);
+ }
+ catch (err) {
+ future.reject(err);
+ }
+ return future;
+ };
+ }
+
+ function toPromise(obj) {
+ if (isGeneratorFunction(obj) || isGenerator(obj)) {
+ return co(obj);
+ }
+ return toFuture(obj);
+ }
+
+ function co(gen) {
+ var thisArg = (function() { return this; })();
+ if (typeof gen === 'function') {
+ var args = slice.call(arguments, 1);
+ gen = gen.apply(thisArg, args);
+ }
+
+ if (!gen || typeof gen.next !== 'function') {
+ return toFuture(gen);
+ }
+
+ var future = new Future();
+
+ function onFulfilled(res) {
+ try {
+ next(gen.next(res));
+ }
+ catch (e) {
+ future.reject(e);
+ }
+ }
+
+ function onRejected(err) {
+ try {
+ next(gen['throw'](err));
+ }
+ catch (e) {
+ future.reject(e);
+ }
+ }
+
+ function next(ret) {
+ if (ret.done) {
+ future.resolve(ret.value);
+ }
+ else {
+ (('function' == typeof ret.value) ?
+ thunkToPromise(ret.value) :
+ toPromise(ret.value)).then(onFulfilled, onRejected);
+ }
+ }
+
+ onFulfilled();
+
+ return future;
+ }
+
function wrap(handler, thisArg) {
return function() {
+ thisArg = thisArg || this;
return all(arguments).then(function(args) {
- return handler.apply(thisArg, args);
+ var result = handler.apply(thisArg, args);
+ if (isGeneratorFunction(result) || isGenerator(result)) {
+ return co.call(thisArg, result);
+ }
+ return result;
});
};
}
+ co.wrap = wrap;
+
function forEach(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
return all(array).then(function(array) {
return array.forEach(callback, thisArg);
});
}
function every(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
return all(array).then(function(array) {
return array.every(callback, thisArg);
});
}
function some(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
return all(array).then(function(array) {
return array.some(callback, thisArg);
});
}
function filter(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
return all(array).then(function(array) {
return array.filter(callback, thisArg);
});
}
function map(array, callback, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
return all(array).then(function(array) {
return array.map(callback, thisArg);
});
@@ -247,10 +405,7 @@
function reduce(array, callback, initialValue) {
if (arguments.length > 2) {
return all(array).then(function(array) {
- if (!isPromise(initialValue)) {
- initialValue = value(initialValue);
- }
- return initialValue.then(function(value) {
+ return toFuture(initialValue).then(function(value) {
return array.reduce(callback, value);
});
});
@@ -263,10 +418,7 @@
function reduceRight(array, callback, initialValue) {
if (arguments.length > 2) {
return all(array).then(function(array) {
- if (!isPromise(initialValue)) {
- initialValue = value(initialValue);
- }
- return initialValue.then(function(value) {
+ return toFuture(initialValue).then(function(value) {
return array.reduceRight(callback, value);
});
});
@@ -276,6 +428,47 @@
});
}
+ function indexOf(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ return array.indexOf(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function lastIndexOf(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ if (fromIndex === undefined) {
+ fromIndex = array.length - 1;
+ }
+ return array.lastIndexOf(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function includes(array, searchElement, fromIndex) {
+ return all(array).then(function(array) {
+ return toFuture(searchElement).then(function(searchElement) {
+ return array.includes(searchElement, fromIndex);
+ });
+ });
+ }
+
+ function find(array, predicate, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.find(predicate, thisArg);
+ });
+ }
+
+ function findIndex(array, predicate, thisArg) {
+ thisArg = thisArg || (function() { return this; })();
+ return all(array).then(function(array) {
+ return array.findIndex(predicate, thisArg);
+ });
+ }
+
Object.defineProperties(Future, {
// port from Dart
delayed: { value: delayed },
@@ -290,12 +483,17 @@
// extended methods
promise: { value: promise },
isFuture: { value: isFuture },
+ toFuture: { value: toFuture },
isPromise: { value: isPromise },
+ toPromise: { value: toPromise },
join: { value: join },
any: { value: any },
settle: { value: settle },
attempt: { value: attempt },
run: { value: run },
+ thunkify: { value: thunkify },
+ promisify: { value: promisify },
+ co: { value: co },
wrap: { value: wrap },
// for array
forEach: { value: forEach },
@@ -304,7 +502,12 @@
filter: { value: filter },
map: { value: map },
reduce: { value: reduce },
- reduceRight: { value: reduceRight }
+ reduceRight: { value: reduceRight },
+ indexOf: { value: indexOf },
+ lastIndexOf: { value: lastIndexOf },
+ includes: { value: includes },
+ find: { value: find },
+ findIndex: { value: findIndex }
});
function _call(callback, next, x) {
@@ -319,6 +522,15 @@
});
}
+ function _resolve(onfulfill, next, x) {
+ if (onfulfill) {
+ _call(onfulfill, next, x);
+ }
+ else {
+ next.resolve(x);
+ }
+ }
+
function _reject(onreject, next, e) {
if (onreject) {
_call(onreject, next, e);
@@ -328,82 +540,63 @@
}
}
-
- function _resolve(onfulfill, onreject, self, next, x) {
- function resolvePromise(y) {
- _resolve(onfulfill, onreject, self, next, y);
- }
- function rejectPromise(r) {
- _reject(onreject, next, r);
- }
- if (isPromise(x)) {
- if (x === self) {
- rejectPromise(new TypeError('Self resolution'));
+ Object.defineProperties(Future.prototype, {
+ _value: { writable: true },
+ _reason: { writable: true },
+ _state: { value: PENDING, writable: true },
+ resolve: { value: function(value) {
+ if (value === this) {
+ this.reject(new TypeError('Self resolution'));
return;
}
- x.then(resolvePromise, rejectPromise);
- return;
- }
- if ((x !== null) &&
- (typeof x === 'object') ||
- (typeof x === 'function')) {
- var then;
- try {
- then = x.then;
- }
- catch (e) {
- rejectPromise(e);
+ if (isFuture(value)) {
+ value.fill(this);
return;
}
- if (typeof then === 'function') {
- var notrun = true;
+ if ((value !== null) &&
+ (typeof value === 'object') ||
+ (typeof value === 'function')) {
+ var then;
try {
- then.call(x, function(y) {
- if (notrun) {
- notrun = false;
- resolvePromise(y);
- }
- }, function(r) {
+ then = value.then;
+ }
+ catch (e) {
+ this.reject(e);
+ return;
+ }
+ if (typeof then === 'function') {
+ var notrun = true;
+ try {
+ var self = this;
+ then.call(value, function(y) {
+ if (notrun) {
+ notrun = false;
+ self.resolve(y);
+ }
+ }, function(r) {
+ if (notrun) {
+ notrun = false;
+ self.reject(r);
+ }
+ });
+ return;
+ }
+ catch (e) {
if (notrun) {
notrun = false;
- rejectPromise(r);
+ this.reject(e);
}
- });
- return;
- }
- catch (e) {
- if (notrun) {
- notrun = false;
- rejectPromise(e);
}
+ return;
}
- return;
}
- }
- if (onfulfill) {
- _call(onfulfill, next, x);
- }
- else {
- next.resolve(x);
- }
- }
-
- Object.defineProperties(Future.prototype, {
- _value: { writable: true },
- _reason: { writable: true },
- _state: { value: PENDING, writable: true },
- resolve: { value: function(value) {
if (this._state === PENDING) {
this._state = FULFILLED;
this._value = value;
var subscribers = this._subscribers;
while (subscribers.length > 0) {
var subscriber = subscribers.shift();
- _resolve(subscriber.onfulfill,
- subscriber.onreject,
- this,
- subscriber.next,
- value);
+ _resolve(subscriber.onfulfill, subscriber.next, value);
}
}
} },
@@ -414,48 +607,33 @@
var subscribers = this._subscribers;
while (subscribers.length > 0) {
var subscriber = subscribers.shift();
- if (subscriber.onreject) {
- _call(subscriber.onreject,
- subscriber.next,
- reason);
- }
- else {
- subscriber.next.reject(reason);
- }
+ _reject(subscriber.onreject, subscriber.next, reason);
}
}
} },
then: { value: function(onfulfill, onreject) {
- if (typeof onfulfill !== 'function') onfulfill = null;
- if (typeof onreject !== 'function') onreject = null;
- if (onfulfill || onreject) {
- var next = new Future();
- if (this._state === FULFILLED) {
- if (onfulfill) {
- _resolve(onfulfill, onreject, this, next, this._value);
- }
- else {
- next.resolve(this._value);
- }
- }
- else if (this._state === REJECTED) {
- if (onreject) {
- _call(onreject, next, this._reason);
- }
- else {
- next.reject(this._reason);
- }
- }
- else {
- this._subscribers.push({
- onfulfill: onfulfill,
- onreject: onreject,
- next: next
- });
- }
- return next;
+ if (typeof onfulfill !== 'function') { onfulfill = null; }
+ if (typeof onreject !== 'function') { onreject = null; }
+ var next = new Future();
+ if (this._state === FULFILLED) {
+ _resolve(onfulfill, next, this._value);
}
- return this;
+ else if (this._state === REJECTED) {
+ _reject(onreject, next, this._reason);
+ }
+ else {
+ this._subscribers.push({
+ onfulfill: onfulfill,
+ onreject: onreject,
+ next: next
+ });
+ }
+ return next;
+ } },
+ done: { value: function(onfulfill, onreject) {
+ this.then(onfulfill, onreject).then(null, function(error) {
+ setImmediate(function() { throw error; });
+ });
} },
inspect: { value: function() {
switch (this._state) {
@@ -481,29 +659,32 @@
'catch': { value: function(onreject) {
return this.then(null, onreject);
} },
+ fail: { value: function(onreject) {
+ this.done(null, onreject);
+ } },
whenComplete: { value: function(action) {
return this.then(
- function(v) {
- var f = action();
- if (f === undefined) return v;
- f = isPromise(f) ? f : value(f);
- return f.then(function() { return v; });
- },
- function(e) {
- var f = action();
- if (f === undefined) throw e;
- f = isPromise(f) ? f : value(f);
- return f.then(function() { throw e; });
- }
+ function(v) { action(); return v; },
+ function(e) { action(); throw e; }
);
} },
+ complete: { value: function(oncomplete) {
+ oncomplete = oncomplete || function(v) { return v; };
+ return this.then(oncomplete, oncomplete);
+ } },
+ always: { value: function(oncomplete) {
+ this.done(oncomplete, oncomplete);
+ } },
+ fill: { value: function(future) {
+ this.then(future.resolve, future.reject);
+ } },
timeout: { value: function(duration, reason) {
var future = new Future();
var timeoutId = setTimeout(function() {
future.reject(reason || new TimeoutError('timeout'));
}, duration);
this.whenComplete(function() { clearTimeout(timeoutId); })
- .then(future.resolve, future.reject);
+ .fill(future);
return future;
} },
delay: { value: function(duration) {
@@ -547,7 +728,7 @@
});
} },
call: { value: function(method) {
- var args = slice(arguments, 1);
+ var args = slice.call(arguments, 1);
return this.then(function(result) {
return all(args).then(function(args) {
return result[method].apply(result, args);
@@ -555,7 +736,7 @@
});
} },
bind: { value: function(method) {
- var bindargs = slice(arguments);
+ var bindargs = slice.call(arguments);
if (Array.isArray(method)) {
for (var i = 0, n = method.length; i < n; ++i) {
bindargs[0] = method[i];
@@ -566,7 +747,7 @@
bindargs.shift();
var self = this;
Object.defineProperty(this, method, { value: function() {
- var args = slice(arguments);
+ var args = slice.call(arguments);
return self.then(function(result) {
return all(bindargs.concat(args)).then(function(args) {
return result[method].apply(result, args);
@@ -601,10 +782,30 @@
return reduceRight(this, callback, initialValue);
}
return reduceRight(this, callback);
+ } },
+ indexOf: { value: function(searchElement, fromIndex) {
+ return indexOf(this, searchElement, fromIndex);
+ } },
+ lastIndexOf: { value: function(searchElement, fromIndex) {
+ return lastIndexOf(this, searchElement, fromIndex);
+ } },
+ includes: { value: function(searchElement, fromIndex) {
+ return includes(this, searchElement, fromIndex);
+ } },
+ find: { value: function(predicate, thisArg) {
+ return find(this, predicate, thisArg);
+ } },
+ findIndex: { value: function(predicate, thisArg) {
+ return findIndex(this, predicate, thisArg);
} }
});
- global.hprose.Future = Future;
+ hprose.Future = Future;
+
+ hprose.thunkify = thunkify;
+ hprose.promisify = promisify;
+ hprose.co = co;
+ hprose.co.wrap = hprose.wrap = wrap;
function Completer() {
var future = new Future();
@@ -618,38 +819,38 @@
});
}
- global.hprose.Completer = Completer;
+ hprose.Completer = Completer;
- global.hprose.resolved = value;
+ hprose.resolved = value;
- global.hprose.rejected = error;
+ hprose.rejected = error;
- global.hprose.deferred = function() {
+ hprose.deferred = function() {
var self = new Future();
return Object.create(null, {
promise: { value: self },
resolve: { value: self.resolve },
- reject: { value: self.reject },
+ reject: { value: self.reject }
});
};
- if (hasPromise) return;
+ if (hasPromise) { return; }
- global.Promise = function(executor) {
+ function MyPromise(executor) {
Future.call(this);
executor(this.resolve, this.reject);
- };
+ }
- global.Promise.prototype = Object.create(Future.prototype);
- global.Promise.prototype.constructor = Future;
+ MyPromise.prototype = Object.create(Future.prototype);
+ MyPromise.prototype.constructor = Future;
- Object.defineProperties(global.Promise, {
+ Object.defineProperties(MyPromise, {
all: { value: all },
race: { value: race },
resolve: { value: value },
reject: { value: error }
});
-}(function() {
- return this || (1, eval)('this');
-}()));
+ global.Promise = MyPromise;
+
+})(hprose, hprose.global);
diff --git a/src/HarmonyMaps.js b/src/HarmonyMaps.js
index 8f7f51a..5be6667 100644
--- a/src/HarmonyMaps.js
+++ b/src/HarmonyMaps.js
@@ -13,12 +13,11 @@
* *
* Harmony Maps for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
(function (global) {
'use strict';
@@ -30,7 +29,7 @@
hasForEach = 'forEach' in new global.Map();
}
- if (hasWeakMap && hasMap && hasForEach) return;
+ if (hasWeakMap && hasMap && hasForEach) { return; }
var namespaces = Object.create(null);
var count = 0;
@@ -42,7 +41,9 @@
if ((this === obj) &&
(n in namespaces) &&
(namespaces[n] === namespace)) {
- if (!(n in privates)) privates[n] = Object.create(null);
+ if (!(n in privates)) {
+ privates[n] = Object.create(null);
+ }
return privates[n];
}
else {
@@ -61,9 +62,13 @@
var n = count++;
namespaces[n] = namespace;
var map = function (key) {
- if (key !== Object(key)) throw new Error('value is not a non-null object');
+ if (key !== Object(key)) {
+ throw new Error('value is not a non-null object');
+ }
var privates = key.valueOf(namespace, n);
- if (privates !== key.valueOf()) return privates;
+ if (privates !== key.valueOf()) {
+ return privates;
+ }
reDefineValueOf(key);
return key.valueOf(namespace, n);
};
@@ -113,9 +118,9 @@
var nullMap = Object.create(null);
namespaces[n] = namespace;
var map = function (key) {
- if (key === null) return nullMap;
+ if (key === null) { return nullMap; }
var privates = key.valueOf(namespace, n);
- if (privates !== key.valueOf()) return privates;
+ if (privates !== key.valueOf()) { return privates; }
reDefineValueOf(key);
return key.valueOf(namespace, n);
};
@@ -200,7 +205,7 @@
clear: {
value: function () {
keys.length = 0;
- for (var key in map) map[key].clear();
+ for (var key in map) { map[key].clear(); }
size = 0;
}
},
@@ -292,6 +297,4 @@
return m;
};
}
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose.global);
diff --git a/src/Helper.js b/src/Helper.js
new file mode 100644
index 0000000..8fcae53
--- /dev/null
+++ b/src/Helper.js
@@ -0,0 +1,114 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Helper.js *
+ * *
+ * hprose helper for HTML5. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, undefined) {
+ 'use strict';
+
+ function generic(method) {
+ if (typeof method !== "function") {
+ throw new TypeError(method + " is not a function");
+ }
+ return function(context) {
+ return method.apply(context, Array.prototype.slice.call(arguments, 1));
+ };
+ }
+
+ var arrayLikeObjectArgumentsEnabled = true;
+
+ try {
+ String.fromCharCode.apply(String, new Uint8Array([1]));
+ }
+ catch (e) {
+ arrayLikeObjectArgumentsEnabled = false;
+ }
+
+ function toArray(arrayLikeObject) {
+ var n = arrayLikeObject.length;
+ var a = new Array(n);
+ for (var i = 0; i < n; ++i) {
+ a[i] = arrayLikeObject[i];
+ }
+ return a;
+ }
+
+ var getCharCodes = arrayLikeObjectArgumentsEnabled ? function(bytes) { return bytes; } : toArray;
+
+ function toBinaryString(bytes) {
+ if (bytes instanceof ArrayBuffer) {
+ bytes = new Uint8Array(bytes);
+ }
+ var n = bytes.length;
+ if (n < 0xFFFF) {
+ return String.fromCharCode.apply(String, getCharCodes(bytes));
+ }
+ var remain = n & 0x7FFF;
+ var count = n >> 15;
+ var a = new Array(remain ? count + 1 : count);
+ for (var i = 0; i < count; ++i) {
+ a[i] = String.fromCharCode.apply(String, getCharCodes(bytes.subarray(i << 15, (i + 1) << 15)));
+ }
+ if (remain) {
+ a[count] = String.fromCharCode.apply(String, getCharCodes(bytes.subarray(count << 15, n)));
+ }
+ return a.join('');
+ }
+
+ function toUint8Array(bs) {
+ var n = bs.length;
+ var data = new Uint8Array(n);
+ for (var i = 0; i < n; i++) {
+ data[i] = bs.charCodeAt(i) & 0xFF;
+ }
+ return data;
+ }
+
+ var parseuri = function(url) {
+ var pattern = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
+ var matches = url.match(pattern);
+ var host = matches[4].split(':', 2);
+ return {
+ protocol: matches[1],
+ host: matches[4],
+ hostname: host[0],
+ port: parseInt(host[1], 10) || 0,
+ path: matches[5],
+ query: matches[7],
+ fragment: matches[9]
+ };
+ }
+
+ var isObjectEmpty = function (obj) {
+ if (obj) {
+ var prop;
+ for (prop in obj) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ hprose.generic = generic;
+ hprose.toBinaryString = toBinaryString;
+ hprose.toUint8Array = toUint8Array;
+ hprose.toArray = toArray;
+ hprose.parseuri = parseuri;
+ hprose.isObjectEmpty = isObjectEmpty;
+
+})(hprose);
diff --git a/src/HttpClient.js b/src/HttpClient.js
index cab1e0d..569deb1 100644
--- a/src/HttpClient.js
+++ b/src/HttpClient.js
@@ -12,22 +12,57 @@
* *
* hprose http client for HTML5. *
* *
- * LastModified: Aug 2, 2015 *
+ * LastModified: Dec 2, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, global, undefined) {
'use strict';
- var Client = global.hprose.Client;
- var Future = global.hprose.Future;
+ var Client = hprose.Client;
+ var Future = hprose.Future;
+ var BytesIO = hprose.BytesIO;
+ var TimeoutError = global.TimeoutError;
+ var localfile = (global.location !== undefined && global.location.protocol === 'file:');
+ var XMLHttpRequest = global.XMLHttpRequest;
+ var nativeXHR = (typeof(XMLHttpRequest) !== 'undefined');
+ var corsSupport = (!localfile && nativeXHR && 'withCredentials' in new XMLHttpRequest());
+ var parseuri = hprose.parseuri;
+ var cookieManager = hprose.cookieManager;
function noop(){}
+ function getResponseHeader(headers) {
+ var header = Object.create(null);
+ if (headers) {
+ headers = headers.split("\r\n");
+ for (var i = 0, n = headers.length; i < n; i++) {
+ if (headers[i] !== "") {
+ var kv = headers[i].split(": ", 2);
+ var k = kv[0].trim();
+ var v = kv[1].trim();
+ if (k in header) {
+ if (Array.isArray(header[k])) {
+ header[k].push(v);
+ }
+ else {
+ header[k] = [header[k], v];
+ }
+ }
+ else {
+ header[k] = v;
+ }
+ }
+ }
+ }
+ return header;
+ }
+
function HttpClient(uri, functions, settings) {
- if (this.constructor !== HttpClient) return new HttpClient(uri, functions, settings);
+ if (this.constructor !== HttpClient) {
+ return new HttpClient(uri, functions, settings);
+ }
Client.call(this, uri, functions, settings);
var _header = Object.create(null);
var _onreqprogress = noop;
@@ -35,19 +70,43 @@
var self = this;
- function send(request, future) {
+ function getRequestHeader(headers) {
+ var header = Object.create(null);
+ var name, value;
+ for (name in _header) {
+ header[name] = _header[name];
+ }
+ if (headers) {
+ for (name in headers) {
+ value = headers[name];
+ if (Array.isArray(value)) {
+ header[name] = value.join(', ');
+ }
+ else {
+ header[name] = value;
+ }
+ }
+ }
+ return header;
+ }
+
+ function xhrPost(request, context) {
+ var future = new Future();
var xhr = new XMLHttpRequest();
xhr.open('POST', self.uri, true);
- if (global.location !== undefined && global.location.protocol !== 'file:') {
+ if (corsSupport) {
xhr.withCredentials = 'true';
}
xhr.responseType = 'arraybuffer';
- for (var name in _header) {
- xhr.setRequestHeader(name, _header[name]);
+ var header = getRequestHeader(context.httpHeader);
+ for (var name in header) {
+ xhr.setRequestHeader(name, header[name]);
}
xhr.onload = function() {
xhr.onload = noop;
if (xhr.status) {
+ var headers = xhr.getAllResponseHeaders();
+ context.httpHeader = getResponseHeader(headers);
if (xhr.status === 200) {
future.resolve(new Uint8Array(xhr.response));
}
@@ -63,6 +122,17 @@
xhr.upload.onprogress = _onreqprogress;
}
xhr.onprogress = _onresprogress;
+ if (context.timeout > 0) {
+ future = future.timeout(context.timeout).catchError(function(e) {
+ xhr.onload = noop;
+ xhr.onerror = noop;
+ xhr.abort();
+ throw e;
+ },
+ function(e) {
+ return e instanceof TimeoutError;
+ });
+ }
if (request.constructor === String || ArrayBuffer.isView) {
xhr.send(request);
}
@@ -70,28 +140,56 @@
xhr.send(request.buffer.slice(0, request.length));
}
else {
- xhr.send(request.buffer);
+ var buf = new Uint8Array(request.length);
+ buf.set(request);
+ xhr.send(buf.buffer);
}
- return xhr;
+ return future;
}
- function sendAndReceive(request, env) {
+ function apiPost(request, context) {
var future = new Future();
- var xhr = send(request, future);
- if (env.timeout > 0) {
- future = future.timeout(env.timeout).catchError(function(e) {
- xhr.onload = noop;
- xhr.onerror = noop;
- xhr.abort();
- throw e;
- },
- function(e) {
- return e instanceof TimeoutError;
- });
+ var header = getRequestHeader(context.httpHeader);
+ var cookie = cookieManager.getCookie(self.uri());
+ if (cookie !== '') {
+ header['Cookie'] = cookie;
}
- if (env.oneway) future.resolve();
+ global.api.ajax({
+ url: self.uri,
+ method: 'post',
+ data: { body: BytesIO.toString(request) },
+ timeout: context.timeout,
+ dataType: 'text',
+ headers: header,
+ returnAll: true,
+ certificate: self.certificate
+ }, function(ret, err) {
+ if (ret) {
+ context.httpHeader = ret.headers;
+ if (ret.statusCode === 200) {
+ cookieManager.setCookie(ret.headers, self.uri);
+ future.resolve((new BytesIO(ret.body)).takeBytes());
+ }
+ else {
+ future.reject(new Error(ret.statusCode+':'+ret.body));
+ }
+ }
+ else {
+ future.reject(new Error(err.msg));
+ }
+ });
return future;
}
+
+ function sendAndReceive(request, context) {
+ var apicloud = (typeof(global.api) !== "undefined" &&
+ typeof(global.api.ajax) !== "undefined");
+ var future = apicloud ? apiPost(request, context) :
+ xhrPost(request, context);
+ if (context.oneway) { future.resolve(); }
+ return future;
+ }
+
function setOnRequestProgress(value) {
if (typeof(value) === 'function') {
_onreqprogress = value;
@@ -120,7 +218,6 @@
}
}
Object.defineProperties(this, {
- onProgress: { get: getOnRequestProgress, set: setOnRequestProgress },
onprogress: { get: getOnRequestProgress, set: setOnRequestProgress },
onRequestProgress: { get: getOnRequestProgress, set: setOnRequestProgress },
onResponseProgress: { get: getOnResponseProgress, set: setOnResponseProgress },
@@ -130,8 +227,7 @@
}
function checkuri(uri) {
- var parser = document.createElement('a');
- parser.href = uri;
+ var parser = parseuri(uri);
if (parser.protocol === 'http:' ||
parser.protocol === 'https:') {
return;
@@ -147,15 +243,13 @@
uri.forEach(function(uri) { checkuri(uri); });
}
else {
- return new Error('You should set server uri first!');
+ throw new Error('You should set server uri first!');
}
return new HttpClient(uri, functions, settings);
}
Object.defineProperty(HttpClient, 'create', { value: create });
- global.hprose.HttpClient = HttpClient;
+ hprose.HttpClient = HttpClient;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose, hprose.global);
diff --git a/src/Init.js b/src/Init.js
index 3ffcd27..7055d01 100644
--- a/src/Init.js
+++ b/src/Init.js
@@ -13,17 +13,19 @@
* *
* hprose init for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
- 'use strict';
+var hprose = Object.create(null);
- global.hprose = Object.create(null);
-
-}(function() {
- return this || (1, eval)('this');
-}()));
+/* global global, window, self */
+hprose.global = (
+ // Among the various tricks for obtaining a reference to the global
+ // object, this seems to be the most reliable technique that does not
+ // use indirect eval (which violates Content Security Policy).
+ typeof global === "object" ? global :
+ typeof window === "object" ? window :
+ typeof self === "object" ? self : this
+);
diff --git a/src/JSONRPCClientFilter.js b/src/JSONRPCClientFilter.js
index da3f7c0..28a85fd 100644
--- a/src/JSONRPCClientFilter.js
+++ b/src/JSONRPCClientFilter.js
@@ -13,19 +13,19 @@
* *
* jsonrpc client filter for JavaScript. *
* *
- * LastModified: Jul 17, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+/* global JSON */
+(function (hprose) {
'use strict';
- var Tags = global.hprose.Tags;
- var BytesIO = global.hprose.BytesIO;
- var Writer = global.hprose.Writer;
- var Reader = global.hprose.Reader;
+ var Tags = hprose.Tags;
+ var BytesIO = hprose.BytesIO;
+ var Writer = hprose.Writer;
+ var Reader = hprose.Reader;
var s_id = 1;
@@ -33,7 +33,7 @@
this.version = version || '2.0';
}
- JSONRPCClientFilter.prototype.inputFilter = function inputFilter(data, context) {
+ JSONRPCClientFilter.prototype.inputFilter = function inputFilter(data/*, context*/) {
var json = BytesIO.toString(data);
if (json.charAt(0) === '{') {
json = '[' + json + ']';
@@ -56,7 +56,7 @@
return stream.bytes;
};
- JSONRPCClientFilter.prototype.outputFilter = function outputFilter(data, context) {
+ JSONRPCClientFilter.prototype.outputFilter = function outputFilter(data/*, context*/) {
var requests = [];
var stream = new BytesIO(data);
var reader = new Reader(stream, false, false);
@@ -89,8 +89,6 @@
return JSON.stringify(requests[0]);
};
- global.hprose.JSONRPCClientFilter = JSONRPCClientFilter;
+ hprose.JSONRPCClientFilter = JSONRPCClientFilter;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/Loader.js b/src/Loader.js
index b0cfcf8..3e2bdf5 100644
--- a/src/Loader.js
+++ b/src/Loader.js
@@ -13,52 +13,51 @@
* *
* hprose CommonJS/AMD/CMD loader for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+/* global define, module */
+(function (hprose) {
'use strict';
- global.hprose.common = {
- Completer: global.hprose.Completer,
- Future: global.hprose.Future,
- ResultMode: global.hprose.ResultMode
+ hprose.common = {
+ Completer: hprose.Completer,
+ Future: hprose.Future,
+ ResultMode: hprose.ResultMode
};
- global.hprose.io = {
- BytesIO: global.hprose.BytesIO,
- ClassManager: global.hprose.ClassManager,
- Tags: global.hprose.Tags,
- RawReader: global.hprose.RawReader,
- Reader: global.hprose.Reader,
- Writer: global.hprose.Writer,
- Formatter: global.hprose.Formatter
+ hprose.io = {
+ BytesIO: hprose.BytesIO,
+ ClassManager: hprose.ClassManager,
+ Tags: hprose.Tags,
+ RawReader: hprose.RawReader,
+ Reader: hprose.Reader,
+ Writer: hprose.Writer,
+ Formatter: hprose.Formatter
};
- global.hprose.client = {
- Client: global.hprose.Client,
- HttpClient: global.hprose.HttpClient,
- WebSocketClient: global.hprose.WebSocketClient
+ hprose.client = {
+ Client: hprose.Client,
+ HttpClient: hprose.HttpClient,
+ TcpClient: hprose.TcpClient,
+ WebSocketClient: hprose.WebSocketClient
};
- global.hprose.filter = {
- JSONRPCClientFilter: global.hprose.JSONRPCClientFilter
+ hprose.filter = {
+ JSONRPCClientFilter: hprose.JSONRPCClientFilter
};
if (typeof define === 'function') {
if (define.cmd) {
- define('hprose', [], global.hprose);
+ define('hprose', [], hprose);
}
else if (define.amd) {
- define('hprose', [], function() { return global.hprose; });
+ define('hprose', [], function() { return hprose; });
}
}
- if (typeof module === 'object' && typeof module.exports === 'object') {
- module.exports = global.hprose;
+ if (typeof module === 'object') {
+ module.exports = hprose;
}
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/Polyfill.js b/src/Polyfill.js
new file mode 100644
index 0000000..8c4a989
--- /dev/null
+++ b/src/Polyfill.js
@@ -0,0 +1,414 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+
+/**********************************************************\
+ * *
+ * Polyfill.js *
+ * *
+ * Polyfill for JavaScript. *
+ * *
+ * LastModified: Nov 18, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (generic, undefined) {
+ 'use strict';
+ /* Function */
+ if (!Function.prototype.bind) {
+ Object.defineProperty(Function.prototype, 'bind', { value: function(oThis) {
+ if (typeof this !== 'function') {
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ toBind = this,
+ NOP = function() {},
+ bound = function() {
+ return toBind.apply(this instanceof NOP ? this : oThis,
+ aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+ if (this.prototype) {
+ NOP.prototype = this.prototype;
+ }
+ bound.prototype = new NOP();
+ return bound;
+ } });
+ }
+ /* Array */
+ if (!Array.prototype.includes) {
+ Object.defineProperty(Array.prototype, 'includes', { value: function(searchElement /*, fromIndex*/ ) {
+ var O = Object(this);
+ var len = parseInt(O.length, 10) || 0;
+ if (len === 0) {
+ return false;
+ }
+ var n = parseInt(arguments[1], 10) || 0;
+ var k;
+ if (n >= 0) {
+ k = n;
+ }
+ else {
+ k = len + n;
+ if (k < 0) { k = 0; }
+ }
+ var currentElement;
+ while (k < len) {
+ currentElement = O[k];
+ if (searchElement === currentElement ||
+ (searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN
+ return true;
+ }
+ k++;
+ }
+ return false;
+ } });
+ }
+ if (!Array.prototype.find) {
+ Object.defineProperty(Array.prototype, 'find', { value: function(predicate) {
+ if (this === null || this === undefined) {
+ throw new TypeError('Array.prototype.find called on null or undefined');
+ }
+ if (typeof predicate !== 'function') {
+ throw new TypeError('predicate must be a function');
+ }
+ var list = Object(this);
+ var length = list.length >>> 0;
+ var thisArg = arguments[1];
+ var value;
+ for (var i = 0; i < length; i++) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) {
+ return value;
+ }
+ }
+ return undefined;
+ } });
+ }
+ if (!Array.prototype.findIndex) {
+ Object.defineProperty(Array.prototype, 'findIndex', { value: function(predicate) {
+ if (this === null || this === undefined) {
+ throw new TypeError('Array.prototype.findIndex called on null or undefined');
+ }
+ if (typeof predicate !== 'function') {
+ throw new TypeError('predicate must be a function');
+ }
+ var list = Object(this);
+ var length = list.length >>> 0;
+ var thisArg = arguments[1];
+ var value;
+
+ for (var i = 0; i < length; i++) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) {
+ return i;
+ }
+ }
+ return -1;
+ } });
+ }
+ if (!Array.prototype.fill) {
+ Object.defineProperty(Array.prototype, 'fill', { value: function(value) {
+ if (this === null || this === undefined) {
+ throw new TypeError('this is null or not defined');
+ }
+ var O = Object(this);
+ var len = O.length >>> 0;
+ var start = arguments[1];
+ var relativeStart = start >> 0;
+ var k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
+ var end = arguments[2];
+ var relativeEnd = end === undefined ? len : end >> 0;
+ var f = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
+
+ while (k < f) {
+ O[k] = value;
+ k++;
+ }
+ return O;
+ } });
+ }
+ if (!Array.prototype.copyWithin) {
+ Object.defineProperty(Array.prototype, 'copyWithin', { value: function(target, start/*, end*/) {
+ if (this === null || this === undefined) {
+ throw new TypeError('this is null or not defined');
+ }
+ var O = Object(this);
+ var len = O.length >>> 0;
+ var relativeTarget = target >> 0;
+ var to = relativeTarget < 0 ? Math.max(len + relativeTarget, 0) : Math.min(relativeTarget, len);
+ var relativeStart = start >> 0;
+ var from = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
+ var end = arguments[2];
+ var relativeEnd = end === undefined ? len : end >> 0;
+ var f = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
+ var count = Math.min(f - from, len - to);
+ var direction = 1;
+ if (from < to && to < (from + count)) {
+ direction = -1;
+ from += count - 1;
+ to += count - 1;
+ }
+ while (count > 0) {
+ if (from in O) {
+ O[to] = O[from];
+ }
+ else {
+ delete O[to];
+ }
+ from += direction;
+ to += direction;
+ count--;
+ }
+ return O;
+ } });
+ }
+ if (!Array.from) {
+ Object.defineProperty(Array, 'from', { value: (function() {
+ var toStr = Object.prototype.toString;
+ var isCallable = function(fn) {
+ return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
+ };
+ var toInteger = function(value) {
+ var number = Number(value);
+ if (isNaN(number)) { return 0; }
+ if (number === 0 || !isFinite(number)) { return number; }
+ return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
+ };
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+ var toLength = function(value) {
+ var len = toInteger(value);
+ return Math.min(Math.max(len, 0), maxSafeInteger);
+ };
+
+ return function(arrayLike/*, mapFn, thisArg */) {
+ var C = this;
+ var items = Object(arrayLike);
+ if (arrayLike === null || arrayLike === undefined) {
+ throw new TypeError("Array.from requires an array-like object - not null or undefined");
+ }
+ var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
+ var T;
+ if (typeof mapFn !== 'undefined') {
+ if (!isCallable(mapFn)) {
+ throw new TypeError('Array.from: when provided, the second argument must be a function');
+ }
+ if (arguments.length > 2) {
+ T = arguments[2];
+ }
+ }
+ var len = toLength(items.length);
+ var A = isCallable(C) ? Object(new C(len)) : new Array(len);
+ var k = 0;
+ var kValue;
+ while (k < len) {
+ kValue = items[k];
+ if (mapFn) {
+ A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
+ }
+ else {
+ A[k] = kValue;
+ }
+ k += 1;
+ }
+ A.length = len;
+ return A;
+ };
+ }()) });
+ }
+ if (!Array.of) {
+ Object.defineProperty(Array, 'of', { value: function() {
+ return Array.prototype.slice.call(arguments);
+ } });
+ }
+ /* String */
+ if (!String.prototype.startsWith) {
+ Object.defineProperty(String.prototype, 'startsWith', { value: function(searchString, position){
+ position = position || 0;
+ return this.substr(position, searchString.length) === searchString;
+ } });
+ }
+ if (!String.prototype.endsWith) {
+ Object.defineProperty(String.prototype, 'endsWith', { value: function(searchString, position) {
+ var subjectString = this.toString();
+ if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
+ position = subjectString.length;
+ }
+ position -= searchString.length;
+ var lastIndex = subjectString.indexOf(searchString, position);
+ return lastIndex !== -1 && lastIndex === position;
+ } });
+ }
+ if (!String.prototype.includes) {
+ Object.defineProperty(String.prototype, 'includes', { value: function() {
+ if (typeof arguments[1] === "number") {
+ if (this.length < arguments[0].length + arguments[1].length) {
+ return false;
+ }
+ else {
+ return this.substr(arguments[1], arguments[0].length) === arguments[0];
+ }
+ }
+ else {
+ return String.prototype.indexOf.apply(this, arguments) !== -1;
+ }
+ } });
+ }
+ if (!String.prototype.repeat) {
+ Object.defineProperty(String.prototype, 'repeat', { value: function(count) {
+ var str = this.toString();
+ count = +count;
+ if (count !== count) {
+ count = 0;
+ }
+ if (count < 0) {
+ throw new RangeError('repeat count must be non-negative');
+ }
+ if (count === Infinity) {
+ throw new RangeError('repeat count must be less than infinity');
+ }
+ count = Math.floor(count);
+ if (str.length === 0 || count === 0) {
+ return '';
+ }
+ // Ensuring count is a 31-bit integer allows us to heavily optimize the
+ // main part. But anyway, most current (August 2014) browsers can't handle
+ // strings 1 << 28 chars or longer, so:
+ if (str.length * count >= 1 << 28) {
+ throw new RangeError('repeat count must not overflow maximum string size');
+ }
+ var rpt = '';
+ for (;;) {
+ if ((count & 1) === 1) {
+ rpt += str;
+ }
+ count >>>= 1;
+ if (count === 0) {
+ break;
+ }
+ str += str;
+ }
+ // Could we try:
+ // return Array(count + 1).join(this);
+ return rpt;
+ } });
+ }
+ if (!String.prototype.trim) {
+ Object.defineProperty(String.prototype, 'trim', { value: function() {
+ return this.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
+ } });
+ }
+ if (!String.prototype.trimLeft) {
+ Object.defineProperty(String.prototype, 'trimLeft', { value: function() {
+ return this.toString().replace(/^[\s\xa0]+/, '');
+ } });
+ }
+ if (!String.prototype.trimRight) {
+ Object.defineProperty(String.prototype, 'trimRight', { value: function() {
+ return this.toString().replace(/[\s\xa0]+$/, '');
+ } });
+ }
+ /* Object */
+ if (!Object.keys) {
+ Object.defineProperty(Object, 'keys', { value: (function () {
+ var hasOwnProperty = Object.prototype.hasOwnProperty,
+ hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
+ dontEnums = [
+ 'toString',
+ 'toLocaleString',
+ 'valueOf',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor'
+ ],
+ dontEnumsLength = dontEnums.length;
+ return function (obj) {
+ if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) {
+ throw new TypeError('Object.keys called on non-object');
+ }
+ var result = [];
+ for (var prop in obj) {
+ if (hasOwnProperty.call(obj, prop)) {
+ result.push(prop);
+ }
+ }
+ if (hasDontEnumBug) {
+ for (var i=0; i < dontEnumsLength; i++) {
+ if (hasOwnProperty.call(obj, dontEnums[i])) {
+ result.push(dontEnums[i]);
+ }
+ }
+ }
+ return result;
+ };
+ })() });
+ }
+
+ function genericMethods(obj, properties) {
+ var proto = obj.prototype;
+ for (var i = 0, len = properties.length; i < len; i++) {
+ var property = properties[i];
+ var method = proto[property];
+ if (typeof method === 'function' && typeof obj[property] === 'undefined') {
+ Object.defineProperty(obj, property, { value: generic(method) });
+ }
+ }
+ }
+ genericMethods(Array, [
+ "pop",
+ "push",
+ "reverse",
+ "shift",
+ "sort",
+ "splice",
+ "unshift",
+ "concat",
+ "join",
+ "slice",
+ "indexOf",
+ "lastIndexOf",
+ "filter",
+ "forEach",
+ "every",
+ "map",
+ "some",
+ "reduce",
+ "reduceRight",
+ "includes",
+ "find",
+ "findIndex"
+ ]);
+ genericMethods(String, [
+ 'quote',
+ 'substring',
+ 'toLowerCase',
+ 'toUpperCase',
+ 'charAt',
+ 'charCodeAt',
+ 'indexOf',
+ 'lastIndexOf',
+ 'include',
+ 'startsWith',
+ 'endsWith',
+ 'repeat',
+ 'trim',
+ 'trimLeft',
+ 'trimRight',
+ 'toLocaleLowerCase',
+ 'toLocaleUpperCase',
+ 'match',
+ 'search',
+ 'replace',
+ 'split',
+ 'substr',
+ 'concat',
+ 'slice'
+ ]);
+
+})(hprose.generic);
diff --git a/src/Reader.js b/src/Reader.js
index 22de239..4ff8e05 100644
--- a/src/Reader.js
+++ b/src/Reader.js
@@ -13,19 +13,18 @@
* *
* hprose Reader for HTML5. *
* *
- * LastModified: Aug 3, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, global, undefined) {
'use strict';
var Map = global.Map;
- var BytesIO = global.hprose.BytesIO;
- var Tags = global.hprose.Tags;
- var ClassManager = global.hprose.ClassManager;
+ var BytesIO = hprose.BytesIO;
+ var Tags = hprose.Tags;
+ var ClassManager = hprose.ClassManager;
function unexpectedTag(tag, expectTags) {
if (tag && expectTags) {
@@ -177,7 +176,7 @@
});
}
- global.hprose.RawReader = RawReader;
+ hprose.RawReader = RawReader;
var fakeReaderRefer = Object.create(null, {
set: { value: function() {} },
@@ -270,7 +269,7 @@
function readInt(stream, tag) {
var s = stream.readUntil(tag);
- if (s.length === 0) return 0;
+ if (s.length === 0) { return 0; }
return parseInt(s, 10);
}
function unserialize(reader) {
@@ -334,7 +333,7 @@
function readLongWithoutTag(stream) {
var s = stream.readUntil(Tags.TagSemicolon);
var l = parseInt(s, 10);
- if (l.toString() === s) return l;
+ if (l.toString() === s) { return l; }
return s;
}
function readLong(stream) {
@@ -658,12 +657,12 @@
Object.defineProperties(Reader.prototype, {
useHarmonyMap: { value: false, writable: true },
checkTag: { value: function(expectTag, tag) {
- if (tag === undefined) tag = this.stream.readByte();
- if (tag !== expectTag) unexpectedTag(tag, expectTag);
+ if (tag === undefined) { tag = this.stream.readByte(); }
+ if (tag !== expectTag) { unexpectedTag(tag, expectTag); }
} },
checkTags: { value: function(expectTags, tag) {
- if (tag === undefined) tag = this.stream.readByte();
- if (expectTags.indexOf(tag) >= 0) return tag;
+ if (tag === undefined) { tag = this.stream.readByte(); }
+ if (expectTags.indexOf(tag) >= 0) { return tag; }
unexpectedTag(tag, expectTags);
} },
unserialize: { value: function() {
@@ -739,7 +738,5 @@
} }
});
- global.hprose.Reader = Reader;
-}(function() {
- return this || (1, eval)('this');
-}()));
+ hprose.Reader = Reader;
+})(hprose, hprose.global);
diff --git a/src/ResultMode.js b/src/ResultMode.js
index f4fd380..01d3e1e 100644
--- a/src/ResultMode.js
+++ b/src/ResultMode.js
@@ -13,26 +13,23 @@
* *
* hprose ResultMode for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+(function (hprose) {
'use strict';
- global.hprose.ResultMode = {
+ hprose.ResultMode = {
Normal: 0,
Serialized: 1,
Raw: 2,
RawWithEndTag: 3
};
- global.hprose.Normal = global.hprose.ResultMode.Normal;
- global.hprose.Serialized = global.hprose.ResultMode.Serialized;
- global.hprose.Raw = global.hprose.ResultMode.Raw;
- global.hprose.RawWithEndTag = global.hprose.ResultMode.RawWithEndTag;
+ hprose.Normal = hprose.ResultMode.Normal;
+ hprose.Serialized = hprose.ResultMode.Serialized;
+ hprose.Raw = hprose.ResultMode.Raw;
+ hprose.RawWithEndTag = hprose.ResultMode.RawWithEndTag;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/Tags.js b/src/Tags.js
index c972dc9..66b85d5 100644
--- a/src/Tags.js
+++ b/src/Tags.js
@@ -12,16 +12,15 @@
* *
* hprose tags enum for HTML5. *
* *
- * LastModified: Jul 15, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global) {
+(function (hprose) {
'use strict';
- global.hprose.Tags = {
+ hprose.Tags = {
/* Serialize Tags */
TagInteger : 0x69, // 'i'
TagLong : 0x6C, // 'l'
@@ -60,6 +59,4 @@
TagError : 0x45, // 'E'
TagEnd : 0x7A // 'z'
};
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose);
diff --git a/src/TcpClient.js b/src/TcpClient.js
new file mode 100644
index 0000000..964a4e8
--- /dev/null
+++ b/src/TcpClient.js
@@ -0,0 +1,470 @@
+/**********************************************************\
+| |
+| hprose |
+| |
+| Official WebSite: http://www.hprose.com/ |
+| http://www.hprose.org/ |
+| |
+\**********************************************************/
+/**********************************************************\
+ * *
+ * TcpClient.js *
+ * *
+ * hprose tcp client for HTML5. *
+ * *
+ * LastModified: Dec 2, 2016 *
+ * Author: Ma Bingyao *
+ * *
+\**********************************************************/
+
+(function (hprose, global, undefined) {
+ 'use strict';
+
+ var ChromeTcpSocket = hprose.ChromeTcpSocket;
+ var APICloudTcpSocket = hprose.APICloudTcpSocket;
+ var Client = hprose.Client;
+ var BytesIO = hprose.BytesIO;
+ var Future = hprose.Future;
+ var TimeoutError = global.TimeoutError;
+ var parseuri = hprose.parseuri;
+
+ function noop(){}
+
+ function setReceiveHandler(socket, onreceive) {
+ socket.onreceive = function(data) {
+ if (!('receiveEntry' in socket)) {
+ socket.receiveEntry = {
+ stream: new BytesIO(),
+ headerLength: 4,
+ dataLength: -1,
+ id: null
+ };
+ }
+ var entry = socket.receiveEntry;
+ var stream = entry.stream;
+ var headerLength = entry.headerLength;
+ var dataLength = entry.dataLength;
+ var id = entry.id;
+ stream.write(data);
+ while (true) {
+ if ((dataLength < 0) && (stream.length >= headerLength)) {
+ dataLength = stream.readInt32BE();
+ if ((dataLength & 0x80000000) !== 0) {
+ dataLength &= 0x7fffffff;
+ headerLength = 8;
+ }
+ }
+ if ((headerLength === 8) && (id === null) && (stream.length >= headerLength)) {
+ id = stream.readInt32BE();
+ }
+ if ((dataLength >= 0) && ((stream.length - headerLength) >= dataLength)) {
+ onreceive(stream.read(dataLength), id);
+ headerLength = 4;
+ id = null;
+ stream.trunc();
+ dataLength = -1;
+ }
+ else {
+ break;
+ }
+ }
+ entry.stream = stream;
+ entry.headerLength = headerLength;
+ entry.dataLength = dataLength;
+ entry.id = id;
+ };
+ }
+
+ function TcpTransporter(client) {
+ if (client) {
+ this.client = client;
+ this.uri = this.client.uri;
+ this.size = 0;
+ this.pool = [];
+ this.requests = [];
+ }
+ }
+
+ Object.defineProperties(TcpTransporter.prototype, {
+ create: { value: function() {
+ var parser = parseuri(this.uri);
+ var protocol = parser.protocol;
+ var address = parser.hostname;
+ var port = parseInt(parser.port, 10);
+ var tls;
+ if (protocol === 'tcp:' ||
+ protocol === 'tcp4:' ||
+ protocol === 'tcp6:') {
+ tls = false;
+ }
+ else if (protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:') {
+ tls = true;
+ }
+ else {
+ throw new Error('Unsupported ' + protocol + ' protocol!');
+ }
+ var conn;
+ if (global.chrome && global.chrome.sockets && global.chrome.sockets.tcp) {
+ conn = new ChromeTcpSocket();
+ }
+ else if (global.api && global.api.require) {
+ conn = new APICloudTcpSocket();
+ }
+ else {
+ throw new Error('TCP Socket is not supported by this browser or platform.');
+ }
+ var self = this;
+ conn.connect(address, port, {
+ persistent: true,
+ tls: tls,
+ timeout: this.client.timeout,
+ noDelay: this.client.noDelay,
+ keepAlive: this.client.keepAlive
+ });
+ conn.onclose = function() { --self.size; };
+ ++this.size;
+ return conn;
+ } }
+ });
+
+ function FullDuplexTcpTransporter(client) {
+ TcpTransporter.call(this, client);
+ }
+
+ FullDuplexTcpTransporter.prototype = Object.create(
+ TcpTransporter.prototype, {
+ fetch: { value: function() {
+ var pool = this.pool;
+ while (pool.length > 0) {
+ var conn = pool.pop();
+ if (conn.connected) {
+ if (conn.count === 0) {
+ conn.clearTimeout();
+ conn.ref();
+ }
+ return conn;
+ }
+ }
+ return null;
+ } },
+ init: { value: function(conn) {
+ var self = this;
+ conn.count = 0;
+ conn.futures = {};
+ conn.timeoutIds = {};
+ setReceiveHandler(conn, function(data, id) {
+ var future = conn.futures[id];
+ if (future) {
+ self.clean(conn, id);
+ if (conn.count === 0) {
+ self.recycle(conn);
+ }
+ future.resolve(data);
+ }
+ });
+ conn.onerror = function (e) {
+ var futures = conn.futures;
+ for (var id in futures) {
+ var future = futures[id];
+ self.clean(conn, id);
+ future.reject(e);
+ }
+ };
+ } },
+ recycle: { value: function(conn) {
+ conn.unref();
+ conn.setTimeout(this.client.poolTimeout, function() {
+ conn.destroy();
+ });
+ } },
+ clean: { value: function(conn, id) {
+ if (conn.timeoutIds[id] !== undefined) {
+ global.clearTimeout(conn.timeoutIds[id]);
+ delete conn.timeoutIds[id];
+ }
+ delete conn.futures[id];
+ --conn.count;
+ this.sendNext(conn);
+ } },
+ sendNext: { value: function(conn) {
+ if (conn.count < 10) {
+ if (this.requests.length > 0) {
+ var request = this.requests.pop();
+ request.push(conn);
+ this.send.apply(this, request);
+ }
+ else {
+ if (this.pool.lastIndexOf(conn) < 0) {
+ this.pool.push(conn);
+ }
+ }
+ }
+ } },
+ send: { value: function(request, future, id, context, conn) {
+ var self = this;
+ var timeout = context.timeout;
+ if (timeout > 0) {
+ conn.timeoutIds[id] = global.setTimeout(function() {
+ self.clean(conn, id);
+ if (conn.count === 0) {
+ self.recycle(conn);
+ }
+ future.reject(new TimeoutError('timeout'));
+ }, timeout);
+ }
+ conn.count++;
+ conn.futures[id] = future;
+
+ var len = request.length;
+ var buf = new BytesIO(8 + len);
+ buf.writeInt32BE(len | 0x80000000);
+ buf.writeInt32BE(id);
+ buf.write(request);
+ conn.send(buf.buffer).then(function() {
+ self.sendNext(conn);
+ });
+ } },
+ getNextId: { value: function() {
+ return (this.nextid < 0x7fffffff) ? ++this.nextid : this.nextid = 0;
+ } },
+ sendAndReceive: { value: function(request, future, context) {
+ var conn = this.fetch();
+ var id = this.getNextId();
+ if (conn) {
+ this.send(request, future, id, context, conn);
+ }
+ else if (this.size < this.client.maxPoolSize) {
+ conn = this.create();
+ conn.onerror = function(e) {
+ future.reject(e);
+ };
+ var self = this;
+ conn.onconnect = function() {
+ self.init(conn);
+ self.send(request, future, id, context, conn);
+ };
+ }
+ else {
+ this.requests.push([request, future, id, context]);
+ }
+ } }
+ });
+
+ FullDuplexTcpTransporter.prototype.constructor = TcpTransporter;
+
+ function HalfDuplexTcpTransporter(client) {
+ TcpTransporter.call(this, client);
+ }
+
+ HalfDuplexTcpTransporter.prototype = Object.create(
+ TcpTransporter.prototype, {
+ fetch: { value: function() {
+ var pool = this.pool;
+ while (pool.length > 0) {
+ var conn = pool.pop();
+ if (conn.connected) {
+ conn.clearTimeout();
+ conn.ref();
+ return conn;
+ }
+ }
+ return null;
+ } },
+ recycle: { value: function(conn) {
+ if (this.pool.lastIndexOf(conn) < 0) {
+ conn.unref();
+ conn.setTimeout(this.client.poolTimeout, function() {
+ conn.destroy();
+ });
+ this.pool.push(conn);
+ }
+ } },
+ clean: { value: function(conn) {
+ conn.onreceive = noop;
+ conn.onerror = noop;
+ if (conn.timeoutId !== undefined) {
+ global.clearTimeout(conn.timeoutId);
+ delete conn.timeoutId;
+ }
+ } },
+ sendNext: { value: function(conn) {
+ if (this.requests.length > 0) {
+ var request = this.requests.pop();
+ request.push(conn);
+ this.send.apply(this, request);
+ }
+ else {
+ this.recycle(conn);
+ }
+ } },
+ send: { value: function(request, future, context, conn) {
+ var self = this;
+ var timeout = context.timeout;
+ if (timeout > 0) {
+ conn.timeoutId = global.setTimeout(function() {
+ self.clean(conn);
+ conn.destroy();
+ future.reject(new TimeoutError('timeout'));
+ }, timeout);
+ }
+ setReceiveHandler(conn, function(data) {
+ self.clean(conn);
+ self.sendNext(conn);
+ future.resolve(data);
+ });
+ conn.onerror = function(e) {
+ self.clean(conn);
+ future.reject(e);
+ };
+
+ var len = request.length;
+ var buf = new BytesIO(4 + len);
+ buf.writeInt32BE(len);
+ buf.write(request);
+ conn.send(buf.buffer);
+ } },
+ sendAndReceive: { value: function(request, future, context) {
+ var conn = this.fetch();
+ if (conn) {
+ this.send(request, future, context, conn);
+ }
+ else if (this.size < this.client.maxPoolSize) {
+ conn = this.create();
+ var self = this;
+ conn.onerror = function(e) {
+ future.reject(e);
+ };
+ conn.onconnect = function() {
+ self.send(request, future, context, conn);
+ };
+ }
+ else {
+ this.requests.push([request, future, context]);
+ }
+ } }
+ });
+
+ HalfDuplexTcpTransporter.prototype.constructor = TcpTransporter;
+
+ function TcpClient(uri, functions, settings) {
+ if (this.constructor !== TcpClient) {
+ return new TcpClient(uri, functions, settings);
+ }
+ Client.call(this, uri, functions, settings);
+
+ var self = this;
+ var _noDelay = true;
+ var _fullDuplex = false;
+ var _maxPoolSize = 10;
+ var _poolTimeout = 30000;
+ var fdtrans = null;
+ var hdtrans = null;
+
+ function getNoDelay() {
+ return _noDelay;
+ }
+
+ function setNoDelay(value) {
+ _noDelay = !!value;
+ }
+
+ function getFullDuplex() {
+ return _fullDuplex;
+ }
+
+ function setFullDuplex(value) {
+ _fullDuplex = !!value;
+ }
+
+ function getMaxPoolSize() {
+ return _maxPoolSize;
+ }
+
+ function setMaxPoolSize(value) {
+ if (typeof(value) === 'number') {
+ _maxPoolSize = value | 0;
+ if (_maxPoolSize < 1) {
+ _maxPoolSize = 10;
+ }
+ }
+ else {
+ _maxPoolSize = 10;
+ }
+ }
+
+ function getPoolTimeout() {
+ return _poolTimeout;
+ }
+
+ function setPoolTimeout(value) {
+ if (typeof(value) === 'number') {
+ _poolTimeout = value | 0;
+ }
+ else {
+ _poolTimeout = 0;
+ }
+ }
+
+ function sendAndReceive(request, context) {
+ var future = new Future();
+ if (_fullDuplex) {
+ if ((fdtrans === null) || (fdtrans.uri !== self.uri)) {
+ fdtrans = new FullDuplexTcpTransporter(self);
+ }
+ fdtrans.sendAndReceive(request, future, context);
+ }
+ else {
+ if ((hdtrans === null) || (hdtrans.uri !== self.uri)) {
+ hdtrans = new HalfDuplexTcpTransporter(self);
+ }
+ hdtrans.sendAndReceive(request, future, context);
+ }
+ if (context.oneway) { future.resolve(); }
+ return future;
+ }
+
+ Object.defineProperties(this, {
+ noDelay: { get: getNoDelay, set: setNoDelay },
+ fullDuplex: { get: getFullDuplex, set: setFullDuplex },
+ maxPoolSize: { get: getMaxPoolSize, set: setMaxPoolSize },
+ poolTimeout: { get: getPoolTimeout, set: setPoolTimeout },
+ sendAndReceive: { value: sendAndReceive }
+ });
+ }
+
+ function checkuri(uri) {
+ var parser = parseuri(uri);
+ var protocol = parser.protocol;
+ if (protocol === 'tcp:' ||
+ protocol === 'tcp4:'||
+ protocol === 'tcp6:' ||
+ protocol === 'tcps:' ||
+ protocol === 'tcp4s:' ||
+ protocol === 'tcp6s:' ||
+ protocol === 'tls:') {
+ return;
+ }
+ throw new Error('This client desn\'t support ' + protocol + ' scheme.');
+ }
+
+ function create(uri, functions, settings) {
+ if (typeof uri === 'string') {
+ checkuri(uri);
+ }
+ else if (Array.isArray(uri)) {
+ uri.forEach(function(uri) { checkuri(uri); });
+ }
+ else {
+ throw new Error('You should set server uri first!');
+ }
+ return new TcpClient(uri, functions, settings);
+ }
+
+ Object.defineProperty(TcpClient, 'create', { value: create });
+
+ hprose.TcpClient = TcpClient;
+
+})(hprose, hprose.global);
diff --git a/src/TimeoutError.js b/src/TimeoutError.js
index b4397ee..7ca5787 100644
--- a/src/TimeoutError.js
+++ b/src/TimeoutError.js
@@ -13,19 +13,21 @@
* *
* TimeoutError for HTML5. *
* *
- * LastModified: Jul 17, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-function TimeoutError(message) {
- Error.call(this);
- this.message = message;
- this.name = TimeoutError.name;
- if (typeof Error.captureStackTrace === 'function') {
- Error.captureStackTrace(this, TimeoutError);
+(function(global) {
+ function TimeoutError(message) {
+ Error.call(this);
+ this.message = message;
+ this.name = TimeoutError.name;
+ if (typeof Error.captureStackTrace === 'function') {
+ Error.captureStackTrace(this, TimeoutError);
+ }
}
-}
-
-TimeoutError.prototype = Object.create(Error.prototype);
-TimeoutError.prototype.constructor = TimeoutError;
+ TimeoutError.prototype = Object.create(Error.prototype);
+ TimeoutError.prototype.constructor = TimeoutError;
+ global.TimeoutError = TimeoutError;
+})(hprose.global);
\ No newline at end of file
diff --git a/src/WebSocketClient.js b/src/WebSocketClient.js
index 8ee7e4c..e95e409 100644
--- a/src/WebSocketClient.js
+++ b/src/WebSocketClient.js
@@ -12,22 +12,30 @@
* *
* hprose websocket client for HTML5. *
* *
- * LastModified: Aug 15, 2015 *
+ * LastModified: Aug 20, 2017 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, global, undefined) {
'use strict';
- var Client = global.hprose.Client;
- var BytesIO = global.hprose.BytesIO;
- var Future = global.hprose.Future;
+ var BytesIO = hprose.BytesIO;
+ var Client = hprose.Client;
+ var Future = hprose.Future;
+ var TimeoutError = global.TimeoutError;
+ var parseuri = hprose.parseuri;
+
+ var WebSocket = global.WebSocket || global.MozWebSocket;
function noop(){}
function WebSocketClient(uri, functions, settings) {
- if (this.constructor !== WebSocketClient) return new WebSocketClient(uri, functions, settings);
+ if (typeof(WebSocket) === "undefined") {
+ throw new Error('WebSocket is not supported by this browser.');
+ }
+ if (this.constructor !== WebSocketClient) {
+ return new WebSocketClient(uri, functions, settings);
+ }
Client.call(this, uri, functions, settings);
@@ -77,11 +85,11 @@
}
if ((_count < 100) && (_requests.length > 0)) {
++_count;
- var request = _requests.shift();
+ var request = _requests.pop();
_ready.then(function() { send(request[0], request[1]); });
}
- if (_count === 0) {
- if (!self.keepAlive) close();
+ if (_count === 0 && !self.keepAlive) {
+ close();
}
}
function onclose(e) {
@@ -101,25 +109,26 @@
ws.onerror = noop;
ws.onclose = onclose;
}
- function sendAndReceive(request, env) {
- if (ws === null ||
- ws.readyState === WebSocket.CLOSING ||
- ws.readyState === WebSocket.CLOSED) {
- connect();
- }
+ function sendAndReceive(request, context) {
var id = getNextId();
var future = new Future();
_futures[id] = future;
- if (self.timeout > 0) {
- future = future.timeout(self.timeout).catchError(function(e) {
+ if (context.timeout > 0) {
+ future = future.timeout(context.timeout).catchError(function(e) {
delete _futures[id];
--_count;
+ close();
throw e;
},
function(e) {
return e instanceof TimeoutError;
});
}
+ if (ws === null ||
+ ws.readyState === WebSocket.CLOSING ||
+ ws.readyState === WebSocket.CLOSED) {
+ connect();
+ }
if (_count < 100) {
++_count;
_ready.then(function() { send(id, request); });
@@ -127,7 +136,7 @@
else {
_requests.push([id, request]);
}
- if (env.oneway) future.resolve();
+ if (context.oneway) { future.resolve(); }
return future;
}
function close() {
@@ -146,8 +155,7 @@
}
function checkuri(uri) {
- var parser = document.createElement('a');
- parser.href = uri;
+ var parser = parseuri(uri);
if (parser.protocol === 'ws:' ||
parser.protocol === 'wss:') {
return;
@@ -163,15 +171,13 @@
uri.forEach(function(uri) { checkuri(uri); });
}
else {
- return new Error('You should set server uri first!');
+ throw new Error('You should set server uri first!');
}
return new WebSocketClient(uri, functions, settings);
}
Object.defineProperty(WebSocketClient, 'create', { value: create });
- global.hprose.WebSocketClient = WebSocketClient;
+ hprose.WebSocketClient = WebSocketClient;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose, hprose.global);
diff --git a/src/Writer.js b/src/Writer.js
index f5a5c11..d99e83e 100644
--- a/src/Writer.js
+++ b/src/Writer.js
@@ -13,24 +13,26 @@
* *
* hprose Writer for HTML5. *
* *
- * LastModified: Aug 2, 2015 *
+ * LastModified: Feb 13, 2017 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
-(function (global, undefined) {
+(function (hprose, global, undefined) {
'use strict';
var Map = global.Map;
- var BytesIO = global.hprose.BytesIO;
- var Tags = global.hprose.Tags;
- var ClassManager = global.hprose.ClassManager;
+ var BytesIO = hprose.BytesIO;
+ var Tags = hprose.Tags;
+ var ClassManager = hprose.ClassManager;
function getClassName(obj) {
var cls = obj.constructor;
+ if (!cls) {
+ return 'Object';
+ }
var classname = ClassManager.getClassAlias(cls);
- if (classname) return classname;
+ if (classname) { return classname; }
if (cls.name) {
classname = cls.name;
}
@@ -303,9 +305,14 @@
var stream = writer.stream;
stream.writeByte(Tags.TagBytes);
var n = bytes.byteLength || bytes.length;
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagQuote);
- if (n > 0) stream.write(bytes);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagQuote);
+ stream.write(bytes);
+ }
+ else {
+ stream.writeByte(Tags.TagQuote);
+ }
stream.writeByte(Tags.TagQuote);
}
@@ -314,9 +321,14 @@
var stream = writer.stream;
var n = str.length;
stream.writeByte(Tags.TagString);
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagQuote);
- if (n > 0) stream.writeString(str);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagQuote);
+ stream.writeString(str);
+ }
+ else {
+ stream.writeByte(Tags.TagQuote);
+ }
stream.writeByte(Tags.TagQuote);
}
@@ -325,10 +337,15 @@
var stream = writer.stream;
var n = array.length;
stream.writeByte(Tags.TagList);
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagOpenbrace);
- for (var i = 0; i < n; i++) {
- writeElem(writer, array[i]);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ writeElem(writer, array[i]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
}
stream.writeByte(Tags.TagClosebrace);
}
@@ -357,11 +374,16 @@
}
var n = fields.length;
stream.writeByte(Tags.TagMap);
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagOpenbrace);
- for (var i = 0; i < n; i++) {
- serialize(writer, fields[i]);
- serialize(writer, map[fields[i]]);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ serialize(writer, fields[i]);
+ serialize(writer, map[fields[i]]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
}
stream.writeByte(Tags.TagClosebrace);
}
@@ -371,12 +393,17 @@
var stream = writer.stream;
var n = map.size;
stream.writeByte(Tags.TagMap);
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagOpenbrace);
- map.forEach(function(value, key) {
- serialize(writer, key);
- serialize(writer, value);
- });
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ map.forEach(function(value, key) {
+ serialize(writer, key);
+ serialize(writer, value);
+ });
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
+ }
stream.writeByte(Tags.TagClosebrace);
}
@@ -417,10 +444,15 @@
stream.writeByte(Tags.TagQuote);
stream.writeString(classname);
stream.writeByte(Tags.TagQuote);
- if (n > 0) stream.writeAsciiString('' + n);
- stream.writeByte(Tags.TagOpenbrace);
- for (var i = 0; i < n; i++) {
- writeString(writer, fields[i]);
+ if (n > 0) {
+ stream.writeAsciiString('' + n);
+ stream.writeByte(Tags.TagOpenbrace);
+ for (var i = 0; i < n; i++) {
+ writeString(writer, fields[i]);
+ }
+ }
+ else {
+ stream.writeByte(Tags.TagOpenbrace);
}
stream.writeByte(Tags.TagClosebrace);
var index = writer._fieldsref.length;
@@ -523,8 +555,6 @@
} }
});
- global.hprose.Writer = Writer;
+ hprose.Writer = Writer;
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose, hprose.global);
diff --git a/src/setImmediate.js b/src/setImmediate.js
index 9014fe4..0dbbc6d 100644
--- a/src/setImmediate.js
+++ b/src/setImmediate.js
@@ -9,60 +9,44 @@
/**********************************************************\
* *
- * hprose/common/setImmediate.js *
+ * setImmediate.js *
* *
* setImmediate for HTML5. *
* *
- * LastModified: Jul 19, 2015 *
+ * LastModified: Nov 18, 2016 *
* Author: Ma Bingyao *
* *
\**********************************************************/
-/* jshint -W067 */
(function(global, undefined) {
'use strict';
-
- // @see http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
- var notUseNative = (global.navigator && /Trident/.test(global.navigator.userAgent));
-
- if (!notUseNative && (global.msSetImmediate || global.setImmediate)) {
- if (!global.setImmediate) {
- global.setImmediate = global.msSetImmediate;
- global.clearImmediate = global.msClearImmediate;
- }
- return;
- }
+ if (global.setImmediate) { return; }
var doc = global.document;
- var slice = Function.prototype.call.bind(Array.prototype.slice);
- var toString = Function.prototype.call.bind(Object.prototype.toString);
+ var MutationObserver = global.MutationObserver || global.WebKitMutationObserver || global.MozMutationOvserver;
var polifill = {};
var nextId = 1;
var tasks = {};
- var lock = false;
function wrap(handler) {
- var args = slice(arguments, 1);
+ var args = Array.prototype.slice.call(arguments, 1);
return function() {
handler.apply(undefined, args);
};
}
+ function clear(handleId) {
+ delete tasks[handleId];
+ }
+
function run(handleId) {
- if (lock) {
- // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a "too much recursion" error.
- global.setTimeout(wrap(run, handleId), 0);
- } else {
- var task = tasks[handleId];
- if (task) {
- lock = true;
- try {
- task();
- }
- finally {
- clear(handleId);
- lock = false;
- }
+ var task = tasks[handleId];
+ if (task) {
+ try {
+ task();
+ }
+ finally {
+ clear(handleId);
}
}
}
@@ -72,9 +56,24 @@
return nextId++;
}
- function clear(handleId) {
- delete tasks[handleId];
- }
+ polifill.mutationObserver = function() {
+ var queue = [],
+ node = doc.createTextNode(''),
+ observer = new MutationObserver(function() {
+ while (queue.length > 0) {
+ run(queue.shift());
+ }
+ });
+
+ observer.observe(node, {"characterData": true});
+
+ return function() {
+ var handleId = create(arguments);
+ queue.push(handleId);
+ node.data = handleId & 1;
+ return handleId;
+ };
+ };
polifill.messageChannel = function() {
var channel = new global.MessageChannel();
@@ -99,27 +98,22 @@
};
polifill.postMessage = function() {
- var messagePrefix = 'setImmediate$' + Math.random() + '$';
-
- var onGlobalMessage = function(event) {
- if (event.source === global &&
- typeof(event.data) === 'string' &&
- event.data.indexOf(messagePrefix) === 0) {
-
- run(Number(event.data.slice(messagePrefix.length)));
+ var iframe = doc.createElement('iframe');
+ iframe.style.display = 'none';
+ doc.documentElement.appendChild(iframe);
+ var iwin = iframe.contentWindow;
+ iwin.document.write('');
+ iwin.document.close();
+ var queue = [];
+ window.addEventListener('message', function() {
+ while (queue.length > 0) {
+ run(queue.shift());
}
- };
-
- if (global.addEventListener) {
- global.addEventListener('message', onGlobalMessage, false);
-
- } else {
- global.attachEvent('onmessage', onGlobalMessage);
- }
-
+ });
return function() {
var handleId = create(arguments);
- global.postMessage(messagePrefix + handleId, '*');
+ queue.push(handleId);
+ iwin.postMessage(1, "*");
return handleId;
};
};
@@ -144,61 +138,45 @@
};
};
+ // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
+ var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
+ attachTo = (attachTo && attachTo.setTimeout ? attachTo : global);
+
polifill.setTimeout = function() {
return function() {
var handleId = create(arguments);
- global.setTimeout( wrap( run, handleId ), 0 );
+ attachTo.setTimeout( wrap( run, handleId ), 0 );
return handleId;
};
};
- function canUsePostMessage() {
- if (global.postMessage && !global.importScripts) {
- var asynch = true;
- var oldOnMessage = global.onmessage;
- global.onmessage = function() {
- asynch = false;
- };
- global.postMessage('', '*');
- global.onmessage = oldOnMessage;
- return asynch;
- }
- }
-
- // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
- var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
- attachTo = (attachTo && attachTo.setTimeout ? attachTo : global);
-
- if (notUseNative) {
- attachTo.setImmediate = polifill.setTimeout();
-
// Don't get fooled by e.g. browserify environments.
// For Node.js before 0.9
- } else if (toString(global.process) === '[object process]') {
+ if (typeof(global.process) !== 'undefined' &&
+ Object.prototype.toString.call(global.process) === '[object process]' &&
+ !global.process.browser) {
attachTo.setImmediate = polifill.nextTick();
-
- // For non-IE10 modern browsers
- } else if (canUsePostMessage()) {
- attachTo.setImmediate = polifill.postMessage();
-
+ }
+ // For IE 6–9
+ else if (doc && ('onreadystatechange' in doc.createElement('script'))) {
+ attachTo.setImmediate = polifill.readyStateChange();
+ }
+ // For MutationObserver, where supported
+ else if (doc && MutationObserver) {
+ attachTo.setImmediate = polifill.mutationObserver();
+ }
// For web workers, where supported
- } else if (global.MessageChannel) {
+ else if (global.MessageChannel) {
attachTo.setImmediate = polifill.messageChannel();
-
- // For IE 6–8
- } else if (doc && ('onreadystatechange' in doc.createElement('script'))) {
- attachTo.setImmediate = polifill.readyStateChange();
-
+ }
+ // For non-IE modern browsers
+ else if (doc && 'postMessage' in global && 'addEventListener' in global) {
+ attachTo.setImmediate = polifill.postMessage();
+ }
// For older browsers
- } else {
+ else {
attachTo.setImmediate = polifill.setTimeout();
}
- attachTo.msSetImmediate = attachTo.setImmediate;
-
attachTo.clearImmediate = clear;
- attachTo.msClearImmediate = clear;
-
-}(function() {
- return this || (1, eval)('this');
-}()));
+})(hprose.global);
diff --git a/test/Future.Test.js b/test/Future.Test.js
index 44d95d0..7ec5212 100644
--- a/test/Future.Test.js
+++ b/test/Future.Test.js
@@ -234,4 +234,4 @@
testPromise();
testPromise();
testPromise();
-})(this);
+})(this || [eval][0]('this'));
diff --git a/test/test.html b/test/test.html
new file mode 100644
index 0000000..3710c74
--- /dev/null
+++ b/test/test.html
@@ -0,0 +1,19 @@
+
+
+
+
+ hprose test
+
+
+
+
+
+
+
diff --git a/test/test_sea.html b/test/test_sea.html
index c3f6f8b..2e62978 100644
--- a/test/test_sea.html
+++ b/test/test_sea.html
@@ -11,7 +11,7 @@
}
});
seajs.use('hprose', function(hprose) {
- var client = new hprose.HttpClient("http://www.hprose.com/example/", ["hello"]);
+ var client = new hprose.HttpClient("http://www.hprose.com/example/index.php", ["hello"]);
client.hello("World!", function(result) {
alert(result);
}, function(name, err) {
diff --git a/test/test_src.html b/test/test_src.html
index 9a1d763..d3f3ffe 100644
--- a/test/test_src.html
+++ b/test/test_src.html
@@ -4,6 +4,8 @@
hprose test
+
+
diff --git a/utils/regenerator-runtime.js b/utils/regenerator-runtime.js
new file mode 100644
index 0000000..4ec72f1
--- /dev/null
+++ b/utils/regenerator-runtime.js
@@ -0,0 +1,669 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
+ * additional grant of patent rights can be found in the PATENTS file in
+ * the same directory.
+ */
+
+!(function(global) {
+ "use strict";
+
+ var hasOwn = Object.prototype.hasOwnProperty;
+ var undefined; // More compressible than void 0.
+ var $Symbol = typeof Symbol === "function" ? Symbol : {};
+ var iteratorSymbol = $Symbol.iterator || "@@iterator";
+ var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
+
+ var inModule = typeof module === "object";
+ var runtime = global.regeneratorRuntime;
+ if (runtime) {
+ if (inModule) {
+ // If regeneratorRuntime is defined globally and we're in a module,
+ // make the exports object identical to regeneratorRuntime.
+ module.exports = runtime;
+ }
+ // Don't bother evaluating the rest of this file if the runtime was
+ // already defined globally.
+ return;
+ }
+
+ // Define the runtime globally (as expected by generated code) as either
+ // module.exports (if we're in a module) or a new, empty object.
+ runtime = global.regeneratorRuntime = inModule ? module.exports : {};
+
+ function wrap(innerFn, outerFn, self, tryLocsList) {
+ // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
+ var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
+ var generator = Object.create(protoGenerator.prototype);
+ var context = new Context(tryLocsList || []);
+
+ // The ._invoke method unifies the implementations of the .next,
+ // .throw, and .return methods.
+ generator._invoke = makeInvokeMethod(innerFn, self, context);
+
+ return generator;
+ }
+ runtime.wrap = wrap;
+
+ // Try/catch helper to minimize deoptimizations. Returns a completion
+ // record like context.tryEntries[i].completion. This interface could
+ // have been (and was previously) designed to take a closure to be
+ // invoked without arguments, but in all the cases we care about we
+ // already have an existing method we want to call, so there's no need
+ // to create a new function object. We can even get away with assuming
+ // the method takes exactly one argument, since that happens to be true
+ // in every case, so we don't have to touch the arguments object. The
+ // only additional allocation required is the completion record, which
+ // has a stable shape and so hopefully should be cheap to allocate.
+ function tryCatch(fn, obj, arg) {
+ try {
+ return { type: "normal", arg: fn.call(obj, arg) };
+ } catch (err) {
+ return { type: "throw", arg: err };
+ }
+ }
+
+ var GenStateSuspendedStart = "suspendedStart";
+ var GenStateSuspendedYield = "suspendedYield";
+ var GenStateExecuting = "executing";
+ var GenStateCompleted = "completed";
+
+ // Returning this object from the innerFn has the same effect as
+ // breaking out of the dispatch switch statement.
+ var ContinueSentinel = {};
+
+ // Dummy constructor functions that we use as the .constructor and
+ // .constructor.prototype properties for functions that return Generator
+ // objects. For full spec compliance, you may wish to configure your
+ // minifier not to mangle the names of these two functions.
+ function Generator() {}
+ function GeneratorFunction() {}
+ function GeneratorFunctionPrototype() {}
+
+ var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype;
+ GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
+ GeneratorFunctionPrototype.constructor = GeneratorFunction;
+ GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction";
+
+ // Helper for defining the .next, .throw, and .return methods of the
+ // Iterator interface in terms of a single ._invoke method.
+ function defineIteratorMethods(prototype) {
+ ["next", "throw", "return"].forEach(function(method) {
+ prototype[method] = function(arg) {
+ return this._invoke(method, arg);
+ };
+ });
+ }
+
+ runtime.isGeneratorFunction = function(genFun) {
+ var ctor = typeof genFun === "function" && genFun.constructor;
+ return ctor
+ ? ctor === GeneratorFunction ||
+ // For the native GeneratorFunction constructor, the best we can
+ // do is to check its .name property.
+ (ctor.displayName || ctor.name) === "GeneratorFunction"
+ : false;
+ };
+
+ runtime.mark = function(genFun) {
+ if (Object.setPrototypeOf) {
+ Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
+ } else {
+ genFun.__proto__ = GeneratorFunctionPrototype;
+ if (!(toStringTagSymbol in genFun)) {
+ genFun[toStringTagSymbol] = "GeneratorFunction";
+ }
+ }
+ genFun.prototype = Object.create(Gp);
+ return genFun;
+ };
+
+ // Within the body of any async function, `await x` is transformed to
+ // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
+ // `value instanceof AwaitArgument` to determine if the yielded value is
+ // meant to be awaited. Some may consider the name of this method too
+ // cutesy, but they are curmudgeons.
+ runtime.awrap = function(arg) {
+ return new AwaitArgument(arg);
+ };
+
+ function AwaitArgument(arg) {
+ this.arg = arg;
+ }
+
+ function AsyncIterator(generator) {
+ function invoke(method, arg, resolve, reject) {
+ var record = tryCatch(generator[method], generator, arg);
+ if (record.type === "throw") {
+ reject(record.arg);
+ } else {
+ var result = record.arg;
+ var value = result.value;
+ if (value instanceof AwaitArgument) {
+ return Promise.resolve(value.arg).then(function(value) {
+ invoke("next", value, resolve, reject);
+ }, function(err) {
+ invoke("throw", err, resolve, reject);
+ });
+ }
+
+ return Promise.resolve(value).then(function(unwrapped) {
+ // When a yielded Promise is resolved, its final value becomes
+ // the .value of the Promise<{value,done}> result for the
+ // current iteration. If the Promise is rejected, however, the
+ // result for this iteration will be rejected with the same
+ // reason. Note that rejections of yielded Promises are not
+ // thrown back into the generator function, as is the case
+ // when an awaited Promise is rejected. This difference in
+ // behavior between yield and await is important, because it
+ // allows the consumer to decide what to do with the yielded
+ // rejection (swallow it and continue, manually .throw it back
+ // into the generator, abandon iteration, whatever). With
+ // await, by contrast, there is no opportunity to examine the
+ // rejection reason outside the generator function, so the
+ // only option is to throw it from the await expression, and
+ // let the generator function handle the exception.
+ result.value = unwrapped;
+ resolve(result);
+ }, reject);
+ }
+ }
+
+ if (typeof process === "object" && process.domain) {
+ invoke = process.domain.bind(invoke);
+ }
+
+ var previousPromise;
+
+ function enqueue(method, arg) {
+ function callInvokeWithMethodAndArg() {
+ return new Promise(function(resolve, reject) {
+ invoke(method, arg, resolve, reject);
+ });
+ }
+
+ return previousPromise =
+ // If enqueue has been called before, then we want to wait until
+ // all previous Promises have been resolved before calling invoke,
+ // so that results are always delivered in the correct order. If
+ // enqueue has not been called before, then it is important to
+ // call invoke immediately, without waiting on a callback to fire,
+ // so that the async generator function has the opportunity to do
+ // any necessary setup in a predictable way. This predictability
+ // is why the Promise constructor synchronously invokes its
+ // executor callback, and why async functions synchronously
+ // execute code before the first await. Since we implement simple
+ // async functions in terms of async generators, it is especially
+ // important to get this right, even though it requires care.
+ previousPromise ? previousPromise.then(
+ callInvokeWithMethodAndArg,
+ // Avoid propagating failures to Promises returned by later
+ // invocations of the iterator.
+ callInvokeWithMethodAndArg
+ ) : callInvokeWithMethodAndArg();
+ }
+
+ // Define the unified helper method that is used to implement .next,
+ // .throw, and .return (see defineIteratorMethods).
+ this._invoke = enqueue;
+ }
+
+ defineIteratorMethods(AsyncIterator.prototype);
+
+ // Note that simple async functions are implemented on top of
+ // AsyncIterator objects; they just return a Promise for the value of
+ // the final result produced by the iterator.
+ runtime.async = function(innerFn, outerFn, self, tryLocsList) {
+ var iter = new AsyncIterator(
+ wrap(innerFn, outerFn, self, tryLocsList)
+ );
+
+ return runtime.isGeneratorFunction(outerFn)
+ ? iter // If outerFn is a generator, return the full iterator.
+ : iter.next().then(function(result) {
+ return result.done ? result.value : iter.next();
+ });
+ };
+
+ function makeInvokeMethod(innerFn, self, context) {
+ var state = GenStateSuspendedStart;
+
+ return function invoke(method, arg) {
+ if (state === GenStateExecuting) {
+ throw new Error("Generator is already running");
+ }
+
+ if (state === GenStateCompleted) {
+ if (method === "throw") {
+ throw arg;
+ }
+
+ // Be forgiving, per 25.3.3.3.3 of the spec:
+ // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
+ return doneResult();
+ }
+
+ while (true) {
+ var delegate = context.delegate;
+ if (delegate) {
+ if (method === "return" ||
+ (method === "throw" && delegate.iterator[method] === undefined)) {
+ // A return or throw (when the delegate iterator has no throw
+ // method) always terminates the yield* loop.
+ context.delegate = null;
+
+ // If the delegate iterator has a return method, give it a
+ // chance to clean up.
+ var returnMethod = delegate.iterator["return"];
+ if (returnMethod) {
+ var record = tryCatch(returnMethod, delegate.iterator, arg);
+ if (record.type === "throw") {
+ // If the return method threw an exception, let that
+ // exception prevail over the original return or throw.
+ method = "throw";
+ arg = record.arg;
+ continue;
+ }
+ }
+
+ if (method === "return") {
+ // Continue with the outer return, now that the delegate
+ // iterator has been terminated.
+ continue;
+ }
+ }
+
+ var record = tryCatch(
+ delegate.iterator[method],
+ delegate.iterator,
+ arg
+ );
+
+ if (record.type === "throw") {
+ context.delegate = null;
+
+ // Like returning generator.throw(uncaught), but without the
+ // overhead of an extra function call.
+ method = "throw";
+ arg = record.arg;
+ continue;
+ }
+
+ // Delegate generator ran and handled its own exceptions so
+ // regardless of what the method was, we continue as if it is
+ // "next" with an undefined arg.
+ method = "next";
+ arg = undefined;
+
+ var info = record.arg;
+ if (info.done) {
+ context[delegate.resultName] = info.value;
+ context.next = delegate.nextLoc;
+ } else {
+ state = GenStateSuspendedYield;
+ return info;
+ }
+
+ context.delegate = null;
+ }
+
+ if (method === "next") {
+ // Setting context._sent for legacy support of Babel's
+ // function.sent implementation.
+ context.sent = context._sent = arg;
+
+ } else if (method === "throw") {
+ if (state === GenStateSuspendedStart) {
+ state = GenStateCompleted;
+ throw arg;
+ }
+
+ if (context.dispatchException(arg)) {
+ // If the dispatched exception was caught by a catch block,
+ // then let that catch block handle the exception normally.
+ method = "next";
+ arg = undefined;
+ }
+
+ } else if (method === "return") {
+ context.abrupt("return", arg);
+ }
+
+ state = GenStateExecuting;
+
+ var record = tryCatch(innerFn, self, context);
+ if (record.type === "normal") {
+ // If an exception is thrown from innerFn, we leave state ===
+ // GenStateExecuting and loop back for another invocation.
+ state = context.done
+ ? GenStateCompleted
+ : GenStateSuspendedYield;
+
+ var info = {
+ value: record.arg,
+ done: context.done
+ };
+
+ if (record.arg === ContinueSentinel) {
+ if (context.delegate && method === "next") {
+ // Deliberately forget the last sent value so that we don't
+ // accidentally pass it on to the delegate.
+ arg = undefined;
+ }
+ } else {
+ return info;
+ }
+
+ } else if (record.type === "throw") {
+ state = GenStateCompleted;
+ // Dispatch the exception by looping back around to the
+ // context.dispatchException(arg) call above.
+ method = "throw";
+ arg = record.arg;
+ }
+ }
+ };
+ }
+
+ // Define Generator.prototype.{next,throw,return} in terms of the
+ // unified ._invoke helper method.
+ defineIteratorMethods(Gp);
+
+ Gp[iteratorSymbol] = function() {
+ return this;
+ };
+
+ Gp[toStringTagSymbol] = "Generator";
+
+ Gp.toString = function() {
+ return "[object Generator]";
+ };
+
+ function pushTryEntry(locs) {
+ var entry = { tryLoc: locs[0] };
+
+ if (1 in locs) {
+ entry.catchLoc = locs[1];
+ }
+
+ if (2 in locs) {
+ entry.finallyLoc = locs[2];
+ entry.afterLoc = locs[3];
+ }
+
+ this.tryEntries.push(entry);
+ }
+
+ function resetTryEntry(entry) {
+ var record = entry.completion || {};
+ record.type = "normal";
+ delete record.arg;
+ entry.completion = record;
+ }
+
+ function Context(tryLocsList) {
+ // The root entry object (effectively a try statement without a catch
+ // or a finally block) gives us a place to store values thrown from
+ // locations where there is no enclosing try statement.
+ this.tryEntries = [{ tryLoc: "root" }];
+ tryLocsList.forEach(pushTryEntry, this);
+ this.reset(true);
+ }
+
+ runtime.keys = function(object) {
+ var keys = [];
+ for (var key in object) {
+ keys.push(key);
+ }
+ keys.reverse();
+
+ // Rather than returning an object with a next method, we keep
+ // things simple and return the next function itself.
+ return function next() {
+ while (keys.length) {
+ var key = keys.pop();
+ if (key in object) {
+ next.value = key;
+ next.done = false;
+ return next;
+ }
+ }
+
+ // To avoid creating an additional object, we just hang the .value
+ // and .done properties off the next function object itself. This
+ // also ensures that the minifier will not anonymize the function.
+ next.done = true;
+ return next;
+ };
+ };
+
+ function values(iterable) {
+ if (iterable) {
+ var iteratorMethod = iterable[iteratorSymbol];
+ if (iteratorMethod) {
+ return iteratorMethod.call(iterable);
+ }
+
+ if (typeof iterable.next === "function") {
+ return iterable;
+ }
+
+ if (!isNaN(iterable.length)) {
+ var i = -1, next = function next() {
+ while (++i < iterable.length) {
+ if (hasOwn.call(iterable, i)) {
+ next.value = iterable[i];
+ next.done = false;
+ return next;
+ }
+ }
+
+ next.value = undefined;
+ next.done = true;
+
+ return next;
+ };
+
+ return next.next = next;
+ }
+ }
+
+ // Return an iterator with no values.
+ return { next: doneResult };
+ }
+ runtime.values = values;
+
+ function doneResult() {
+ return { value: undefined, done: true };
+ }
+
+ Context.prototype = {
+ constructor: Context,
+
+ reset: function(skipTempReset) {
+ this.prev = 0;
+ this.next = 0;
+ // Resetting context._sent for legacy support of Babel's
+ // function.sent implementation.
+ this.sent = this._sent = undefined;
+ this.done = false;
+ this.delegate = null;
+
+ this.tryEntries.forEach(resetTryEntry);
+
+ if (!skipTempReset) {
+ for (var name in this) {
+ // Not sure about the optimal order of these conditions:
+ if (name.charAt(0) === "t" &&
+ hasOwn.call(this, name) &&
+ !isNaN(+name.slice(1))) {
+ this[name] = undefined;
+ }
+ }
+ }
+ },
+
+ stop: function() {
+ this.done = true;
+
+ var rootEntry = this.tryEntries[0];
+ var rootRecord = rootEntry.completion;
+ if (rootRecord.type === "throw") {
+ throw rootRecord.arg;
+ }
+
+ return this.rval;
+ },
+
+ dispatchException: function(exception) {
+ if (this.done) {
+ throw exception;
+ }
+
+ var context = this;
+ function handle(loc, caught) {
+ record.type = "throw";
+ record.arg = exception;
+ context.next = loc;
+ return !!caught;
+ }
+
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+ var entry = this.tryEntries[i];
+ var record = entry.completion;
+
+ if (entry.tryLoc === "root") {
+ // Exception thrown outside of any try block that could handle
+ // it, so set the completion value of the entire function to
+ // throw the exception.
+ return handle("end");
+ }
+
+ if (entry.tryLoc <= this.prev) {
+ var hasCatch = hasOwn.call(entry, "catchLoc");
+ var hasFinally = hasOwn.call(entry, "finallyLoc");
+
+ if (hasCatch && hasFinally) {
+ if (this.prev < entry.catchLoc) {
+ return handle(entry.catchLoc, true);
+ } else if (this.prev < entry.finallyLoc) {
+ return handle(entry.finallyLoc);
+ }
+
+ } else if (hasCatch) {
+ if (this.prev < entry.catchLoc) {
+ return handle(entry.catchLoc, true);
+ }
+
+ } else if (hasFinally) {
+ if (this.prev < entry.finallyLoc) {
+ return handle(entry.finallyLoc);
+ }
+
+ } else {
+ throw new Error("try statement without catch or finally");
+ }
+ }
+ }
+ },
+
+ abrupt: function(type, arg) {
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+ var entry = this.tryEntries[i];
+ if (entry.tryLoc <= this.prev &&
+ hasOwn.call(entry, "finallyLoc") &&
+ this.prev < entry.finallyLoc) {
+ var finallyEntry = entry;
+ break;
+ }
+ }
+
+ if (finallyEntry &&
+ (type === "break" ||
+ type === "continue") &&
+ finallyEntry.tryLoc <= arg &&
+ arg <= finallyEntry.finallyLoc) {
+ // Ignore the finally entry if control is not jumping to a
+ // location outside the try/catch block.
+ finallyEntry = null;
+ }
+
+ var record = finallyEntry ? finallyEntry.completion : {};
+ record.type = type;
+ record.arg = arg;
+
+ if (finallyEntry) {
+ this.next = finallyEntry.finallyLoc;
+ } else {
+ this.complete(record);
+ }
+
+ return ContinueSentinel;
+ },
+
+ complete: function(record, afterLoc) {
+ if (record.type === "throw") {
+ throw record.arg;
+ }
+
+ if (record.type === "break" ||
+ record.type === "continue") {
+ this.next = record.arg;
+ } else if (record.type === "return") {
+ this.rval = record.arg;
+ this.next = "end";
+ } else if (record.type === "normal" && afterLoc) {
+ this.next = afterLoc;
+ }
+ },
+
+ finish: function(finallyLoc) {
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+ var entry = this.tryEntries[i];
+ if (entry.finallyLoc === finallyLoc) {
+ this.complete(entry.completion, entry.afterLoc);
+ resetTryEntry(entry);
+ return ContinueSentinel;
+ }
+ }
+ },
+
+ "catch": function(tryLoc) {
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+ var entry = this.tryEntries[i];
+ if (entry.tryLoc === tryLoc) {
+ var record = entry.completion;
+ if (record.type === "throw") {
+ var thrown = record.arg;
+ resetTryEntry(entry);
+ }
+ return thrown;
+ }
+ }
+
+ // The context.catch method must only be called with a location
+ // argument that corresponds to a known catch block.
+ throw new Error("illegal catch attempt");
+ },
+
+ delegateYield: function(iterable, resultName, nextLoc) {
+ this.delegate = {
+ iterator: values(iterable),
+ resultName: resultName,
+ nextLoc: nextLoc
+ };
+
+ return ContinueSentinel;
+ }
+ };
+})(
+ // Among the various tricks for obtaining a reference to the global
+ // object, this seems to be the most reliable technique that does not
+ // use indirect eval (which violates Content Security Policy).
+ typeof global === "object" ? global :
+ typeof window === "object" ? window :
+ typeof self === "object" ? self : this
+);