Node.js based smart shopping cart app

Information

In this page, there is English description followed by Japanese one.
本ページは英語の説明の後に日本語の説明が続きます。

Getting Started

Installing Node.js and npm

You need to have Node.js and npm installed.

To check if you have them installed, open a terminal or command prompt and run the following commands:

node --version
npm --version

If you see an number output similar to x.x.x for each command, then they are both installed and you can continue to the next section.

To install on Windows or mac, you can download the installer from https://nodejs.org/en/download.

To install on Linux, you can use a package manager. Instructions for installing Node.js on your distribution can be found in the following link:
https://nodejs.org/en/download/package-manager

Prerequisite

This example assumes that you've already run the following program that can communicate the decoded result of barcode data with mbed Device Connector:

Import programGR-PEACH_mbed-os-client-ZXingSample

Fork of https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/

Configuring the Applition

In order to run this app, you need to set up the options shown below via .env file stored in the folder GR-PEACH_mbed-os-QRCode-ShoppingCart-node which should be automatically created when cloning this program.

  • ACCESS_KEY
    Set this variable to your Access Key that you can create on mbed Device Connector. if you don't have an Access Key yet, please create it in accordance with the following procedure.
    1. Access https://connector.mbed.com/#accesskeys.
    2. Click CREATE NEW ACCESS KEY.
    /media/uploads/HinoNaka/screenshot7.png
    3. When prompted, enter a name for the access key (e.g. "demo") and click ADD.
    /media/uploads/HinoNaka/screenshot8.png

    After an access key is successfully created, please copy the access key you just created and use it in .env file as follows:

.env

ACCESS_KEY=...
  • PORT
    Set this variable as follows to override the default port for this example if needed. The default port is 8080.

.env

PORT=...

Also, user need to prepare for the comma-delimited list which includes "Item Name" and "Price" which is added to shopping cart, and save it by the name klist.txt as follows:
/media/uploads/HinoNaka/mbed_shoppingcart_fig8.png
The list should be stored in GR-Peach_mbed-os_QRCode_ShoppingCart_node\public\list.

Application Execution

This application consists of 2 tabs. One is Shopping Cart and the other is QR Code Login. In this section, it is described that how those work.

As mentioned above, GR-PEACH_mbed-os-client-ZXingSample should be executed beforehand. For details on how to set up and execute GR-PEACH_mbed-os-client-ZXingSample, please refer to https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/. If the program works properly, you can see the following message in your terminal: /media/uploads/HinoNaka/mbed_shoppingcart_fig4.png

After it is confirmed that the program works properly, please follow the procedure below in order to execute this Web Application.

  • How to invoke this Web Application
    You can now run the application by invoking the following: /media/uploads/HinoNaka/shoppingcart_fig1.png
    Then, you should see the following message if the configuration is successfully done, :
    /media/uploads/HinoNaka/shoppingcart_fig2.png
    Please note that 8080 might be changed. It should depends on your PORT setting mentioned above. If you access the above URL using Web browser, you can see the following Smart Shopping Cart tab by default: /media/uploads/HinoNaka/mbed_shoppingcart_fig3.png

  • How Shopping Cart tab works
    When you decode QR code stored in GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode by GR-PEACH successfully, the item should be added to shopping cart as follows:
    /media/uploads/HinoNaka/mbed_shoppingcart_fig5.png

  • How QR Code Login tab works
    When you choose QR Code Login tab, you can see the following screen indicating it's Locked status.
    /media/uploads/HinoNaka/mbed_shoppingcart_fig6.png
    Then, if you decode the Unlock qrcode described in GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qr.pdf, screen should transit to the following one indicating it's Unlocked status.
    /media/uploads/HinoNaka/mbed_shoppingcart_fig7.png
    After that if you you decode the Lock qrcode described in the above qr.pdf, screen should re-transit to Locked status. In this way, the screen transits to Locked and Unlocked status in accordance with the decoded result of QR code.

How to Deploy this app on HEROKU

HEROKU ( https://id.heroku.com ) is PaaS (Platform as a Service) on which Node.js application can deploy free-of charge. By utilizing it, you can access mbed Shopping Cart and QR Code Login from mobile terminal.

Here is the procedure to deploy this application on HEROKU:

  1. Create your HEROKU account at https://signup.heroku.com/login if you haven't created it yet.
  2. Install Heroku Toolbelt
    32-bit: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x86.exe
    64-bit: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x64.exe )
  3. Launch command prompt (e.g. Windows PowerShell) and move to the project root directory. Then, invoke the command heroku login. At the first time, Email and Password is thought to be required. At that time, please type Email address and password registered at the step 1.
  4. Invoke the command git init
  5. Invoke the command git add . to prepare all the files staged for the next commit
  6. Invoke the command git commit -m "[commit message]" to commit the files staged at the step 5
  7. Invoke the command heroku create. If the command is successfully terminated, the remote repository heroku should be created and associated with the local repository
  8. Invoke the command git push heroku master If the command is successfully terminated, this application should be deployed to HEROKU and its URL should be shown as follows:

remote: -----> Launching...
remote:        Released v3
remote:        https://hogeoge.herokuapp.com/ deployed to Heroku

After all the steps are completed without error, please access the URL http:hogehoge.herokuapp.com/ (i.e URL where https in the URL shown in the step 7 is replaced with http) with Web browser. You should be able to show mbed Shopping Cart on Web browser.

-------------------------------------------------------------------------------------------------------------------------------------------------

Node.jsとnpmのインストール

本アプリケーションを実行するにあたっては、Node.jsとnpmのインストールが必要です。
お使いの開発環境(PC)にNode.js、npmがインストールされているかどうかは、下記コマンドで確認する事ができます。

node --version
npm --version

上記コマンド実行後、x.x.x というバージョン・リビジョン番号が表示されれば、Node.js、npmは既にインストールされていますので、次節以降の手順にしたがってアプリケーションのセットアップを行ってください。未インストールの場合は以降の手順にしたがってNode.js、npmをインストールしてください。

開発環境のホストOSがWindowsまたはmacの場合はhttps://nodejs.org/en/download から入手可能なインストーラを使用してインストールします。

開発環境のホストOSがLinuxの場合は、お使いのディストリビーションに応じたパッケージ管理システムを用いたインストールが可能です。詳細はhttps://nodejs.org/en/download/package-manager を参照ください。

前提条件

本アプリケーションを実行するにあたっては、GR-PEACH上のバーコードデータのデコード結果にmbed Device Connectorからアクセスする下記プログラムを事前にセットアップしておく必要があります。

Import programGR-PEACH_mbed-os-client-ZXingSample

Fork of https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/

アプリケーションの設定

本アプリケーションの実行するためには、.envファイルを介して以下に示すオプションを設定する必要があります。なお、.envファイルはGR-PEACH_mbed-os-QRCode-ShoppingCart-nodeフォルダに格納されています。

  • ACCESS_KEY 本変数にはmbed Device Connector上で生成可能なAccess Keyを設定します。Access Keyが未生成の場合は下記に従って作成してください。
    1. https://connector.mbed.com/#accesskeys にアクセスします。
    2. CREATE NEW ACCESS KEYをクリックします。
    /media/uploads/HinoNaka/screenshot7.png
    3. access keyの名称を入力するように促されたら、任意の名称(例えばdemo等)を入力し、ADDをクリックします。
    /media/uploads/HinoNaka/screenshot8.png

    access keyが正常に生成できたら、コピーして下記のように.envファイルでACCESS_KEYに設定します。

.env

ACCESS_KEY=...
  • PORT 本変数にはWebアプリへのアクセスに使用するポート番号を下記のように設定します。デフォルトのポート番号は 8080 です。8080から変更の必要がなければ、設定は省略可能です。

.env

PORT=...

また、ショッピングカートに追加する品目と値段をカンマ区切りで下記のように記載したリストを準備し、klist.txtという名称でGR-Peach_mbed-os_QRCode_ShoppingCart_node\public\listフォルダに格納してください。

/media/uploads/HinoNaka/mbed_shoppingcart_fig8.png

アプリケーションの実行

本アプリケーションでは、Shopping CartQR Code Loginという2つのタブが実装されています。以下、それぞれの動作方法について記載します。
なお上述の通り、本アプリケーションの実行に際しては、事前にGR-PEACH_mbed-os-client-ZXingSampleを実行しておく必要があります。GR-PEACH_mbed-os-client-ZXingSampleのセットアップ方法、および実行方法に関しては、https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/ を参照ください。プログラムが正常に動作している場合、下記のメッセージがターミナルに表示されます。
/media/uploads/HinoNaka/mbed_shoppingcart_fig4.png

プログラムの正常動作が確認できたら、以降の手順に従ってWebアプリケーションを実行します。

  • Webアプリケーションの起動
    下記コマンドでWebアプリケーションを起動可能です。
    /media/uploads/HinoNaka/shoppingcart_fig1.png
    上述のアプリケーション設定が正常に行われていれば、下記メッセージが表示されます。
    /media/uploads/HinoNaka/shoppingcart_fig2.png
    なお、8080PORT設定に応じた値となります。
    続いて、上述のURLにWebブラウザでアクセスすると、下記のSmart Shopping Cartの画面が表示されます。
    /media/uploads/HinoNaka/mbed_shoppingcart_fig3.png

  • Shopping Cartタブ
    GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載されている Birthday CakeParty CupsBeer KegsPound of beefBuflle-proof vest のQRコードをデコードすると、下記のようにデコードしたアイテムが都度ショッピングカートに追加されます。
    /media/uploads/HinoNaka/mbed_shoppingcart_fig5.png

  • QR Code Loginタブ
    このタブを選択すると、下記のLock状態を示す画面が表示されます。 /media/uploads/HinoNaka/mbed_shoppingcart_fig6.png
    ここで、GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載のUnlock QRコードをデコードすると、Unlock状態を示す下記の画面に遷移します。 /media/uploads/HinoNaka/mbed_shoppingcart_fig7.png

    この後、Lock QRコードをデコードすると画面はLock状態に再度遷移します。

    このようにQR Code Loginタブでは、LockUnlockのQRコードをデコードする都度、対応する画面に遷移するアプリケーションです。

HEROKUへのデプロイ

HEROKU ( https://id.heroku.com) はNode.jsアプリが無償でデプロイ可能なPaaS (Platform as a Service)と呼ばれるサービスです。HEROKUを活用する事で、mbed Shopping CartQR Code Loginにモバイル端末等からアクセスする事が可能となります。

以下、HEROKUへ本アプリをデプロイする手順を説明します。

  1. HEROKUのアカウントを所有していない場合は https://signup.heroku.com/login でアカウントを作成してください
  2. Heroku Toolbeltをインストールします
    32-bit版: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x86.exe
    64-bit版: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x64.exe )
  3. ターミナルソフトウェア(例えばWindows PowerShell)を立上げます。そして本アプリのルートディレクトリへ移動し、heroku loginコマンドを実行します。Emailアドレスとパスワードの入力を求められた場合は、アカウント生成時に入力したアドレスとパスワードを入力してください。
  4. git initコマンドを実行します
  5. git add .コマンドを実行し、全ファイルをコミット対象に設定します
  6. git commit -m "[commit message]" で、全ファイルをコミットします
  7. heroku createを実行します。本コマンドが正常終了すると、リモートリポジトリ herokuが設定されます
  8. git push heroku master本コマンドが正常終了すると、HEROKUへのデプロイが完了し、下記のように本WebアプリのURLが表示されます

remote: -----> Launching...
remote:        Released v3
remote:        https://hogeoge.herokuapp.com/ deployed to Heroku

上記の全ての手順が完了したら、http:hogehoge.herokuapp.com/ ( 8. で表示されたURL中のhttpshttpに置換えたもの)へブラウザ等でアクセスします。途中でエラーが発生していなければ、mbed Shopping CartがWebブラウザ上に表示されます。

Committer:
Osamu Nakamura
Date:
Fri Jan 12 19:05:14 2018 +0900
Revision:
0:a40b9a259b52
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Osamu Nakamura 0:a40b9a259b52 1 !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 2
Osamu Nakamura 0:a40b9a259b52 3 module.exports = _dereq_('./lib/');
Osamu Nakamura 0:a40b9a259b52 4
Osamu Nakamura 0:a40b9a259b52 5 },{"./lib/":2}],2:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 6
Osamu Nakamura 0:a40b9a259b52 7 /**
Osamu Nakamura 0:a40b9a259b52 8 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 9 */
Osamu Nakamura 0:a40b9a259b52 10
Osamu Nakamura 0:a40b9a259b52 11 var url = _dereq_('./url');
Osamu Nakamura 0:a40b9a259b52 12 var parser = _dereq_('socket.io-parser');
Osamu Nakamura 0:a40b9a259b52 13 var Manager = _dereq_('./manager');
Osamu Nakamura 0:a40b9a259b52 14 var debug = _dereq_('debug')('socket.io-client');
Osamu Nakamura 0:a40b9a259b52 15
Osamu Nakamura 0:a40b9a259b52 16 /**
Osamu Nakamura 0:a40b9a259b52 17 * Module exports.
Osamu Nakamura 0:a40b9a259b52 18 */
Osamu Nakamura 0:a40b9a259b52 19
Osamu Nakamura 0:a40b9a259b52 20 module.exports = exports = lookup;
Osamu Nakamura 0:a40b9a259b52 21
Osamu Nakamura 0:a40b9a259b52 22 /**
Osamu Nakamura 0:a40b9a259b52 23 * Managers cache.
Osamu Nakamura 0:a40b9a259b52 24 */
Osamu Nakamura 0:a40b9a259b52 25
Osamu Nakamura 0:a40b9a259b52 26 var cache = exports.managers = {};
Osamu Nakamura 0:a40b9a259b52 27
Osamu Nakamura 0:a40b9a259b52 28 /**
Osamu Nakamura 0:a40b9a259b52 29 * Looks up an existing `Manager` for multiplexing.
Osamu Nakamura 0:a40b9a259b52 30 * If the user summons:
Osamu Nakamura 0:a40b9a259b52 31 *
Osamu Nakamura 0:a40b9a259b52 32 * `io('http://localhost/a');`
Osamu Nakamura 0:a40b9a259b52 33 * `io('http://localhost/b');`
Osamu Nakamura 0:a40b9a259b52 34 *
Osamu Nakamura 0:a40b9a259b52 35 * We reuse the existing instance based on same scheme/port/host,
Osamu Nakamura 0:a40b9a259b52 36 * and we initialize sockets for each namespace.
Osamu Nakamura 0:a40b9a259b52 37 *
Osamu Nakamura 0:a40b9a259b52 38 * @api public
Osamu Nakamura 0:a40b9a259b52 39 */
Osamu Nakamura 0:a40b9a259b52 40
Osamu Nakamura 0:a40b9a259b52 41 function lookup(uri, opts) {
Osamu Nakamura 0:a40b9a259b52 42 if (typeof uri == 'object') {
Osamu Nakamura 0:a40b9a259b52 43 opts = uri;
Osamu Nakamura 0:a40b9a259b52 44 uri = undefined;
Osamu Nakamura 0:a40b9a259b52 45 }
Osamu Nakamura 0:a40b9a259b52 46
Osamu Nakamura 0:a40b9a259b52 47 opts = opts || {};
Osamu Nakamura 0:a40b9a259b52 48
Osamu Nakamura 0:a40b9a259b52 49 var parsed = url(uri);
Osamu Nakamura 0:a40b9a259b52 50 var source = parsed.source;
Osamu Nakamura 0:a40b9a259b52 51 var id = parsed.id;
Osamu Nakamura 0:a40b9a259b52 52 var path = parsed.path;
Osamu Nakamura 0:a40b9a259b52 53 var sameNamespace = (cache[id] && cache[id].nsps[path] &&
Osamu Nakamura 0:a40b9a259b52 54 path == cache[id].nsps[path].nsp);
Osamu Nakamura 0:a40b9a259b52 55 var newConnection = opts.forceNew || opts['force new connection'] ||
Osamu Nakamura 0:a40b9a259b52 56 false === opts.multiplex || sameNamespace;
Osamu Nakamura 0:a40b9a259b52 57
Osamu Nakamura 0:a40b9a259b52 58 var io;
Osamu Nakamura 0:a40b9a259b52 59
Osamu Nakamura 0:a40b9a259b52 60 if (newConnection) {
Osamu Nakamura 0:a40b9a259b52 61 debug('ignoring socket cache for %s', source);
Osamu Nakamura 0:a40b9a259b52 62 io = Manager(source, opts);
Osamu Nakamura 0:a40b9a259b52 63 } else {
Osamu Nakamura 0:a40b9a259b52 64 if (!cache[id]) {
Osamu Nakamura 0:a40b9a259b52 65 debug('new io instance for %s', source);
Osamu Nakamura 0:a40b9a259b52 66 cache[id] = Manager(source, opts);
Osamu Nakamura 0:a40b9a259b52 67 }
Osamu Nakamura 0:a40b9a259b52 68 io = cache[id];
Osamu Nakamura 0:a40b9a259b52 69 }
Osamu Nakamura 0:a40b9a259b52 70
Osamu Nakamura 0:a40b9a259b52 71 return io.socket(parsed.path);
Osamu Nakamura 0:a40b9a259b52 72 }
Osamu Nakamura 0:a40b9a259b52 73
Osamu Nakamura 0:a40b9a259b52 74 /**
Osamu Nakamura 0:a40b9a259b52 75 * Protocol version.
Osamu Nakamura 0:a40b9a259b52 76 *
Osamu Nakamura 0:a40b9a259b52 77 * @api public
Osamu Nakamura 0:a40b9a259b52 78 */
Osamu Nakamura 0:a40b9a259b52 79
Osamu Nakamura 0:a40b9a259b52 80 exports.protocol = parser.protocol;
Osamu Nakamura 0:a40b9a259b52 81
Osamu Nakamura 0:a40b9a259b52 82 /**
Osamu Nakamura 0:a40b9a259b52 83 * `connect`.
Osamu Nakamura 0:a40b9a259b52 84 *
Osamu Nakamura 0:a40b9a259b52 85 * @param {String} uri
Osamu Nakamura 0:a40b9a259b52 86 * @api public
Osamu Nakamura 0:a40b9a259b52 87 */
Osamu Nakamura 0:a40b9a259b52 88
Osamu Nakamura 0:a40b9a259b52 89 exports.connect = lookup;
Osamu Nakamura 0:a40b9a259b52 90
Osamu Nakamura 0:a40b9a259b52 91 /**
Osamu Nakamura 0:a40b9a259b52 92 * Expose constructors for standalone build.
Osamu Nakamura 0:a40b9a259b52 93 *
Osamu Nakamura 0:a40b9a259b52 94 * @api public
Osamu Nakamura 0:a40b9a259b52 95 */
Osamu Nakamura 0:a40b9a259b52 96
Osamu Nakamura 0:a40b9a259b52 97 exports.Manager = _dereq_('./manager');
Osamu Nakamura 0:a40b9a259b52 98 exports.Socket = _dereq_('./socket');
Osamu Nakamura 0:a40b9a259b52 99
Osamu Nakamura 0:a40b9a259b52 100 },{"./manager":3,"./socket":5,"./url":6,"debug":10,"socket.io-parser":46}],3:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 101
Osamu Nakamura 0:a40b9a259b52 102 /**
Osamu Nakamura 0:a40b9a259b52 103 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 104 */
Osamu Nakamura 0:a40b9a259b52 105
Osamu Nakamura 0:a40b9a259b52 106 var url = _dereq_('./url');
Osamu Nakamura 0:a40b9a259b52 107 var eio = _dereq_('engine.io-client');
Osamu Nakamura 0:a40b9a259b52 108 var Socket = _dereq_('./socket');
Osamu Nakamura 0:a40b9a259b52 109 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 110 var parser = _dereq_('socket.io-parser');
Osamu Nakamura 0:a40b9a259b52 111 var on = _dereq_('./on');
Osamu Nakamura 0:a40b9a259b52 112 var bind = _dereq_('component-bind');
Osamu Nakamura 0:a40b9a259b52 113 var object = _dereq_('object-component');
Osamu Nakamura 0:a40b9a259b52 114 var debug = _dereq_('debug')('socket.io-client:manager');
Osamu Nakamura 0:a40b9a259b52 115 var indexOf = _dereq_('indexof');
Osamu Nakamura 0:a40b9a259b52 116 var Backoff = _dereq_('backo2');
Osamu Nakamura 0:a40b9a259b52 117
Osamu Nakamura 0:a40b9a259b52 118 /**
Osamu Nakamura 0:a40b9a259b52 119 * Module exports
Osamu Nakamura 0:a40b9a259b52 120 */
Osamu Nakamura 0:a40b9a259b52 121
Osamu Nakamura 0:a40b9a259b52 122 module.exports = Manager;
Osamu Nakamura 0:a40b9a259b52 123
Osamu Nakamura 0:a40b9a259b52 124 /**
Osamu Nakamura 0:a40b9a259b52 125 * `Manager` constructor.
Osamu Nakamura 0:a40b9a259b52 126 *
Osamu Nakamura 0:a40b9a259b52 127 * @param {String} engine instance or engine uri/opts
Osamu Nakamura 0:a40b9a259b52 128 * @param {Object} options
Osamu Nakamura 0:a40b9a259b52 129 * @api public
Osamu Nakamura 0:a40b9a259b52 130 */
Osamu Nakamura 0:a40b9a259b52 131
Osamu Nakamura 0:a40b9a259b52 132 function Manager(uri, opts){
Osamu Nakamura 0:a40b9a259b52 133 if (!(this instanceof Manager)) return new Manager(uri, opts);
Osamu Nakamura 0:a40b9a259b52 134 if (uri && ('object' == typeof uri)) {
Osamu Nakamura 0:a40b9a259b52 135 opts = uri;
Osamu Nakamura 0:a40b9a259b52 136 uri = undefined;
Osamu Nakamura 0:a40b9a259b52 137 }
Osamu Nakamura 0:a40b9a259b52 138 opts = opts || {};
Osamu Nakamura 0:a40b9a259b52 139
Osamu Nakamura 0:a40b9a259b52 140 opts.path = opts.path || '/socket.io';
Osamu Nakamura 0:a40b9a259b52 141 this.nsps = {};
Osamu Nakamura 0:a40b9a259b52 142 this.subs = [];
Osamu Nakamura 0:a40b9a259b52 143 this.opts = opts;
Osamu Nakamura 0:a40b9a259b52 144 this.reconnection(opts.reconnection !== false);
Osamu Nakamura 0:a40b9a259b52 145 this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
Osamu Nakamura 0:a40b9a259b52 146 this.reconnectionDelay(opts.reconnectionDelay || 1000);
Osamu Nakamura 0:a40b9a259b52 147 this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
Osamu Nakamura 0:a40b9a259b52 148 this.randomizationFactor(opts.randomizationFactor || 0.5);
Osamu Nakamura 0:a40b9a259b52 149 this.backoff = new Backoff({
Osamu Nakamura 0:a40b9a259b52 150 min: this.reconnectionDelay(),
Osamu Nakamura 0:a40b9a259b52 151 max: this.reconnectionDelayMax(),
Osamu Nakamura 0:a40b9a259b52 152 jitter: this.randomizationFactor()
Osamu Nakamura 0:a40b9a259b52 153 });
Osamu Nakamura 0:a40b9a259b52 154 this.timeout(null == opts.timeout ? 20000 : opts.timeout);
Osamu Nakamura 0:a40b9a259b52 155 this.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 156 this.uri = uri;
Osamu Nakamura 0:a40b9a259b52 157 this.connected = [];
Osamu Nakamura 0:a40b9a259b52 158 this.encoding = false;
Osamu Nakamura 0:a40b9a259b52 159 this.packetBuffer = [];
Osamu Nakamura 0:a40b9a259b52 160 this.encoder = new parser.Encoder();
Osamu Nakamura 0:a40b9a259b52 161 this.decoder = new parser.Decoder();
Osamu Nakamura 0:a40b9a259b52 162 this.autoConnect = opts.autoConnect !== false;
Osamu Nakamura 0:a40b9a259b52 163 if (this.autoConnect) this.open();
Osamu Nakamura 0:a40b9a259b52 164 }
Osamu Nakamura 0:a40b9a259b52 165
Osamu Nakamura 0:a40b9a259b52 166 /**
Osamu Nakamura 0:a40b9a259b52 167 * Propagate given event to sockets and emit on `this`
Osamu Nakamura 0:a40b9a259b52 168 *
Osamu Nakamura 0:a40b9a259b52 169 * @api private
Osamu Nakamura 0:a40b9a259b52 170 */
Osamu Nakamura 0:a40b9a259b52 171
Osamu Nakamura 0:a40b9a259b52 172 Manager.prototype.emitAll = function() {
Osamu Nakamura 0:a40b9a259b52 173 this.emit.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 174 for (var nsp in this.nsps) {
Osamu Nakamura 0:a40b9a259b52 175 this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
Osamu Nakamura 0:a40b9a259b52 176 }
Osamu Nakamura 0:a40b9a259b52 177 };
Osamu Nakamura 0:a40b9a259b52 178
Osamu Nakamura 0:a40b9a259b52 179 /**
Osamu Nakamura 0:a40b9a259b52 180 * Update `socket.id` of all sockets
Osamu Nakamura 0:a40b9a259b52 181 *
Osamu Nakamura 0:a40b9a259b52 182 * @api private
Osamu Nakamura 0:a40b9a259b52 183 */
Osamu Nakamura 0:a40b9a259b52 184
Osamu Nakamura 0:a40b9a259b52 185 Manager.prototype.updateSocketIds = function(){
Osamu Nakamura 0:a40b9a259b52 186 for (var nsp in this.nsps) {
Osamu Nakamura 0:a40b9a259b52 187 this.nsps[nsp].id = this.engine.id;
Osamu Nakamura 0:a40b9a259b52 188 }
Osamu Nakamura 0:a40b9a259b52 189 };
Osamu Nakamura 0:a40b9a259b52 190
Osamu Nakamura 0:a40b9a259b52 191 /**
Osamu Nakamura 0:a40b9a259b52 192 * Mix in `Emitter`.
Osamu Nakamura 0:a40b9a259b52 193 */
Osamu Nakamura 0:a40b9a259b52 194
Osamu Nakamura 0:a40b9a259b52 195 Emitter(Manager.prototype);
Osamu Nakamura 0:a40b9a259b52 196
Osamu Nakamura 0:a40b9a259b52 197 /**
Osamu Nakamura 0:a40b9a259b52 198 * Sets the `reconnection` config.
Osamu Nakamura 0:a40b9a259b52 199 *
Osamu Nakamura 0:a40b9a259b52 200 * @param {Boolean} true/false if it should automatically reconnect
Osamu Nakamura 0:a40b9a259b52 201 * @return {Manager} self or value
Osamu Nakamura 0:a40b9a259b52 202 * @api public
Osamu Nakamura 0:a40b9a259b52 203 */
Osamu Nakamura 0:a40b9a259b52 204
Osamu Nakamura 0:a40b9a259b52 205 Manager.prototype.reconnection = function(v){
Osamu Nakamura 0:a40b9a259b52 206 if (!arguments.length) return this._reconnection;
Osamu Nakamura 0:a40b9a259b52 207 this._reconnection = !!v;
Osamu Nakamura 0:a40b9a259b52 208 return this;
Osamu Nakamura 0:a40b9a259b52 209 };
Osamu Nakamura 0:a40b9a259b52 210
Osamu Nakamura 0:a40b9a259b52 211 /**
Osamu Nakamura 0:a40b9a259b52 212 * Sets the reconnection attempts config.
Osamu Nakamura 0:a40b9a259b52 213 *
Osamu Nakamura 0:a40b9a259b52 214 * @param {Number} max reconnection attempts before giving up
Osamu Nakamura 0:a40b9a259b52 215 * @return {Manager} self or value
Osamu Nakamura 0:a40b9a259b52 216 * @api public
Osamu Nakamura 0:a40b9a259b52 217 */
Osamu Nakamura 0:a40b9a259b52 218
Osamu Nakamura 0:a40b9a259b52 219 Manager.prototype.reconnectionAttempts = function(v){
Osamu Nakamura 0:a40b9a259b52 220 if (!arguments.length) return this._reconnectionAttempts;
Osamu Nakamura 0:a40b9a259b52 221 this._reconnectionAttempts = v;
Osamu Nakamura 0:a40b9a259b52 222 return this;
Osamu Nakamura 0:a40b9a259b52 223 };
Osamu Nakamura 0:a40b9a259b52 224
Osamu Nakamura 0:a40b9a259b52 225 /**
Osamu Nakamura 0:a40b9a259b52 226 * Sets the delay between reconnections.
Osamu Nakamura 0:a40b9a259b52 227 *
Osamu Nakamura 0:a40b9a259b52 228 * @param {Number} delay
Osamu Nakamura 0:a40b9a259b52 229 * @return {Manager} self or value
Osamu Nakamura 0:a40b9a259b52 230 * @api public
Osamu Nakamura 0:a40b9a259b52 231 */
Osamu Nakamura 0:a40b9a259b52 232
Osamu Nakamura 0:a40b9a259b52 233 Manager.prototype.reconnectionDelay = function(v){
Osamu Nakamura 0:a40b9a259b52 234 if (!arguments.length) return this._reconnectionDelay;
Osamu Nakamura 0:a40b9a259b52 235 this._reconnectionDelay = v;
Osamu Nakamura 0:a40b9a259b52 236 this.backoff && this.backoff.setMin(v);
Osamu Nakamura 0:a40b9a259b52 237 return this;
Osamu Nakamura 0:a40b9a259b52 238 };
Osamu Nakamura 0:a40b9a259b52 239
Osamu Nakamura 0:a40b9a259b52 240 Manager.prototype.randomizationFactor = function(v){
Osamu Nakamura 0:a40b9a259b52 241 if (!arguments.length) return this._randomizationFactor;
Osamu Nakamura 0:a40b9a259b52 242 this._randomizationFactor = v;
Osamu Nakamura 0:a40b9a259b52 243 this.backoff && this.backoff.setJitter(v);
Osamu Nakamura 0:a40b9a259b52 244 return this;
Osamu Nakamura 0:a40b9a259b52 245 };
Osamu Nakamura 0:a40b9a259b52 246
Osamu Nakamura 0:a40b9a259b52 247 /**
Osamu Nakamura 0:a40b9a259b52 248 * Sets the maximum delay between reconnections.
Osamu Nakamura 0:a40b9a259b52 249 *
Osamu Nakamura 0:a40b9a259b52 250 * @param {Number} delay
Osamu Nakamura 0:a40b9a259b52 251 * @return {Manager} self or value
Osamu Nakamura 0:a40b9a259b52 252 * @api public
Osamu Nakamura 0:a40b9a259b52 253 */
Osamu Nakamura 0:a40b9a259b52 254
Osamu Nakamura 0:a40b9a259b52 255 Manager.prototype.reconnectionDelayMax = function(v){
Osamu Nakamura 0:a40b9a259b52 256 if (!arguments.length) return this._reconnectionDelayMax;
Osamu Nakamura 0:a40b9a259b52 257 this._reconnectionDelayMax = v;
Osamu Nakamura 0:a40b9a259b52 258 this.backoff && this.backoff.setMax(v);
Osamu Nakamura 0:a40b9a259b52 259 return this;
Osamu Nakamura 0:a40b9a259b52 260 };
Osamu Nakamura 0:a40b9a259b52 261
Osamu Nakamura 0:a40b9a259b52 262 /**
Osamu Nakamura 0:a40b9a259b52 263 * Sets the connection timeout. `false` to disable
Osamu Nakamura 0:a40b9a259b52 264 *
Osamu Nakamura 0:a40b9a259b52 265 * @return {Manager} self or value
Osamu Nakamura 0:a40b9a259b52 266 * @api public
Osamu Nakamura 0:a40b9a259b52 267 */
Osamu Nakamura 0:a40b9a259b52 268
Osamu Nakamura 0:a40b9a259b52 269 Manager.prototype.timeout = function(v){
Osamu Nakamura 0:a40b9a259b52 270 if (!arguments.length) return this._timeout;
Osamu Nakamura 0:a40b9a259b52 271 this._timeout = v;
Osamu Nakamura 0:a40b9a259b52 272 return this;
Osamu Nakamura 0:a40b9a259b52 273 };
Osamu Nakamura 0:a40b9a259b52 274
Osamu Nakamura 0:a40b9a259b52 275 /**
Osamu Nakamura 0:a40b9a259b52 276 * Starts trying to reconnect if reconnection is enabled and we have not
Osamu Nakamura 0:a40b9a259b52 277 * started reconnecting yet
Osamu Nakamura 0:a40b9a259b52 278 *
Osamu Nakamura 0:a40b9a259b52 279 * @api private
Osamu Nakamura 0:a40b9a259b52 280 */
Osamu Nakamura 0:a40b9a259b52 281
Osamu Nakamura 0:a40b9a259b52 282 Manager.prototype.maybeReconnectOnOpen = function() {
Osamu Nakamura 0:a40b9a259b52 283 // Only try to reconnect if it's the first time we're connecting
Osamu Nakamura 0:a40b9a259b52 284 if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
Osamu Nakamura 0:a40b9a259b52 285 // keeps reconnection from firing twice for the same reconnection loop
Osamu Nakamura 0:a40b9a259b52 286 this.reconnect();
Osamu Nakamura 0:a40b9a259b52 287 }
Osamu Nakamura 0:a40b9a259b52 288 };
Osamu Nakamura 0:a40b9a259b52 289
Osamu Nakamura 0:a40b9a259b52 290
Osamu Nakamura 0:a40b9a259b52 291 /**
Osamu Nakamura 0:a40b9a259b52 292 * Sets the current transport `socket`.
Osamu Nakamura 0:a40b9a259b52 293 *
Osamu Nakamura 0:a40b9a259b52 294 * @param {Function} optional, callback
Osamu Nakamura 0:a40b9a259b52 295 * @return {Manager} self
Osamu Nakamura 0:a40b9a259b52 296 * @api public
Osamu Nakamura 0:a40b9a259b52 297 */
Osamu Nakamura 0:a40b9a259b52 298
Osamu Nakamura 0:a40b9a259b52 299 Manager.prototype.open =
Osamu Nakamura 0:a40b9a259b52 300 Manager.prototype.connect = function(fn){
Osamu Nakamura 0:a40b9a259b52 301 debug('readyState %s', this.readyState);
Osamu Nakamura 0:a40b9a259b52 302 if (~this.readyState.indexOf('open')) return this;
Osamu Nakamura 0:a40b9a259b52 303
Osamu Nakamura 0:a40b9a259b52 304 debug('opening %s', this.uri);
Osamu Nakamura 0:a40b9a259b52 305 this.engine = eio(this.uri, this.opts);
Osamu Nakamura 0:a40b9a259b52 306 var socket = this.engine;
Osamu Nakamura 0:a40b9a259b52 307 var self = this;
Osamu Nakamura 0:a40b9a259b52 308 this.readyState = 'opening';
Osamu Nakamura 0:a40b9a259b52 309 this.skipReconnect = false;
Osamu Nakamura 0:a40b9a259b52 310
Osamu Nakamura 0:a40b9a259b52 311 // emit `open`
Osamu Nakamura 0:a40b9a259b52 312 var openSub = on(socket, 'open', function() {
Osamu Nakamura 0:a40b9a259b52 313 self.onopen();
Osamu Nakamura 0:a40b9a259b52 314 fn && fn();
Osamu Nakamura 0:a40b9a259b52 315 });
Osamu Nakamura 0:a40b9a259b52 316
Osamu Nakamura 0:a40b9a259b52 317 // emit `connect_error`
Osamu Nakamura 0:a40b9a259b52 318 var errorSub = on(socket, 'error', function(data){
Osamu Nakamura 0:a40b9a259b52 319 debug('connect_error');
Osamu Nakamura 0:a40b9a259b52 320 self.cleanup();
Osamu Nakamura 0:a40b9a259b52 321 self.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 322 self.emitAll('connect_error', data);
Osamu Nakamura 0:a40b9a259b52 323 if (fn) {
Osamu Nakamura 0:a40b9a259b52 324 var err = new Error('Connection error');
Osamu Nakamura 0:a40b9a259b52 325 err.data = data;
Osamu Nakamura 0:a40b9a259b52 326 fn(err);
Osamu Nakamura 0:a40b9a259b52 327 } else {
Osamu Nakamura 0:a40b9a259b52 328 // Only do this if there is no fn to handle the error
Osamu Nakamura 0:a40b9a259b52 329 self.maybeReconnectOnOpen();
Osamu Nakamura 0:a40b9a259b52 330 }
Osamu Nakamura 0:a40b9a259b52 331 });
Osamu Nakamura 0:a40b9a259b52 332
Osamu Nakamura 0:a40b9a259b52 333 // emit `connect_timeout`
Osamu Nakamura 0:a40b9a259b52 334 if (false !== this._timeout) {
Osamu Nakamura 0:a40b9a259b52 335 var timeout = this._timeout;
Osamu Nakamura 0:a40b9a259b52 336 debug('connect attempt will timeout after %d', timeout);
Osamu Nakamura 0:a40b9a259b52 337
Osamu Nakamura 0:a40b9a259b52 338 // set timer
Osamu Nakamura 0:a40b9a259b52 339 var timer = setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 340 debug('connect attempt timed out after %d', timeout);
Osamu Nakamura 0:a40b9a259b52 341 openSub.destroy();
Osamu Nakamura 0:a40b9a259b52 342 socket.close();
Osamu Nakamura 0:a40b9a259b52 343 socket.emit('error', 'timeout');
Osamu Nakamura 0:a40b9a259b52 344 self.emitAll('connect_timeout', timeout);
Osamu Nakamura 0:a40b9a259b52 345 }, timeout);
Osamu Nakamura 0:a40b9a259b52 346
Osamu Nakamura 0:a40b9a259b52 347 this.subs.push({
Osamu Nakamura 0:a40b9a259b52 348 destroy: function(){
Osamu Nakamura 0:a40b9a259b52 349 clearTimeout(timer);
Osamu Nakamura 0:a40b9a259b52 350 }
Osamu Nakamura 0:a40b9a259b52 351 });
Osamu Nakamura 0:a40b9a259b52 352 }
Osamu Nakamura 0:a40b9a259b52 353
Osamu Nakamura 0:a40b9a259b52 354 this.subs.push(openSub);
Osamu Nakamura 0:a40b9a259b52 355 this.subs.push(errorSub);
Osamu Nakamura 0:a40b9a259b52 356
Osamu Nakamura 0:a40b9a259b52 357 return this;
Osamu Nakamura 0:a40b9a259b52 358 };
Osamu Nakamura 0:a40b9a259b52 359
Osamu Nakamura 0:a40b9a259b52 360 /**
Osamu Nakamura 0:a40b9a259b52 361 * Called upon transport open.
Osamu Nakamura 0:a40b9a259b52 362 *
Osamu Nakamura 0:a40b9a259b52 363 * @api private
Osamu Nakamura 0:a40b9a259b52 364 */
Osamu Nakamura 0:a40b9a259b52 365
Osamu Nakamura 0:a40b9a259b52 366 Manager.prototype.onopen = function(){
Osamu Nakamura 0:a40b9a259b52 367 debug('open');
Osamu Nakamura 0:a40b9a259b52 368
Osamu Nakamura 0:a40b9a259b52 369 // clear old subs
Osamu Nakamura 0:a40b9a259b52 370 this.cleanup();
Osamu Nakamura 0:a40b9a259b52 371
Osamu Nakamura 0:a40b9a259b52 372 // mark as open
Osamu Nakamura 0:a40b9a259b52 373 this.readyState = 'open';
Osamu Nakamura 0:a40b9a259b52 374 this.emit('open');
Osamu Nakamura 0:a40b9a259b52 375
Osamu Nakamura 0:a40b9a259b52 376 // add new subs
Osamu Nakamura 0:a40b9a259b52 377 var socket = this.engine;
Osamu Nakamura 0:a40b9a259b52 378 this.subs.push(on(socket, 'data', bind(this, 'ondata')));
Osamu Nakamura 0:a40b9a259b52 379 this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
Osamu Nakamura 0:a40b9a259b52 380 this.subs.push(on(socket, 'error', bind(this, 'onerror')));
Osamu Nakamura 0:a40b9a259b52 381 this.subs.push(on(socket, 'close', bind(this, 'onclose')));
Osamu Nakamura 0:a40b9a259b52 382 };
Osamu Nakamura 0:a40b9a259b52 383
Osamu Nakamura 0:a40b9a259b52 384 /**
Osamu Nakamura 0:a40b9a259b52 385 * Called with data.
Osamu Nakamura 0:a40b9a259b52 386 *
Osamu Nakamura 0:a40b9a259b52 387 * @api private
Osamu Nakamura 0:a40b9a259b52 388 */
Osamu Nakamura 0:a40b9a259b52 389
Osamu Nakamura 0:a40b9a259b52 390 Manager.prototype.ondata = function(data){
Osamu Nakamura 0:a40b9a259b52 391 this.decoder.add(data);
Osamu Nakamura 0:a40b9a259b52 392 };
Osamu Nakamura 0:a40b9a259b52 393
Osamu Nakamura 0:a40b9a259b52 394 /**
Osamu Nakamura 0:a40b9a259b52 395 * Called when parser fully decodes a packet.
Osamu Nakamura 0:a40b9a259b52 396 *
Osamu Nakamura 0:a40b9a259b52 397 * @api private
Osamu Nakamura 0:a40b9a259b52 398 */
Osamu Nakamura 0:a40b9a259b52 399
Osamu Nakamura 0:a40b9a259b52 400 Manager.prototype.ondecoded = function(packet) {
Osamu Nakamura 0:a40b9a259b52 401 this.emit('packet', packet);
Osamu Nakamura 0:a40b9a259b52 402 };
Osamu Nakamura 0:a40b9a259b52 403
Osamu Nakamura 0:a40b9a259b52 404 /**
Osamu Nakamura 0:a40b9a259b52 405 * Called upon socket error.
Osamu Nakamura 0:a40b9a259b52 406 *
Osamu Nakamura 0:a40b9a259b52 407 * @api private
Osamu Nakamura 0:a40b9a259b52 408 */
Osamu Nakamura 0:a40b9a259b52 409
Osamu Nakamura 0:a40b9a259b52 410 Manager.prototype.onerror = function(err){
Osamu Nakamura 0:a40b9a259b52 411 debug('error', err);
Osamu Nakamura 0:a40b9a259b52 412 this.emitAll('error', err);
Osamu Nakamura 0:a40b9a259b52 413 };
Osamu Nakamura 0:a40b9a259b52 414
Osamu Nakamura 0:a40b9a259b52 415 /**
Osamu Nakamura 0:a40b9a259b52 416 * Creates a new socket for the given `nsp`.
Osamu Nakamura 0:a40b9a259b52 417 *
Osamu Nakamura 0:a40b9a259b52 418 * @return {Socket}
Osamu Nakamura 0:a40b9a259b52 419 * @api public
Osamu Nakamura 0:a40b9a259b52 420 */
Osamu Nakamura 0:a40b9a259b52 421
Osamu Nakamura 0:a40b9a259b52 422 Manager.prototype.socket = function(nsp){
Osamu Nakamura 0:a40b9a259b52 423 var socket = this.nsps[nsp];
Osamu Nakamura 0:a40b9a259b52 424 if (!socket) {
Osamu Nakamura 0:a40b9a259b52 425 socket = new Socket(this, nsp);
Osamu Nakamura 0:a40b9a259b52 426 this.nsps[nsp] = socket;
Osamu Nakamura 0:a40b9a259b52 427 var self = this;
Osamu Nakamura 0:a40b9a259b52 428 socket.on('connect', function(){
Osamu Nakamura 0:a40b9a259b52 429 socket.id = self.engine.id;
Osamu Nakamura 0:a40b9a259b52 430 if (!~indexOf(self.connected, socket)) {
Osamu Nakamura 0:a40b9a259b52 431 self.connected.push(socket);
Osamu Nakamura 0:a40b9a259b52 432 }
Osamu Nakamura 0:a40b9a259b52 433 });
Osamu Nakamura 0:a40b9a259b52 434 }
Osamu Nakamura 0:a40b9a259b52 435 return socket;
Osamu Nakamura 0:a40b9a259b52 436 };
Osamu Nakamura 0:a40b9a259b52 437
Osamu Nakamura 0:a40b9a259b52 438 /**
Osamu Nakamura 0:a40b9a259b52 439 * Called upon a socket close.
Osamu Nakamura 0:a40b9a259b52 440 *
Osamu Nakamura 0:a40b9a259b52 441 * @param {Socket} socket
Osamu Nakamura 0:a40b9a259b52 442 */
Osamu Nakamura 0:a40b9a259b52 443
Osamu Nakamura 0:a40b9a259b52 444 Manager.prototype.destroy = function(socket){
Osamu Nakamura 0:a40b9a259b52 445 var index = indexOf(this.connected, socket);
Osamu Nakamura 0:a40b9a259b52 446 if (~index) this.connected.splice(index, 1);
Osamu Nakamura 0:a40b9a259b52 447 if (this.connected.length) return;
Osamu Nakamura 0:a40b9a259b52 448
Osamu Nakamura 0:a40b9a259b52 449 this.close();
Osamu Nakamura 0:a40b9a259b52 450 };
Osamu Nakamura 0:a40b9a259b52 451
Osamu Nakamura 0:a40b9a259b52 452 /**
Osamu Nakamura 0:a40b9a259b52 453 * Writes a packet.
Osamu Nakamura 0:a40b9a259b52 454 *
Osamu Nakamura 0:a40b9a259b52 455 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 456 * @api private
Osamu Nakamura 0:a40b9a259b52 457 */
Osamu Nakamura 0:a40b9a259b52 458
Osamu Nakamura 0:a40b9a259b52 459 Manager.prototype.packet = function(packet){
Osamu Nakamura 0:a40b9a259b52 460 debug('writing packet %j', packet);
Osamu Nakamura 0:a40b9a259b52 461 var self = this;
Osamu Nakamura 0:a40b9a259b52 462
Osamu Nakamura 0:a40b9a259b52 463 if (!self.encoding) {
Osamu Nakamura 0:a40b9a259b52 464 // encode, then write to engine with result
Osamu Nakamura 0:a40b9a259b52 465 self.encoding = true;
Osamu Nakamura 0:a40b9a259b52 466 this.encoder.encode(packet, function(encodedPackets) {
Osamu Nakamura 0:a40b9a259b52 467 for (var i = 0; i < encodedPackets.length; i++) {
Osamu Nakamura 0:a40b9a259b52 468 self.engine.write(encodedPackets[i]);
Osamu Nakamura 0:a40b9a259b52 469 }
Osamu Nakamura 0:a40b9a259b52 470 self.encoding = false;
Osamu Nakamura 0:a40b9a259b52 471 self.processPacketQueue();
Osamu Nakamura 0:a40b9a259b52 472 });
Osamu Nakamura 0:a40b9a259b52 473 } else { // add packet to the queue
Osamu Nakamura 0:a40b9a259b52 474 self.packetBuffer.push(packet);
Osamu Nakamura 0:a40b9a259b52 475 }
Osamu Nakamura 0:a40b9a259b52 476 };
Osamu Nakamura 0:a40b9a259b52 477
Osamu Nakamura 0:a40b9a259b52 478 /**
Osamu Nakamura 0:a40b9a259b52 479 * If packet buffer is non-empty, begins encoding the
Osamu Nakamura 0:a40b9a259b52 480 * next packet in line.
Osamu Nakamura 0:a40b9a259b52 481 *
Osamu Nakamura 0:a40b9a259b52 482 * @api private
Osamu Nakamura 0:a40b9a259b52 483 */
Osamu Nakamura 0:a40b9a259b52 484
Osamu Nakamura 0:a40b9a259b52 485 Manager.prototype.processPacketQueue = function() {
Osamu Nakamura 0:a40b9a259b52 486 if (this.packetBuffer.length > 0 && !this.encoding) {
Osamu Nakamura 0:a40b9a259b52 487 var pack = this.packetBuffer.shift();
Osamu Nakamura 0:a40b9a259b52 488 this.packet(pack);
Osamu Nakamura 0:a40b9a259b52 489 }
Osamu Nakamura 0:a40b9a259b52 490 };
Osamu Nakamura 0:a40b9a259b52 491
Osamu Nakamura 0:a40b9a259b52 492 /**
Osamu Nakamura 0:a40b9a259b52 493 * Clean up transport subscriptions and packet buffer.
Osamu Nakamura 0:a40b9a259b52 494 *
Osamu Nakamura 0:a40b9a259b52 495 * @api private
Osamu Nakamura 0:a40b9a259b52 496 */
Osamu Nakamura 0:a40b9a259b52 497
Osamu Nakamura 0:a40b9a259b52 498 Manager.prototype.cleanup = function(){
Osamu Nakamura 0:a40b9a259b52 499 var sub;
Osamu Nakamura 0:a40b9a259b52 500 while (sub = this.subs.shift()) sub.destroy();
Osamu Nakamura 0:a40b9a259b52 501
Osamu Nakamura 0:a40b9a259b52 502 this.packetBuffer = [];
Osamu Nakamura 0:a40b9a259b52 503 this.encoding = false;
Osamu Nakamura 0:a40b9a259b52 504
Osamu Nakamura 0:a40b9a259b52 505 this.decoder.destroy();
Osamu Nakamura 0:a40b9a259b52 506 };
Osamu Nakamura 0:a40b9a259b52 507
Osamu Nakamura 0:a40b9a259b52 508 /**
Osamu Nakamura 0:a40b9a259b52 509 * Close the current socket.
Osamu Nakamura 0:a40b9a259b52 510 *
Osamu Nakamura 0:a40b9a259b52 511 * @api private
Osamu Nakamura 0:a40b9a259b52 512 */
Osamu Nakamura 0:a40b9a259b52 513
Osamu Nakamura 0:a40b9a259b52 514 Manager.prototype.close =
Osamu Nakamura 0:a40b9a259b52 515 Manager.prototype.disconnect = function(){
Osamu Nakamura 0:a40b9a259b52 516 this.skipReconnect = true;
Osamu Nakamura 0:a40b9a259b52 517 this.backoff.reset();
Osamu Nakamura 0:a40b9a259b52 518 this.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 519 this.engine && this.engine.close();
Osamu Nakamura 0:a40b9a259b52 520 };
Osamu Nakamura 0:a40b9a259b52 521
Osamu Nakamura 0:a40b9a259b52 522 /**
Osamu Nakamura 0:a40b9a259b52 523 * Called upon engine close.
Osamu Nakamura 0:a40b9a259b52 524 *
Osamu Nakamura 0:a40b9a259b52 525 * @api private
Osamu Nakamura 0:a40b9a259b52 526 */
Osamu Nakamura 0:a40b9a259b52 527
Osamu Nakamura 0:a40b9a259b52 528 Manager.prototype.onclose = function(reason){
Osamu Nakamura 0:a40b9a259b52 529 debug('close');
Osamu Nakamura 0:a40b9a259b52 530 this.cleanup();
Osamu Nakamura 0:a40b9a259b52 531 this.backoff.reset();
Osamu Nakamura 0:a40b9a259b52 532 this.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 533 this.emit('close', reason);
Osamu Nakamura 0:a40b9a259b52 534 if (this._reconnection && !this.skipReconnect) {
Osamu Nakamura 0:a40b9a259b52 535 this.reconnect();
Osamu Nakamura 0:a40b9a259b52 536 }
Osamu Nakamura 0:a40b9a259b52 537 };
Osamu Nakamura 0:a40b9a259b52 538
Osamu Nakamura 0:a40b9a259b52 539 /**
Osamu Nakamura 0:a40b9a259b52 540 * Attempt a reconnection.
Osamu Nakamura 0:a40b9a259b52 541 *
Osamu Nakamura 0:a40b9a259b52 542 * @api private
Osamu Nakamura 0:a40b9a259b52 543 */
Osamu Nakamura 0:a40b9a259b52 544
Osamu Nakamura 0:a40b9a259b52 545 Manager.prototype.reconnect = function(){
Osamu Nakamura 0:a40b9a259b52 546 if (this.reconnecting || this.skipReconnect) return this;
Osamu Nakamura 0:a40b9a259b52 547
Osamu Nakamura 0:a40b9a259b52 548 var self = this;
Osamu Nakamura 0:a40b9a259b52 549
Osamu Nakamura 0:a40b9a259b52 550 if (this.backoff.attempts >= this._reconnectionAttempts) {
Osamu Nakamura 0:a40b9a259b52 551 debug('reconnect failed');
Osamu Nakamura 0:a40b9a259b52 552 this.backoff.reset();
Osamu Nakamura 0:a40b9a259b52 553 this.emitAll('reconnect_failed');
Osamu Nakamura 0:a40b9a259b52 554 this.reconnecting = false;
Osamu Nakamura 0:a40b9a259b52 555 } else {
Osamu Nakamura 0:a40b9a259b52 556 var delay = this.backoff.duration();
Osamu Nakamura 0:a40b9a259b52 557 debug('will wait %dms before reconnect attempt', delay);
Osamu Nakamura 0:a40b9a259b52 558
Osamu Nakamura 0:a40b9a259b52 559 this.reconnecting = true;
Osamu Nakamura 0:a40b9a259b52 560 var timer = setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 561 if (self.skipReconnect) return;
Osamu Nakamura 0:a40b9a259b52 562
Osamu Nakamura 0:a40b9a259b52 563 debug('attempting reconnect');
Osamu Nakamura 0:a40b9a259b52 564 self.emitAll('reconnect_attempt', self.backoff.attempts);
Osamu Nakamura 0:a40b9a259b52 565 self.emitAll('reconnecting', self.backoff.attempts);
Osamu Nakamura 0:a40b9a259b52 566
Osamu Nakamura 0:a40b9a259b52 567 // check again for the case socket closed in above events
Osamu Nakamura 0:a40b9a259b52 568 if (self.skipReconnect) return;
Osamu Nakamura 0:a40b9a259b52 569
Osamu Nakamura 0:a40b9a259b52 570 self.open(function(err){
Osamu Nakamura 0:a40b9a259b52 571 if (err) {
Osamu Nakamura 0:a40b9a259b52 572 debug('reconnect attempt error');
Osamu Nakamura 0:a40b9a259b52 573 self.reconnecting = false;
Osamu Nakamura 0:a40b9a259b52 574 self.reconnect();
Osamu Nakamura 0:a40b9a259b52 575 self.emitAll('reconnect_error', err.data);
Osamu Nakamura 0:a40b9a259b52 576 } else {
Osamu Nakamura 0:a40b9a259b52 577 debug('reconnect success');
Osamu Nakamura 0:a40b9a259b52 578 self.onreconnect();
Osamu Nakamura 0:a40b9a259b52 579 }
Osamu Nakamura 0:a40b9a259b52 580 });
Osamu Nakamura 0:a40b9a259b52 581 }, delay);
Osamu Nakamura 0:a40b9a259b52 582
Osamu Nakamura 0:a40b9a259b52 583 this.subs.push({
Osamu Nakamura 0:a40b9a259b52 584 destroy: function(){
Osamu Nakamura 0:a40b9a259b52 585 clearTimeout(timer);
Osamu Nakamura 0:a40b9a259b52 586 }
Osamu Nakamura 0:a40b9a259b52 587 });
Osamu Nakamura 0:a40b9a259b52 588 }
Osamu Nakamura 0:a40b9a259b52 589 };
Osamu Nakamura 0:a40b9a259b52 590
Osamu Nakamura 0:a40b9a259b52 591 /**
Osamu Nakamura 0:a40b9a259b52 592 * Called upon successful reconnect.
Osamu Nakamura 0:a40b9a259b52 593 *
Osamu Nakamura 0:a40b9a259b52 594 * @api private
Osamu Nakamura 0:a40b9a259b52 595 */
Osamu Nakamura 0:a40b9a259b52 596
Osamu Nakamura 0:a40b9a259b52 597 Manager.prototype.onreconnect = function(){
Osamu Nakamura 0:a40b9a259b52 598 var attempt = this.backoff.attempts;
Osamu Nakamura 0:a40b9a259b52 599 this.reconnecting = false;
Osamu Nakamura 0:a40b9a259b52 600 this.backoff.reset();
Osamu Nakamura 0:a40b9a259b52 601 this.updateSocketIds();
Osamu Nakamura 0:a40b9a259b52 602 this.emitAll('reconnect', attempt);
Osamu Nakamura 0:a40b9a259b52 603 };
Osamu Nakamura 0:a40b9a259b52 604
Osamu Nakamura 0:a40b9a259b52 605 },{"./on":4,"./socket":5,"./url":6,"backo2":7,"component-bind":8,"component-emitter":9,"debug":10,"engine.io-client":11,"indexof":42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 606
Osamu Nakamura 0:a40b9a259b52 607 /**
Osamu Nakamura 0:a40b9a259b52 608 * Module exports.
Osamu Nakamura 0:a40b9a259b52 609 */
Osamu Nakamura 0:a40b9a259b52 610
Osamu Nakamura 0:a40b9a259b52 611 module.exports = on;
Osamu Nakamura 0:a40b9a259b52 612
Osamu Nakamura 0:a40b9a259b52 613 /**
Osamu Nakamura 0:a40b9a259b52 614 * Helper for subscriptions.
Osamu Nakamura 0:a40b9a259b52 615 *
Osamu Nakamura 0:a40b9a259b52 616 * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
Osamu Nakamura 0:a40b9a259b52 617 * @param {String} event name
Osamu Nakamura 0:a40b9a259b52 618 * @param {Function} callback
Osamu Nakamura 0:a40b9a259b52 619 * @api public
Osamu Nakamura 0:a40b9a259b52 620 */
Osamu Nakamura 0:a40b9a259b52 621
Osamu Nakamura 0:a40b9a259b52 622 function on(obj, ev, fn) {
Osamu Nakamura 0:a40b9a259b52 623 obj.on(ev, fn);
Osamu Nakamura 0:a40b9a259b52 624 return {
Osamu Nakamura 0:a40b9a259b52 625 destroy: function(){
Osamu Nakamura 0:a40b9a259b52 626 obj.removeListener(ev, fn);
Osamu Nakamura 0:a40b9a259b52 627 }
Osamu Nakamura 0:a40b9a259b52 628 };
Osamu Nakamura 0:a40b9a259b52 629 }
Osamu Nakamura 0:a40b9a259b52 630
Osamu Nakamura 0:a40b9a259b52 631 },{}],5:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 632
Osamu Nakamura 0:a40b9a259b52 633 /**
Osamu Nakamura 0:a40b9a259b52 634 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 635 */
Osamu Nakamura 0:a40b9a259b52 636
Osamu Nakamura 0:a40b9a259b52 637 var parser = _dereq_('socket.io-parser');
Osamu Nakamura 0:a40b9a259b52 638 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 639 var toArray = _dereq_('to-array');
Osamu Nakamura 0:a40b9a259b52 640 var on = _dereq_('./on');
Osamu Nakamura 0:a40b9a259b52 641 var bind = _dereq_('component-bind');
Osamu Nakamura 0:a40b9a259b52 642 var debug = _dereq_('debug')('socket.io-client:socket');
Osamu Nakamura 0:a40b9a259b52 643 var hasBin = _dereq_('has-binary');
Osamu Nakamura 0:a40b9a259b52 644
Osamu Nakamura 0:a40b9a259b52 645 /**
Osamu Nakamura 0:a40b9a259b52 646 * Module exports.
Osamu Nakamura 0:a40b9a259b52 647 */
Osamu Nakamura 0:a40b9a259b52 648
Osamu Nakamura 0:a40b9a259b52 649 module.exports = exports = Socket;
Osamu Nakamura 0:a40b9a259b52 650
Osamu Nakamura 0:a40b9a259b52 651 /**
Osamu Nakamura 0:a40b9a259b52 652 * Internal events (blacklisted).
Osamu Nakamura 0:a40b9a259b52 653 * These events can't be emitted by the user.
Osamu Nakamura 0:a40b9a259b52 654 *
Osamu Nakamura 0:a40b9a259b52 655 * @api private
Osamu Nakamura 0:a40b9a259b52 656 */
Osamu Nakamura 0:a40b9a259b52 657
Osamu Nakamura 0:a40b9a259b52 658 var events = {
Osamu Nakamura 0:a40b9a259b52 659 connect: 1,
Osamu Nakamura 0:a40b9a259b52 660 connect_error: 1,
Osamu Nakamura 0:a40b9a259b52 661 connect_timeout: 1,
Osamu Nakamura 0:a40b9a259b52 662 disconnect: 1,
Osamu Nakamura 0:a40b9a259b52 663 error: 1,
Osamu Nakamura 0:a40b9a259b52 664 reconnect: 1,
Osamu Nakamura 0:a40b9a259b52 665 reconnect_attempt: 1,
Osamu Nakamura 0:a40b9a259b52 666 reconnect_failed: 1,
Osamu Nakamura 0:a40b9a259b52 667 reconnect_error: 1,
Osamu Nakamura 0:a40b9a259b52 668 reconnecting: 1
Osamu Nakamura 0:a40b9a259b52 669 };
Osamu Nakamura 0:a40b9a259b52 670
Osamu Nakamura 0:a40b9a259b52 671 /**
Osamu Nakamura 0:a40b9a259b52 672 * Shortcut to `Emitter#emit`.
Osamu Nakamura 0:a40b9a259b52 673 */
Osamu Nakamura 0:a40b9a259b52 674
Osamu Nakamura 0:a40b9a259b52 675 var emit = Emitter.prototype.emit;
Osamu Nakamura 0:a40b9a259b52 676
Osamu Nakamura 0:a40b9a259b52 677 /**
Osamu Nakamura 0:a40b9a259b52 678 * `Socket` constructor.
Osamu Nakamura 0:a40b9a259b52 679 *
Osamu Nakamura 0:a40b9a259b52 680 * @api public
Osamu Nakamura 0:a40b9a259b52 681 */
Osamu Nakamura 0:a40b9a259b52 682
Osamu Nakamura 0:a40b9a259b52 683 function Socket(io, nsp){
Osamu Nakamura 0:a40b9a259b52 684 this.io = io;
Osamu Nakamura 0:a40b9a259b52 685 this.nsp = nsp;
Osamu Nakamura 0:a40b9a259b52 686 this.json = this; // compat
Osamu Nakamura 0:a40b9a259b52 687 this.ids = 0;
Osamu Nakamura 0:a40b9a259b52 688 this.acks = {};
Osamu Nakamura 0:a40b9a259b52 689 if (this.io.autoConnect) this.open();
Osamu Nakamura 0:a40b9a259b52 690 this.receiveBuffer = [];
Osamu Nakamura 0:a40b9a259b52 691 this.sendBuffer = [];
Osamu Nakamura 0:a40b9a259b52 692 this.connected = false;
Osamu Nakamura 0:a40b9a259b52 693 this.disconnected = true;
Osamu Nakamura 0:a40b9a259b52 694 }
Osamu Nakamura 0:a40b9a259b52 695
Osamu Nakamura 0:a40b9a259b52 696 /**
Osamu Nakamura 0:a40b9a259b52 697 * Mix in `Emitter`.
Osamu Nakamura 0:a40b9a259b52 698 */
Osamu Nakamura 0:a40b9a259b52 699
Osamu Nakamura 0:a40b9a259b52 700 Emitter(Socket.prototype);
Osamu Nakamura 0:a40b9a259b52 701
Osamu Nakamura 0:a40b9a259b52 702 /**
Osamu Nakamura 0:a40b9a259b52 703 * Subscribe to open, close and packet events
Osamu Nakamura 0:a40b9a259b52 704 *
Osamu Nakamura 0:a40b9a259b52 705 * @api private
Osamu Nakamura 0:a40b9a259b52 706 */
Osamu Nakamura 0:a40b9a259b52 707
Osamu Nakamura 0:a40b9a259b52 708 Socket.prototype.subEvents = function() {
Osamu Nakamura 0:a40b9a259b52 709 if (this.subs) return;
Osamu Nakamura 0:a40b9a259b52 710
Osamu Nakamura 0:a40b9a259b52 711 var io = this.io;
Osamu Nakamura 0:a40b9a259b52 712 this.subs = [
Osamu Nakamura 0:a40b9a259b52 713 on(io, 'open', bind(this, 'onopen')),
Osamu Nakamura 0:a40b9a259b52 714 on(io, 'packet', bind(this, 'onpacket')),
Osamu Nakamura 0:a40b9a259b52 715 on(io, 'close', bind(this, 'onclose'))
Osamu Nakamura 0:a40b9a259b52 716 ];
Osamu Nakamura 0:a40b9a259b52 717 };
Osamu Nakamura 0:a40b9a259b52 718
Osamu Nakamura 0:a40b9a259b52 719 /**
Osamu Nakamura 0:a40b9a259b52 720 * "Opens" the socket.
Osamu Nakamura 0:a40b9a259b52 721 *
Osamu Nakamura 0:a40b9a259b52 722 * @api public
Osamu Nakamura 0:a40b9a259b52 723 */
Osamu Nakamura 0:a40b9a259b52 724
Osamu Nakamura 0:a40b9a259b52 725 Socket.prototype.open =
Osamu Nakamura 0:a40b9a259b52 726 Socket.prototype.connect = function(){
Osamu Nakamura 0:a40b9a259b52 727 if (this.connected) return this;
Osamu Nakamura 0:a40b9a259b52 728
Osamu Nakamura 0:a40b9a259b52 729 this.subEvents();
Osamu Nakamura 0:a40b9a259b52 730 this.io.open(); // ensure open
Osamu Nakamura 0:a40b9a259b52 731 if ('open' == this.io.readyState) this.onopen();
Osamu Nakamura 0:a40b9a259b52 732 return this;
Osamu Nakamura 0:a40b9a259b52 733 };
Osamu Nakamura 0:a40b9a259b52 734
Osamu Nakamura 0:a40b9a259b52 735 /**
Osamu Nakamura 0:a40b9a259b52 736 * Sends a `message` event.
Osamu Nakamura 0:a40b9a259b52 737 *
Osamu Nakamura 0:a40b9a259b52 738 * @return {Socket} self
Osamu Nakamura 0:a40b9a259b52 739 * @api public
Osamu Nakamura 0:a40b9a259b52 740 */
Osamu Nakamura 0:a40b9a259b52 741
Osamu Nakamura 0:a40b9a259b52 742 Socket.prototype.send = function(){
Osamu Nakamura 0:a40b9a259b52 743 var args = toArray(arguments);
Osamu Nakamura 0:a40b9a259b52 744 args.unshift('message');
Osamu Nakamura 0:a40b9a259b52 745 this.emit.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 746 return this;
Osamu Nakamura 0:a40b9a259b52 747 };
Osamu Nakamura 0:a40b9a259b52 748
Osamu Nakamura 0:a40b9a259b52 749 /**
Osamu Nakamura 0:a40b9a259b52 750 * Override `emit`.
Osamu Nakamura 0:a40b9a259b52 751 * If the event is in `events`, it's emitted normally.
Osamu Nakamura 0:a40b9a259b52 752 *
Osamu Nakamura 0:a40b9a259b52 753 * @param {String} event name
Osamu Nakamura 0:a40b9a259b52 754 * @return {Socket} self
Osamu Nakamura 0:a40b9a259b52 755 * @api public
Osamu Nakamura 0:a40b9a259b52 756 */
Osamu Nakamura 0:a40b9a259b52 757
Osamu Nakamura 0:a40b9a259b52 758 Socket.prototype.emit = function(ev){
Osamu Nakamura 0:a40b9a259b52 759 if (events.hasOwnProperty(ev)) {
Osamu Nakamura 0:a40b9a259b52 760 emit.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 761 return this;
Osamu Nakamura 0:a40b9a259b52 762 }
Osamu Nakamura 0:a40b9a259b52 763
Osamu Nakamura 0:a40b9a259b52 764 var args = toArray(arguments);
Osamu Nakamura 0:a40b9a259b52 765 var parserType = parser.EVENT; // default
Osamu Nakamura 0:a40b9a259b52 766 if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
Osamu Nakamura 0:a40b9a259b52 767 var packet = { type: parserType, data: args };
Osamu Nakamura 0:a40b9a259b52 768
Osamu Nakamura 0:a40b9a259b52 769 // event ack callback
Osamu Nakamura 0:a40b9a259b52 770 if ('function' == typeof args[args.length - 1]) {
Osamu Nakamura 0:a40b9a259b52 771 debug('emitting packet with ack id %d', this.ids);
Osamu Nakamura 0:a40b9a259b52 772 this.acks[this.ids] = args.pop();
Osamu Nakamura 0:a40b9a259b52 773 packet.id = this.ids++;
Osamu Nakamura 0:a40b9a259b52 774 }
Osamu Nakamura 0:a40b9a259b52 775
Osamu Nakamura 0:a40b9a259b52 776 if (this.connected) {
Osamu Nakamura 0:a40b9a259b52 777 this.packet(packet);
Osamu Nakamura 0:a40b9a259b52 778 } else {
Osamu Nakamura 0:a40b9a259b52 779 this.sendBuffer.push(packet);
Osamu Nakamura 0:a40b9a259b52 780 }
Osamu Nakamura 0:a40b9a259b52 781
Osamu Nakamura 0:a40b9a259b52 782 return this;
Osamu Nakamura 0:a40b9a259b52 783 };
Osamu Nakamura 0:a40b9a259b52 784
Osamu Nakamura 0:a40b9a259b52 785 /**
Osamu Nakamura 0:a40b9a259b52 786 * Sends a packet.
Osamu Nakamura 0:a40b9a259b52 787 *
Osamu Nakamura 0:a40b9a259b52 788 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 789 * @api private
Osamu Nakamura 0:a40b9a259b52 790 */
Osamu Nakamura 0:a40b9a259b52 791
Osamu Nakamura 0:a40b9a259b52 792 Socket.prototype.packet = function(packet){
Osamu Nakamura 0:a40b9a259b52 793 packet.nsp = this.nsp;
Osamu Nakamura 0:a40b9a259b52 794 this.io.packet(packet);
Osamu Nakamura 0:a40b9a259b52 795 };
Osamu Nakamura 0:a40b9a259b52 796
Osamu Nakamura 0:a40b9a259b52 797 /**
Osamu Nakamura 0:a40b9a259b52 798 * Called upon engine `open`.
Osamu Nakamura 0:a40b9a259b52 799 *
Osamu Nakamura 0:a40b9a259b52 800 * @api private
Osamu Nakamura 0:a40b9a259b52 801 */
Osamu Nakamura 0:a40b9a259b52 802
Osamu Nakamura 0:a40b9a259b52 803 Socket.prototype.onopen = function(){
Osamu Nakamura 0:a40b9a259b52 804 debug('transport is open - connecting');
Osamu Nakamura 0:a40b9a259b52 805
Osamu Nakamura 0:a40b9a259b52 806 // write connect packet if necessary
Osamu Nakamura 0:a40b9a259b52 807 if ('/' != this.nsp) {
Osamu Nakamura 0:a40b9a259b52 808 this.packet({ type: parser.CONNECT });
Osamu Nakamura 0:a40b9a259b52 809 }
Osamu Nakamura 0:a40b9a259b52 810 };
Osamu Nakamura 0:a40b9a259b52 811
Osamu Nakamura 0:a40b9a259b52 812 /**
Osamu Nakamura 0:a40b9a259b52 813 * Called upon engine `close`.
Osamu Nakamura 0:a40b9a259b52 814 *
Osamu Nakamura 0:a40b9a259b52 815 * @param {String} reason
Osamu Nakamura 0:a40b9a259b52 816 * @api private
Osamu Nakamura 0:a40b9a259b52 817 */
Osamu Nakamura 0:a40b9a259b52 818
Osamu Nakamura 0:a40b9a259b52 819 Socket.prototype.onclose = function(reason){
Osamu Nakamura 0:a40b9a259b52 820 debug('close (%s)', reason);
Osamu Nakamura 0:a40b9a259b52 821 this.connected = false;
Osamu Nakamura 0:a40b9a259b52 822 this.disconnected = true;
Osamu Nakamura 0:a40b9a259b52 823 delete this.id;
Osamu Nakamura 0:a40b9a259b52 824 this.emit('disconnect', reason);
Osamu Nakamura 0:a40b9a259b52 825 };
Osamu Nakamura 0:a40b9a259b52 826
Osamu Nakamura 0:a40b9a259b52 827 /**
Osamu Nakamura 0:a40b9a259b52 828 * Called with socket packet.
Osamu Nakamura 0:a40b9a259b52 829 *
Osamu Nakamura 0:a40b9a259b52 830 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 831 * @api private
Osamu Nakamura 0:a40b9a259b52 832 */
Osamu Nakamura 0:a40b9a259b52 833
Osamu Nakamura 0:a40b9a259b52 834 Socket.prototype.onpacket = function(packet){
Osamu Nakamura 0:a40b9a259b52 835 if (packet.nsp != this.nsp) return;
Osamu Nakamura 0:a40b9a259b52 836
Osamu Nakamura 0:a40b9a259b52 837 switch (packet.type) {
Osamu Nakamura 0:a40b9a259b52 838 case parser.CONNECT:
Osamu Nakamura 0:a40b9a259b52 839 this.onconnect();
Osamu Nakamura 0:a40b9a259b52 840 break;
Osamu Nakamura 0:a40b9a259b52 841
Osamu Nakamura 0:a40b9a259b52 842 case parser.EVENT:
Osamu Nakamura 0:a40b9a259b52 843 this.onevent(packet);
Osamu Nakamura 0:a40b9a259b52 844 break;
Osamu Nakamura 0:a40b9a259b52 845
Osamu Nakamura 0:a40b9a259b52 846 case parser.BINARY_EVENT:
Osamu Nakamura 0:a40b9a259b52 847 this.onevent(packet);
Osamu Nakamura 0:a40b9a259b52 848 break;
Osamu Nakamura 0:a40b9a259b52 849
Osamu Nakamura 0:a40b9a259b52 850 case parser.ACK:
Osamu Nakamura 0:a40b9a259b52 851 this.onack(packet);
Osamu Nakamura 0:a40b9a259b52 852 break;
Osamu Nakamura 0:a40b9a259b52 853
Osamu Nakamura 0:a40b9a259b52 854 case parser.BINARY_ACK:
Osamu Nakamura 0:a40b9a259b52 855 this.onack(packet);
Osamu Nakamura 0:a40b9a259b52 856 break;
Osamu Nakamura 0:a40b9a259b52 857
Osamu Nakamura 0:a40b9a259b52 858 case parser.DISCONNECT:
Osamu Nakamura 0:a40b9a259b52 859 this.ondisconnect();
Osamu Nakamura 0:a40b9a259b52 860 break;
Osamu Nakamura 0:a40b9a259b52 861
Osamu Nakamura 0:a40b9a259b52 862 case parser.ERROR:
Osamu Nakamura 0:a40b9a259b52 863 this.emit('error', packet.data);
Osamu Nakamura 0:a40b9a259b52 864 break;
Osamu Nakamura 0:a40b9a259b52 865 }
Osamu Nakamura 0:a40b9a259b52 866 };
Osamu Nakamura 0:a40b9a259b52 867
Osamu Nakamura 0:a40b9a259b52 868 /**
Osamu Nakamura 0:a40b9a259b52 869 * Called upon a server event.
Osamu Nakamura 0:a40b9a259b52 870 *
Osamu Nakamura 0:a40b9a259b52 871 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 872 * @api private
Osamu Nakamura 0:a40b9a259b52 873 */
Osamu Nakamura 0:a40b9a259b52 874
Osamu Nakamura 0:a40b9a259b52 875 Socket.prototype.onevent = function(packet){
Osamu Nakamura 0:a40b9a259b52 876 var args = packet.data || [];
Osamu Nakamura 0:a40b9a259b52 877 debug('emitting event %j', args);
Osamu Nakamura 0:a40b9a259b52 878
Osamu Nakamura 0:a40b9a259b52 879 if (null != packet.id) {
Osamu Nakamura 0:a40b9a259b52 880 debug('attaching ack callback to event');
Osamu Nakamura 0:a40b9a259b52 881 args.push(this.ack(packet.id));
Osamu Nakamura 0:a40b9a259b52 882 }
Osamu Nakamura 0:a40b9a259b52 883
Osamu Nakamura 0:a40b9a259b52 884 if (this.connected) {
Osamu Nakamura 0:a40b9a259b52 885 emit.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 886 } else {
Osamu Nakamura 0:a40b9a259b52 887 this.receiveBuffer.push(args);
Osamu Nakamura 0:a40b9a259b52 888 }
Osamu Nakamura 0:a40b9a259b52 889 };
Osamu Nakamura 0:a40b9a259b52 890
Osamu Nakamura 0:a40b9a259b52 891 /**
Osamu Nakamura 0:a40b9a259b52 892 * Produces an ack callback to emit with an event.
Osamu Nakamura 0:a40b9a259b52 893 *
Osamu Nakamura 0:a40b9a259b52 894 * @api private
Osamu Nakamura 0:a40b9a259b52 895 */
Osamu Nakamura 0:a40b9a259b52 896
Osamu Nakamura 0:a40b9a259b52 897 Socket.prototype.ack = function(id){
Osamu Nakamura 0:a40b9a259b52 898 var self = this;
Osamu Nakamura 0:a40b9a259b52 899 var sent = false;
Osamu Nakamura 0:a40b9a259b52 900 return function(){
Osamu Nakamura 0:a40b9a259b52 901 // prevent double callbacks
Osamu Nakamura 0:a40b9a259b52 902 if (sent) return;
Osamu Nakamura 0:a40b9a259b52 903 sent = true;
Osamu Nakamura 0:a40b9a259b52 904 var args = toArray(arguments);
Osamu Nakamura 0:a40b9a259b52 905 debug('sending ack %j', args);
Osamu Nakamura 0:a40b9a259b52 906
Osamu Nakamura 0:a40b9a259b52 907 var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
Osamu Nakamura 0:a40b9a259b52 908 self.packet({
Osamu Nakamura 0:a40b9a259b52 909 type: type,
Osamu Nakamura 0:a40b9a259b52 910 id: id,
Osamu Nakamura 0:a40b9a259b52 911 data: args
Osamu Nakamura 0:a40b9a259b52 912 });
Osamu Nakamura 0:a40b9a259b52 913 };
Osamu Nakamura 0:a40b9a259b52 914 };
Osamu Nakamura 0:a40b9a259b52 915
Osamu Nakamura 0:a40b9a259b52 916 /**
Osamu Nakamura 0:a40b9a259b52 917 * Called upon a server acknowlegement.
Osamu Nakamura 0:a40b9a259b52 918 *
Osamu Nakamura 0:a40b9a259b52 919 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 920 * @api private
Osamu Nakamura 0:a40b9a259b52 921 */
Osamu Nakamura 0:a40b9a259b52 922
Osamu Nakamura 0:a40b9a259b52 923 Socket.prototype.onack = function(packet){
Osamu Nakamura 0:a40b9a259b52 924 debug('calling ack %s with %j', packet.id, packet.data);
Osamu Nakamura 0:a40b9a259b52 925 var fn = this.acks[packet.id];
Osamu Nakamura 0:a40b9a259b52 926 fn.apply(this, packet.data);
Osamu Nakamura 0:a40b9a259b52 927 delete this.acks[packet.id];
Osamu Nakamura 0:a40b9a259b52 928 };
Osamu Nakamura 0:a40b9a259b52 929
Osamu Nakamura 0:a40b9a259b52 930 /**
Osamu Nakamura 0:a40b9a259b52 931 * Called upon server connect.
Osamu Nakamura 0:a40b9a259b52 932 *
Osamu Nakamura 0:a40b9a259b52 933 * @api private
Osamu Nakamura 0:a40b9a259b52 934 */
Osamu Nakamura 0:a40b9a259b52 935
Osamu Nakamura 0:a40b9a259b52 936 Socket.prototype.onconnect = function(){
Osamu Nakamura 0:a40b9a259b52 937 this.connected = true;
Osamu Nakamura 0:a40b9a259b52 938 this.disconnected = false;
Osamu Nakamura 0:a40b9a259b52 939 this.emit('connect');
Osamu Nakamura 0:a40b9a259b52 940 this.emitBuffered();
Osamu Nakamura 0:a40b9a259b52 941 };
Osamu Nakamura 0:a40b9a259b52 942
Osamu Nakamura 0:a40b9a259b52 943 /**
Osamu Nakamura 0:a40b9a259b52 944 * Emit buffered events (received and emitted).
Osamu Nakamura 0:a40b9a259b52 945 *
Osamu Nakamura 0:a40b9a259b52 946 * @api private
Osamu Nakamura 0:a40b9a259b52 947 */
Osamu Nakamura 0:a40b9a259b52 948
Osamu Nakamura 0:a40b9a259b52 949 Socket.prototype.emitBuffered = function(){
Osamu Nakamura 0:a40b9a259b52 950 var i;
Osamu Nakamura 0:a40b9a259b52 951 for (i = 0; i < this.receiveBuffer.length; i++) {
Osamu Nakamura 0:a40b9a259b52 952 emit.apply(this, this.receiveBuffer[i]);
Osamu Nakamura 0:a40b9a259b52 953 }
Osamu Nakamura 0:a40b9a259b52 954 this.receiveBuffer = [];
Osamu Nakamura 0:a40b9a259b52 955
Osamu Nakamura 0:a40b9a259b52 956 for (i = 0; i < this.sendBuffer.length; i++) {
Osamu Nakamura 0:a40b9a259b52 957 this.packet(this.sendBuffer[i]);
Osamu Nakamura 0:a40b9a259b52 958 }
Osamu Nakamura 0:a40b9a259b52 959 this.sendBuffer = [];
Osamu Nakamura 0:a40b9a259b52 960 };
Osamu Nakamura 0:a40b9a259b52 961
Osamu Nakamura 0:a40b9a259b52 962 /**
Osamu Nakamura 0:a40b9a259b52 963 * Called upon server disconnect.
Osamu Nakamura 0:a40b9a259b52 964 *
Osamu Nakamura 0:a40b9a259b52 965 * @api private
Osamu Nakamura 0:a40b9a259b52 966 */
Osamu Nakamura 0:a40b9a259b52 967
Osamu Nakamura 0:a40b9a259b52 968 Socket.prototype.ondisconnect = function(){
Osamu Nakamura 0:a40b9a259b52 969 debug('server disconnect (%s)', this.nsp);
Osamu Nakamura 0:a40b9a259b52 970 this.destroy();
Osamu Nakamura 0:a40b9a259b52 971 this.onclose('io server disconnect');
Osamu Nakamura 0:a40b9a259b52 972 };
Osamu Nakamura 0:a40b9a259b52 973
Osamu Nakamura 0:a40b9a259b52 974 /**
Osamu Nakamura 0:a40b9a259b52 975 * Called upon forced client/server side disconnections,
Osamu Nakamura 0:a40b9a259b52 976 * this method ensures the manager stops tracking us and
Osamu Nakamura 0:a40b9a259b52 977 * that reconnections don't get triggered for this.
Osamu Nakamura 0:a40b9a259b52 978 *
Osamu Nakamura 0:a40b9a259b52 979 * @api private.
Osamu Nakamura 0:a40b9a259b52 980 */
Osamu Nakamura 0:a40b9a259b52 981
Osamu Nakamura 0:a40b9a259b52 982 Socket.prototype.destroy = function(){
Osamu Nakamura 0:a40b9a259b52 983 if (this.subs) {
Osamu Nakamura 0:a40b9a259b52 984 // clean subscriptions to avoid reconnections
Osamu Nakamura 0:a40b9a259b52 985 for (var i = 0; i < this.subs.length; i++) {
Osamu Nakamura 0:a40b9a259b52 986 this.subs[i].destroy();
Osamu Nakamura 0:a40b9a259b52 987 }
Osamu Nakamura 0:a40b9a259b52 988 this.subs = null;
Osamu Nakamura 0:a40b9a259b52 989 }
Osamu Nakamura 0:a40b9a259b52 990
Osamu Nakamura 0:a40b9a259b52 991 this.io.destroy(this);
Osamu Nakamura 0:a40b9a259b52 992 };
Osamu Nakamura 0:a40b9a259b52 993
Osamu Nakamura 0:a40b9a259b52 994 /**
Osamu Nakamura 0:a40b9a259b52 995 * Disconnects the socket manually.
Osamu Nakamura 0:a40b9a259b52 996 *
Osamu Nakamura 0:a40b9a259b52 997 * @return {Socket} self
Osamu Nakamura 0:a40b9a259b52 998 * @api public
Osamu Nakamura 0:a40b9a259b52 999 */
Osamu Nakamura 0:a40b9a259b52 1000
Osamu Nakamura 0:a40b9a259b52 1001 Socket.prototype.close =
Osamu Nakamura 0:a40b9a259b52 1002 Socket.prototype.disconnect = function(){
Osamu Nakamura 0:a40b9a259b52 1003 if (this.connected) {
Osamu Nakamura 0:a40b9a259b52 1004 debug('performing disconnect (%s)', this.nsp);
Osamu Nakamura 0:a40b9a259b52 1005 this.packet({ type: parser.DISCONNECT });
Osamu Nakamura 0:a40b9a259b52 1006 }
Osamu Nakamura 0:a40b9a259b52 1007
Osamu Nakamura 0:a40b9a259b52 1008 // remove socket from pool
Osamu Nakamura 0:a40b9a259b52 1009 this.destroy();
Osamu Nakamura 0:a40b9a259b52 1010
Osamu Nakamura 0:a40b9a259b52 1011 if (this.connected) {
Osamu Nakamura 0:a40b9a259b52 1012 // fire events
Osamu Nakamura 0:a40b9a259b52 1013 this.onclose('io client disconnect');
Osamu Nakamura 0:a40b9a259b52 1014 }
Osamu Nakamura 0:a40b9a259b52 1015 return this;
Osamu Nakamura 0:a40b9a259b52 1016 };
Osamu Nakamura 0:a40b9a259b52 1017
Osamu Nakamura 0:a40b9a259b52 1018 },{"./on":4,"component-bind":8,"component-emitter":9,"debug":10,"has-binary":38,"socket.io-parser":46,"to-array":50}],6:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1019 (function (global){
Osamu Nakamura 0:a40b9a259b52 1020
Osamu Nakamura 0:a40b9a259b52 1021 /**
Osamu Nakamura 0:a40b9a259b52 1022 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 1023 */
Osamu Nakamura 0:a40b9a259b52 1024
Osamu Nakamura 0:a40b9a259b52 1025 var parseuri = _dereq_('parseuri');
Osamu Nakamura 0:a40b9a259b52 1026 var debug = _dereq_('debug')('socket.io-client:url');
Osamu Nakamura 0:a40b9a259b52 1027
Osamu Nakamura 0:a40b9a259b52 1028 /**
Osamu Nakamura 0:a40b9a259b52 1029 * Module exports.
Osamu Nakamura 0:a40b9a259b52 1030 */
Osamu Nakamura 0:a40b9a259b52 1031
Osamu Nakamura 0:a40b9a259b52 1032 module.exports = url;
Osamu Nakamura 0:a40b9a259b52 1033
Osamu Nakamura 0:a40b9a259b52 1034 /**
Osamu Nakamura 0:a40b9a259b52 1035 * URL parser.
Osamu Nakamura 0:a40b9a259b52 1036 *
Osamu Nakamura 0:a40b9a259b52 1037 * @param {String} url
Osamu Nakamura 0:a40b9a259b52 1038 * @param {Object} An object meant to mimic window.location.
Osamu Nakamura 0:a40b9a259b52 1039 * Defaults to window.location.
Osamu Nakamura 0:a40b9a259b52 1040 * @api public
Osamu Nakamura 0:a40b9a259b52 1041 */
Osamu Nakamura 0:a40b9a259b52 1042
Osamu Nakamura 0:a40b9a259b52 1043 function url(uri, loc){
Osamu Nakamura 0:a40b9a259b52 1044 var obj = uri;
Osamu Nakamura 0:a40b9a259b52 1045
Osamu Nakamura 0:a40b9a259b52 1046 // default to window.location
Osamu Nakamura 0:a40b9a259b52 1047 var loc = loc || global.location;
Osamu Nakamura 0:a40b9a259b52 1048 if (null == uri) uri = loc.protocol + '//' + loc.host;
Osamu Nakamura 0:a40b9a259b52 1049
Osamu Nakamura 0:a40b9a259b52 1050 // relative path support
Osamu Nakamura 0:a40b9a259b52 1051 if ('string' == typeof uri) {
Osamu Nakamura 0:a40b9a259b52 1052 if ('/' == uri.charAt(0)) {
Osamu Nakamura 0:a40b9a259b52 1053 if ('/' == uri.charAt(1)) {
Osamu Nakamura 0:a40b9a259b52 1054 uri = loc.protocol + uri;
Osamu Nakamura 0:a40b9a259b52 1055 } else {
Osamu Nakamura 0:a40b9a259b52 1056 uri = loc.hostname + uri;
Osamu Nakamura 0:a40b9a259b52 1057 }
Osamu Nakamura 0:a40b9a259b52 1058 }
Osamu Nakamura 0:a40b9a259b52 1059
Osamu Nakamura 0:a40b9a259b52 1060 if (!/^(https?|wss?):\/\//.test(uri)) {
Osamu Nakamura 0:a40b9a259b52 1061 debug('protocol-less url %s', uri);
Osamu Nakamura 0:a40b9a259b52 1062 if ('undefined' != typeof loc) {
Osamu Nakamura 0:a40b9a259b52 1063 uri = loc.protocol + '//' + uri;
Osamu Nakamura 0:a40b9a259b52 1064 } else {
Osamu Nakamura 0:a40b9a259b52 1065 uri = 'https://' + uri;
Osamu Nakamura 0:a40b9a259b52 1066 }
Osamu Nakamura 0:a40b9a259b52 1067 }
Osamu Nakamura 0:a40b9a259b52 1068
Osamu Nakamura 0:a40b9a259b52 1069 // parse
Osamu Nakamura 0:a40b9a259b52 1070 debug('parse %s', uri);
Osamu Nakamura 0:a40b9a259b52 1071 obj = parseuri(uri);
Osamu Nakamura 0:a40b9a259b52 1072 }
Osamu Nakamura 0:a40b9a259b52 1073
Osamu Nakamura 0:a40b9a259b52 1074 // make sure we treat `localhost:80` and `localhost` equally
Osamu Nakamura 0:a40b9a259b52 1075 if (!obj.port) {
Osamu Nakamura 0:a40b9a259b52 1076 if (/^(http|ws)$/.test(obj.protocol)) {
Osamu Nakamura 0:a40b9a259b52 1077 obj.port = '80';
Osamu Nakamura 0:a40b9a259b52 1078 }
Osamu Nakamura 0:a40b9a259b52 1079 else if (/^(http|ws)s$/.test(obj.protocol)) {
Osamu Nakamura 0:a40b9a259b52 1080 obj.port = '443';
Osamu Nakamura 0:a40b9a259b52 1081 }
Osamu Nakamura 0:a40b9a259b52 1082 }
Osamu Nakamura 0:a40b9a259b52 1083
Osamu Nakamura 0:a40b9a259b52 1084 obj.path = obj.path || '/';
Osamu Nakamura 0:a40b9a259b52 1085
Osamu Nakamura 0:a40b9a259b52 1086 // define unique id
Osamu Nakamura 0:a40b9a259b52 1087 obj.id = obj.protocol + '://' + obj.host + ':' + obj.port;
Osamu Nakamura 0:a40b9a259b52 1088 // define href
Osamu Nakamura 0:a40b9a259b52 1089 obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
Osamu Nakamura 0:a40b9a259b52 1090
Osamu Nakamura 0:a40b9a259b52 1091 return obj;
Osamu Nakamura 0:a40b9a259b52 1092 }
Osamu Nakamura 0:a40b9a259b52 1093
Osamu Nakamura 0:a40b9a259b52 1094 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 1095 },{"debug":10,"parseuri":44}],7:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1096
Osamu Nakamura 0:a40b9a259b52 1097 /**
Osamu Nakamura 0:a40b9a259b52 1098 * Expose `Backoff`.
Osamu Nakamura 0:a40b9a259b52 1099 */
Osamu Nakamura 0:a40b9a259b52 1100
Osamu Nakamura 0:a40b9a259b52 1101 module.exports = Backoff;
Osamu Nakamura 0:a40b9a259b52 1102
Osamu Nakamura 0:a40b9a259b52 1103 /**
Osamu Nakamura 0:a40b9a259b52 1104 * Initialize backoff timer with `opts`.
Osamu Nakamura 0:a40b9a259b52 1105 *
Osamu Nakamura 0:a40b9a259b52 1106 * - `min` initial timeout in milliseconds [100]
Osamu Nakamura 0:a40b9a259b52 1107 * - `max` max timeout [10000]
Osamu Nakamura 0:a40b9a259b52 1108 * - `jitter` [0]
Osamu Nakamura 0:a40b9a259b52 1109 * - `factor` [2]
Osamu Nakamura 0:a40b9a259b52 1110 *
Osamu Nakamura 0:a40b9a259b52 1111 * @param {Object} opts
Osamu Nakamura 0:a40b9a259b52 1112 * @api public
Osamu Nakamura 0:a40b9a259b52 1113 */
Osamu Nakamura 0:a40b9a259b52 1114
Osamu Nakamura 0:a40b9a259b52 1115 function Backoff(opts) {
Osamu Nakamura 0:a40b9a259b52 1116 opts = opts || {};
Osamu Nakamura 0:a40b9a259b52 1117 this.ms = opts.min || 100;
Osamu Nakamura 0:a40b9a259b52 1118 this.max = opts.max || 10000;
Osamu Nakamura 0:a40b9a259b52 1119 this.factor = opts.factor || 2;
Osamu Nakamura 0:a40b9a259b52 1120 this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
Osamu Nakamura 0:a40b9a259b52 1121 this.attempts = 0;
Osamu Nakamura 0:a40b9a259b52 1122 }
Osamu Nakamura 0:a40b9a259b52 1123
Osamu Nakamura 0:a40b9a259b52 1124 /**
Osamu Nakamura 0:a40b9a259b52 1125 * Return the backoff duration.
Osamu Nakamura 0:a40b9a259b52 1126 *
Osamu Nakamura 0:a40b9a259b52 1127 * @return {Number}
Osamu Nakamura 0:a40b9a259b52 1128 * @api public
Osamu Nakamura 0:a40b9a259b52 1129 */
Osamu Nakamura 0:a40b9a259b52 1130
Osamu Nakamura 0:a40b9a259b52 1131 Backoff.prototype.duration = function(){
Osamu Nakamura 0:a40b9a259b52 1132 var ms = this.ms * Math.pow(this.factor, this.attempts++);
Osamu Nakamura 0:a40b9a259b52 1133 if (this.jitter) {
Osamu Nakamura 0:a40b9a259b52 1134 var rand = Math.random();
Osamu Nakamura 0:a40b9a259b52 1135 var deviation = Math.floor(rand * this.jitter * ms);
Osamu Nakamura 0:a40b9a259b52 1136 ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
Osamu Nakamura 0:a40b9a259b52 1137 }
Osamu Nakamura 0:a40b9a259b52 1138 return Math.min(ms, this.max) | 0;
Osamu Nakamura 0:a40b9a259b52 1139 };
Osamu Nakamura 0:a40b9a259b52 1140
Osamu Nakamura 0:a40b9a259b52 1141 /**
Osamu Nakamura 0:a40b9a259b52 1142 * Reset the number of attempts.
Osamu Nakamura 0:a40b9a259b52 1143 *
Osamu Nakamura 0:a40b9a259b52 1144 * @api public
Osamu Nakamura 0:a40b9a259b52 1145 */
Osamu Nakamura 0:a40b9a259b52 1146
Osamu Nakamura 0:a40b9a259b52 1147 Backoff.prototype.reset = function(){
Osamu Nakamura 0:a40b9a259b52 1148 this.attempts = 0;
Osamu Nakamura 0:a40b9a259b52 1149 };
Osamu Nakamura 0:a40b9a259b52 1150
Osamu Nakamura 0:a40b9a259b52 1151 /**
Osamu Nakamura 0:a40b9a259b52 1152 * Set the minimum duration
Osamu Nakamura 0:a40b9a259b52 1153 *
Osamu Nakamura 0:a40b9a259b52 1154 * @api public
Osamu Nakamura 0:a40b9a259b52 1155 */
Osamu Nakamura 0:a40b9a259b52 1156
Osamu Nakamura 0:a40b9a259b52 1157 Backoff.prototype.setMin = function(min){
Osamu Nakamura 0:a40b9a259b52 1158 this.ms = min;
Osamu Nakamura 0:a40b9a259b52 1159 };
Osamu Nakamura 0:a40b9a259b52 1160
Osamu Nakamura 0:a40b9a259b52 1161 /**
Osamu Nakamura 0:a40b9a259b52 1162 * Set the maximum duration
Osamu Nakamura 0:a40b9a259b52 1163 *
Osamu Nakamura 0:a40b9a259b52 1164 * @api public
Osamu Nakamura 0:a40b9a259b52 1165 */
Osamu Nakamura 0:a40b9a259b52 1166
Osamu Nakamura 0:a40b9a259b52 1167 Backoff.prototype.setMax = function(max){
Osamu Nakamura 0:a40b9a259b52 1168 this.max = max;
Osamu Nakamura 0:a40b9a259b52 1169 };
Osamu Nakamura 0:a40b9a259b52 1170
Osamu Nakamura 0:a40b9a259b52 1171 /**
Osamu Nakamura 0:a40b9a259b52 1172 * Set the jitter
Osamu Nakamura 0:a40b9a259b52 1173 *
Osamu Nakamura 0:a40b9a259b52 1174 * @api public
Osamu Nakamura 0:a40b9a259b52 1175 */
Osamu Nakamura 0:a40b9a259b52 1176
Osamu Nakamura 0:a40b9a259b52 1177 Backoff.prototype.setJitter = function(jitter){
Osamu Nakamura 0:a40b9a259b52 1178 this.jitter = jitter;
Osamu Nakamura 0:a40b9a259b52 1179 };
Osamu Nakamura 0:a40b9a259b52 1180
Osamu Nakamura 0:a40b9a259b52 1181
Osamu Nakamura 0:a40b9a259b52 1182 },{}],8:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1183 /**
Osamu Nakamura 0:a40b9a259b52 1184 * Slice reference.
Osamu Nakamura 0:a40b9a259b52 1185 */
Osamu Nakamura 0:a40b9a259b52 1186
Osamu Nakamura 0:a40b9a259b52 1187 var slice = [].slice;
Osamu Nakamura 0:a40b9a259b52 1188
Osamu Nakamura 0:a40b9a259b52 1189 /**
Osamu Nakamura 0:a40b9a259b52 1190 * Bind `obj` to `fn`.
Osamu Nakamura 0:a40b9a259b52 1191 *
Osamu Nakamura 0:a40b9a259b52 1192 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 1193 * @param {Function|String} fn or string
Osamu Nakamura 0:a40b9a259b52 1194 * @return {Function}
Osamu Nakamura 0:a40b9a259b52 1195 * @api public
Osamu Nakamura 0:a40b9a259b52 1196 */
Osamu Nakamura 0:a40b9a259b52 1197
Osamu Nakamura 0:a40b9a259b52 1198 module.exports = function(obj, fn){
Osamu Nakamura 0:a40b9a259b52 1199 if ('string' == typeof fn) fn = obj[fn];
Osamu Nakamura 0:a40b9a259b52 1200 if ('function' != typeof fn) throw new Error('bind() requires a function');
Osamu Nakamura 0:a40b9a259b52 1201 var args = slice.call(arguments, 2);
Osamu Nakamura 0:a40b9a259b52 1202 return function(){
Osamu Nakamura 0:a40b9a259b52 1203 return fn.apply(obj, args.concat(slice.call(arguments)));
Osamu Nakamura 0:a40b9a259b52 1204 }
Osamu Nakamura 0:a40b9a259b52 1205 };
Osamu Nakamura 0:a40b9a259b52 1206
Osamu Nakamura 0:a40b9a259b52 1207 },{}],9:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1208
Osamu Nakamura 0:a40b9a259b52 1209 /**
Osamu Nakamura 0:a40b9a259b52 1210 * Expose `Emitter`.
Osamu Nakamura 0:a40b9a259b52 1211 */
Osamu Nakamura 0:a40b9a259b52 1212
Osamu Nakamura 0:a40b9a259b52 1213 module.exports = Emitter;
Osamu Nakamura 0:a40b9a259b52 1214
Osamu Nakamura 0:a40b9a259b52 1215 /**
Osamu Nakamura 0:a40b9a259b52 1216 * Initialize a new `Emitter`.
Osamu Nakamura 0:a40b9a259b52 1217 *
Osamu Nakamura 0:a40b9a259b52 1218 * @api public
Osamu Nakamura 0:a40b9a259b52 1219 */
Osamu Nakamura 0:a40b9a259b52 1220
Osamu Nakamura 0:a40b9a259b52 1221 function Emitter(obj) {
Osamu Nakamura 0:a40b9a259b52 1222 if (obj) return mixin(obj);
Osamu Nakamura 0:a40b9a259b52 1223 };
Osamu Nakamura 0:a40b9a259b52 1224
Osamu Nakamura 0:a40b9a259b52 1225 /**
Osamu Nakamura 0:a40b9a259b52 1226 * Mixin the emitter properties.
Osamu Nakamura 0:a40b9a259b52 1227 *
Osamu Nakamura 0:a40b9a259b52 1228 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 1229 * @return {Object}
Osamu Nakamura 0:a40b9a259b52 1230 * @api private
Osamu Nakamura 0:a40b9a259b52 1231 */
Osamu Nakamura 0:a40b9a259b52 1232
Osamu Nakamura 0:a40b9a259b52 1233 function mixin(obj) {
Osamu Nakamura 0:a40b9a259b52 1234 for (var key in Emitter.prototype) {
Osamu Nakamura 0:a40b9a259b52 1235 obj[key] = Emitter.prototype[key];
Osamu Nakamura 0:a40b9a259b52 1236 }
Osamu Nakamura 0:a40b9a259b52 1237 return obj;
Osamu Nakamura 0:a40b9a259b52 1238 }
Osamu Nakamura 0:a40b9a259b52 1239
Osamu Nakamura 0:a40b9a259b52 1240 /**
Osamu Nakamura 0:a40b9a259b52 1241 * Listen on the given `event` with `fn`.
Osamu Nakamura 0:a40b9a259b52 1242 *
Osamu Nakamura 0:a40b9a259b52 1243 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1244 * @param {Function} fn
Osamu Nakamura 0:a40b9a259b52 1245 * @return {Emitter}
Osamu Nakamura 0:a40b9a259b52 1246 * @api public
Osamu Nakamura 0:a40b9a259b52 1247 */
Osamu Nakamura 0:a40b9a259b52 1248
Osamu Nakamura 0:a40b9a259b52 1249 Emitter.prototype.on =
Osamu Nakamura 0:a40b9a259b52 1250 Emitter.prototype.addEventListener = function(event, fn){
Osamu Nakamura 0:a40b9a259b52 1251 this._callbacks = this._callbacks || {};
Osamu Nakamura 0:a40b9a259b52 1252 (this._callbacks[event] = this._callbacks[event] || [])
Osamu Nakamura 0:a40b9a259b52 1253 .push(fn);
Osamu Nakamura 0:a40b9a259b52 1254 return this;
Osamu Nakamura 0:a40b9a259b52 1255 };
Osamu Nakamura 0:a40b9a259b52 1256
Osamu Nakamura 0:a40b9a259b52 1257 /**
Osamu Nakamura 0:a40b9a259b52 1258 * Adds an `event` listener that will be invoked a single
Osamu Nakamura 0:a40b9a259b52 1259 * time then automatically removed.
Osamu Nakamura 0:a40b9a259b52 1260 *
Osamu Nakamura 0:a40b9a259b52 1261 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1262 * @param {Function} fn
Osamu Nakamura 0:a40b9a259b52 1263 * @return {Emitter}
Osamu Nakamura 0:a40b9a259b52 1264 * @api public
Osamu Nakamura 0:a40b9a259b52 1265 */
Osamu Nakamura 0:a40b9a259b52 1266
Osamu Nakamura 0:a40b9a259b52 1267 Emitter.prototype.once = function(event, fn){
Osamu Nakamura 0:a40b9a259b52 1268 var self = this;
Osamu Nakamura 0:a40b9a259b52 1269 this._callbacks = this._callbacks || {};
Osamu Nakamura 0:a40b9a259b52 1270
Osamu Nakamura 0:a40b9a259b52 1271 function on() {
Osamu Nakamura 0:a40b9a259b52 1272 self.off(event, on);
Osamu Nakamura 0:a40b9a259b52 1273 fn.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 1274 }
Osamu Nakamura 0:a40b9a259b52 1275
Osamu Nakamura 0:a40b9a259b52 1276 on.fn = fn;
Osamu Nakamura 0:a40b9a259b52 1277 this.on(event, on);
Osamu Nakamura 0:a40b9a259b52 1278 return this;
Osamu Nakamura 0:a40b9a259b52 1279 };
Osamu Nakamura 0:a40b9a259b52 1280
Osamu Nakamura 0:a40b9a259b52 1281 /**
Osamu Nakamura 0:a40b9a259b52 1282 * Remove the given callback for `event` or all
Osamu Nakamura 0:a40b9a259b52 1283 * registered callbacks.
Osamu Nakamura 0:a40b9a259b52 1284 *
Osamu Nakamura 0:a40b9a259b52 1285 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1286 * @param {Function} fn
Osamu Nakamura 0:a40b9a259b52 1287 * @return {Emitter}
Osamu Nakamura 0:a40b9a259b52 1288 * @api public
Osamu Nakamura 0:a40b9a259b52 1289 */
Osamu Nakamura 0:a40b9a259b52 1290
Osamu Nakamura 0:a40b9a259b52 1291 Emitter.prototype.off =
Osamu Nakamura 0:a40b9a259b52 1292 Emitter.prototype.removeListener =
Osamu Nakamura 0:a40b9a259b52 1293 Emitter.prototype.removeAllListeners =
Osamu Nakamura 0:a40b9a259b52 1294 Emitter.prototype.removeEventListener = function(event, fn){
Osamu Nakamura 0:a40b9a259b52 1295 this._callbacks = this._callbacks || {};
Osamu Nakamura 0:a40b9a259b52 1296
Osamu Nakamura 0:a40b9a259b52 1297 // all
Osamu Nakamura 0:a40b9a259b52 1298 if (0 == arguments.length) {
Osamu Nakamura 0:a40b9a259b52 1299 this._callbacks = {};
Osamu Nakamura 0:a40b9a259b52 1300 return this;
Osamu Nakamura 0:a40b9a259b52 1301 }
Osamu Nakamura 0:a40b9a259b52 1302
Osamu Nakamura 0:a40b9a259b52 1303 // specific event
Osamu Nakamura 0:a40b9a259b52 1304 var callbacks = this._callbacks[event];
Osamu Nakamura 0:a40b9a259b52 1305 if (!callbacks) return this;
Osamu Nakamura 0:a40b9a259b52 1306
Osamu Nakamura 0:a40b9a259b52 1307 // remove all handlers
Osamu Nakamura 0:a40b9a259b52 1308 if (1 == arguments.length) {
Osamu Nakamura 0:a40b9a259b52 1309 delete this._callbacks[event];
Osamu Nakamura 0:a40b9a259b52 1310 return this;
Osamu Nakamura 0:a40b9a259b52 1311 }
Osamu Nakamura 0:a40b9a259b52 1312
Osamu Nakamura 0:a40b9a259b52 1313 // remove specific handler
Osamu Nakamura 0:a40b9a259b52 1314 var cb;
Osamu Nakamura 0:a40b9a259b52 1315 for (var i = 0; i < callbacks.length; i++) {
Osamu Nakamura 0:a40b9a259b52 1316 cb = callbacks[i];
Osamu Nakamura 0:a40b9a259b52 1317 if (cb === fn || cb.fn === fn) {
Osamu Nakamura 0:a40b9a259b52 1318 callbacks.splice(i, 1);
Osamu Nakamura 0:a40b9a259b52 1319 break;
Osamu Nakamura 0:a40b9a259b52 1320 }
Osamu Nakamura 0:a40b9a259b52 1321 }
Osamu Nakamura 0:a40b9a259b52 1322 return this;
Osamu Nakamura 0:a40b9a259b52 1323 };
Osamu Nakamura 0:a40b9a259b52 1324
Osamu Nakamura 0:a40b9a259b52 1325 /**
Osamu Nakamura 0:a40b9a259b52 1326 * Emit `event` with the given args.
Osamu Nakamura 0:a40b9a259b52 1327 *
Osamu Nakamura 0:a40b9a259b52 1328 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1329 * @param {Mixed} ...
Osamu Nakamura 0:a40b9a259b52 1330 * @return {Emitter}
Osamu Nakamura 0:a40b9a259b52 1331 */
Osamu Nakamura 0:a40b9a259b52 1332
Osamu Nakamura 0:a40b9a259b52 1333 Emitter.prototype.emit = function(event){
Osamu Nakamura 0:a40b9a259b52 1334 this._callbacks = this._callbacks || {};
Osamu Nakamura 0:a40b9a259b52 1335 var args = [].slice.call(arguments, 1)
Osamu Nakamura 0:a40b9a259b52 1336 , callbacks = this._callbacks[event];
Osamu Nakamura 0:a40b9a259b52 1337
Osamu Nakamura 0:a40b9a259b52 1338 if (callbacks) {
Osamu Nakamura 0:a40b9a259b52 1339 callbacks = callbacks.slice(0);
Osamu Nakamura 0:a40b9a259b52 1340 for (var i = 0, len = callbacks.length; i < len; ++i) {
Osamu Nakamura 0:a40b9a259b52 1341 callbacks[i].apply(this, args);
Osamu Nakamura 0:a40b9a259b52 1342 }
Osamu Nakamura 0:a40b9a259b52 1343 }
Osamu Nakamura 0:a40b9a259b52 1344
Osamu Nakamura 0:a40b9a259b52 1345 return this;
Osamu Nakamura 0:a40b9a259b52 1346 };
Osamu Nakamura 0:a40b9a259b52 1347
Osamu Nakamura 0:a40b9a259b52 1348 /**
Osamu Nakamura 0:a40b9a259b52 1349 * Return array of callbacks for `event`.
Osamu Nakamura 0:a40b9a259b52 1350 *
Osamu Nakamura 0:a40b9a259b52 1351 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1352 * @return {Array}
Osamu Nakamura 0:a40b9a259b52 1353 * @api public
Osamu Nakamura 0:a40b9a259b52 1354 */
Osamu Nakamura 0:a40b9a259b52 1355
Osamu Nakamura 0:a40b9a259b52 1356 Emitter.prototype.listeners = function(event){
Osamu Nakamura 0:a40b9a259b52 1357 this._callbacks = this._callbacks || {};
Osamu Nakamura 0:a40b9a259b52 1358 return this._callbacks[event] || [];
Osamu Nakamura 0:a40b9a259b52 1359 };
Osamu Nakamura 0:a40b9a259b52 1360
Osamu Nakamura 0:a40b9a259b52 1361 /**
Osamu Nakamura 0:a40b9a259b52 1362 * Check if this emitter has `event` handlers.
Osamu Nakamura 0:a40b9a259b52 1363 *
Osamu Nakamura 0:a40b9a259b52 1364 * @param {String} event
Osamu Nakamura 0:a40b9a259b52 1365 * @return {Boolean}
Osamu Nakamura 0:a40b9a259b52 1366 * @api public
Osamu Nakamura 0:a40b9a259b52 1367 */
Osamu Nakamura 0:a40b9a259b52 1368
Osamu Nakamura 0:a40b9a259b52 1369 Emitter.prototype.hasListeners = function(event){
Osamu Nakamura 0:a40b9a259b52 1370 return !! this.listeners(event).length;
Osamu Nakamura 0:a40b9a259b52 1371 };
Osamu Nakamura 0:a40b9a259b52 1372
Osamu Nakamura 0:a40b9a259b52 1373 },{}],10:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1374
Osamu Nakamura 0:a40b9a259b52 1375 /**
Osamu Nakamura 0:a40b9a259b52 1376 * Expose `debug()` as the module.
Osamu Nakamura 0:a40b9a259b52 1377 */
Osamu Nakamura 0:a40b9a259b52 1378
Osamu Nakamura 0:a40b9a259b52 1379 module.exports = debug;
Osamu Nakamura 0:a40b9a259b52 1380
Osamu Nakamura 0:a40b9a259b52 1381 /**
Osamu Nakamura 0:a40b9a259b52 1382 * Create a debugger with the given `name`.
Osamu Nakamura 0:a40b9a259b52 1383 *
Osamu Nakamura 0:a40b9a259b52 1384 * @param {String} name
Osamu Nakamura 0:a40b9a259b52 1385 * @return {Type}
Osamu Nakamura 0:a40b9a259b52 1386 * @api public
Osamu Nakamura 0:a40b9a259b52 1387 */
Osamu Nakamura 0:a40b9a259b52 1388
Osamu Nakamura 0:a40b9a259b52 1389 function debug(name) {
Osamu Nakamura 0:a40b9a259b52 1390 if (!debug.enabled(name)) return function(){};
Osamu Nakamura 0:a40b9a259b52 1391
Osamu Nakamura 0:a40b9a259b52 1392 return function(fmt){
Osamu Nakamura 0:a40b9a259b52 1393 fmt = coerce(fmt);
Osamu Nakamura 0:a40b9a259b52 1394
Osamu Nakamura 0:a40b9a259b52 1395 var curr = new Date;
Osamu Nakamura 0:a40b9a259b52 1396 var ms = curr - (debug[name] || curr);
Osamu Nakamura 0:a40b9a259b52 1397 debug[name] = curr;
Osamu Nakamura 0:a40b9a259b52 1398
Osamu Nakamura 0:a40b9a259b52 1399 fmt = name
Osamu Nakamura 0:a40b9a259b52 1400 + ' '
Osamu Nakamura 0:a40b9a259b52 1401 + fmt
Osamu Nakamura 0:a40b9a259b52 1402 + ' +' + debug.humanize(ms);
Osamu Nakamura 0:a40b9a259b52 1403
Osamu Nakamura 0:a40b9a259b52 1404 // This hackery is required for IE8
Osamu Nakamura 0:a40b9a259b52 1405 // where `console.log` doesn't have 'apply'
Osamu Nakamura 0:a40b9a259b52 1406 window.console
Osamu Nakamura 0:a40b9a259b52 1407 && console.log
Osamu Nakamura 0:a40b9a259b52 1408 && Function.prototype.apply.call(console.log, console, arguments);
Osamu Nakamura 0:a40b9a259b52 1409 }
Osamu Nakamura 0:a40b9a259b52 1410 }
Osamu Nakamura 0:a40b9a259b52 1411
Osamu Nakamura 0:a40b9a259b52 1412 /**
Osamu Nakamura 0:a40b9a259b52 1413 * The currently active debug mode names.
Osamu Nakamura 0:a40b9a259b52 1414 */
Osamu Nakamura 0:a40b9a259b52 1415
Osamu Nakamura 0:a40b9a259b52 1416 debug.names = [];
Osamu Nakamura 0:a40b9a259b52 1417 debug.skips = [];
Osamu Nakamura 0:a40b9a259b52 1418
Osamu Nakamura 0:a40b9a259b52 1419 /**
Osamu Nakamura 0:a40b9a259b52 1420 * Enables a debug mode by name. This can include modes
Osamu Nakamura 0:a40b9a259b52 1421 * separated by a colon and wildcards.
Osamu Nakamura 0:a40b9a259b52 1422 *
Osamu Nakamura 0:a40b9a259b52 1423 * @param {String} name
Osamu Nakamura 0:a40b9a259b52 1424 * @api public
Osamu Nakamura 0:a40b9a259b52 1425 */
Osamu Nakamura 0:a40b9a259b52 1426
Osamu Nakamura 0:a40b9a259b52 1427 debug.enable = function(name) {
Osamu Nakamura 0:a40b9a259b52 1428 try {
Osamu Nakamura 0:a40b9a259b52 1429 localStorage.debug = name;
Osamu Nakamura 0:a40b9a259b52 1430 } catch(e){}
Osamu Nakamura 0:a40b9a259b52 1431
Osamu Nakamura 0:a40b9a259b52 1432 var split = (name || '').split(/[\s,]+/)
Osamu Nakamura 0:a40b9a259b52 1433 , len = split.length;
Osamu Nakamura 0:a40b9a259b52 1434
Osamu Nakamura 0:a40b9a259b52 1435 for (var i = 0; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 1436 name = split[i].replace('*', '.*?');
Osamu Nakamura 0:a40b9a259b52 1437 if (name[0] === '-') {
Osamu Nakamura 0:a40b9a259b52 1438 debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
Osamu Nakamura 0:a40b9a259b52 1439 }
Osamu Nakamura 0:a40b9a259b52 1440 else {
Osamu Nakamura 0:a40b9a259b52 1441 debug.names.push(new RegExp('^' + name + '$'));
Osamu Nakamura 0:a40b9a259b52 1442 }
Osamu Nakamura 0:a40b9a259b52 1443 }
Osamu Nakamura 0:a40b9a259b52 1444 };
Osamu Nakamura 0:a40b9a259b52 1445
Osamu Nakamura 0:a40b9a259b52 1446 /**
Osamu Nakamura 0:a40b9a259b52 1447 * Disable debug output.
Osamu Nakamura 0:a40b9a259b52 1448 *
Osamu Nakamura 0:a40b9a259b52 1449 * @api public
Osamu Nakamura 0:a40b9a259b52 1450 */
Osamu Nakamura 0:a40b9a259b52 1451
Osamu Nakamura 0:a40b9a259b52 1452 debug.disable = function(){
Osamu Nakamura 0:a40b9a259b52 1453 debug.enable('');
Osamu Nakamura 0:a40b9a259b52 1454 };
Osamu Nakamura 0:a40b9a259b52 1455
Osamu Nakamura 0:a40b9a259b52 1456 /**
Osamu Nakamura 0:a40b9a259b52 1457 * Humanize the given `ms`.
Osamu Nakamura 0:a40b9a259b52 1458 *
Osamu Nakamura 0:a40b9a259b52 1459 * @param {Number} m
Osamu Nakamura 0:a40b9a259b52 1460 * @return {String}
Osamu Nakamura 0:a40b9a259b52 1461 * @api private
Osamu Nakamura 0:a40b9a259b52 1462 */
Osamu Nakamura 0:a40b9a259b52 1463
Osamu Nakamura 0:a40b9a259b52 1464 debug.humanize = function(ms) {
Osamu Nakamura 0:a40b9a259b52 1465 var sec = 1000
Osamu Nakamura 0:a40b9a259b52 1466 , min = 60 * 1000
Osamu Nakamura 0:a40b9a259b52 1467 , hour = 60 * min;
Osamu Nakamura 0:a40b9a259b52 1468
Osamu Nakamura 0:a40b9a259b52 1469 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
Osamu Nakamura 0:a40b9a259b52 1470 if (ms >= min) return (ms / min).toFixed(1) + 'm';
Osamu Nakamura 0:a40b9a259b52 1471 if (ms >= sec) return (ms / sec | 0) + 's';
Osamu Nakamura 0:a40b9a259b52 1472 return ms + 'ms';
Osamu Nakamura 0:a40b9a259b52 1473 };
Osamu Nakamura 0:a40b9a259b52 1474
Osamu Nakamura 0:a40b9a259b52 1475 /**
Osamu Nakamura 0:a40b9a259b52 1476 * Returns true if the given mode name is enabled, false otherwise.
Osamu Nakamura 0:a40b9a259b52 1477 *
Osamu Nakamura 0:a40b9a259b52 1478 * @param {String} name
Osamu Nakamura 0:a40b9a259b52 1479 * @return {Boolean}
Osamu Nakamura 0:a40b9a259b52 1480 * @api public
Osamu Nakamura 0:a40b9a259b52 1481 */
Osamu Nakamura 0:a40b9a259b52 1482
Osamu Nakamura 0:a40b9a259b52 1483 debug.enabled = function(name) {
Osamu Nakamura 0:a40b9a259b52 1484 for (var i = 0, len = debug.skips.length; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 1485 if (debug.skips[i].test(name)) {
Osamu Nakamura 0:a40b9a259b52 1486 return false;
Osamu Nakamura 0:a40b9a259b52 1487 }
Osamu Nakamura 0:a40b9a259b52 1488 }
Osamu Nakamura 0:a40b9a259b52 1489 for (var i = 0, len = debug.names.length; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 1490 if (debug.names[i].test(name)) {
Osamu Nakamura 0:a40b9a259b52 1491 return true;
Osamu Nakamura 0:a40b9a259b52 1492 }
Osamu Nakamura 0:a40b9a259b52 1493 }
Osamu Nakamura 0:a40b9a259b52 1494 return false;
Osamu Nakamura 0:a40b9a259b52 1495 };
Osamu Nakamura 0:a40b9a259b52 1496
Osamu Nakamura 0:a40b9a259b52 1497 /**
Osamu Nakamura 0:a40b9a259b52 1498 * Coerce `val`.
Osamu Nakamura 0:a40b9a259b52 1499 */
Osamu Nakamura 0:a40b9a259b52 1500
Osamu Nakamura 0:a40b9a259b52 1501 function coerce(val) {
Osamu Nakamura 0:a40b9a259b52 1502 if (val instanceof Error) return val.stack || val.message;
Osamu Nakamura 0:a40b9a259b52 1503 return val;
Osamu Nakamura 0:a40b9a259b52 1504 }
Osamu Nakamura 0:a40b9a259b52 1505
Osamu Nakamura 0:a40b9a259b52 1506 // persist
Osamu Nakamura 0:a40b9a259b52 1507
Osamu Nakamura 0:a40b9a259b52 1508 try {
Osamu Nakamura 0:a40b9a259b52 1509 if (window.localStorage) debug.enable(localStorage.debug);
Osamu Nakamura 0:a40b9a259b52 1510 } catch(e){}
Osamu Nakamura 0:a40b9a259b52 1511
Osamu Nakamura 0:a40b9a259b52 1512 },{}],11:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1513
Osamu Nakamura 0:a40b9a259b52 1514 module.exports = _dereq_('./lib/');
Osamu Nakamura 0:a40b9a259b52 1515
Osamu Nakamura 0:a40b9a259b52 1516 },{"./lib/":12}],12:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1517
Osamu Nakamura 0:a40b9a259b52 1518 module.exports = _dereq_('./socket');
Osamu Nakamura 0:a40b9a259b52 1519
Osamu Nakamura 0:a40b9a259b52 1520 /**
Osamu Nakamura 0:a40b9a259b52 1521 * Exports parser
Osamu Nakamura 0:a40b9a259b52 1522 *
Osamu Nakamura 0:a40b9a259b52 1523 * @api public
Osamu Nakamura 0:a40b9a259b52 1524 *
Osamu Nakamura 0:a40b9a259b52 1525 */
Osamu Nakamura 0:a40b9a259b52 1526 module.exports.parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 1527
Osamu Nakamura 0:a40b9a259b52 1528 },{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 1529 (function (global){
Osamu Nakamura 0:a40b9a259b52 1530 /**
Osamu Nakamura 0:a40b9a259b52 1531 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 1532 */
Osamu Nakamura 0:a40b9a259b52 1533
Osamu Nakamura 0:a40b9a259b52 1534 var transports = _dereq_('./transports');
Osamu Nakamura 0:a40b9a259b52 1535 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 1536 var debug = _dereq_('debug')('engine.io-client:socket');
Osamu Nakamura 0:a40b9a259b52 1537 var index = _dereq_('indexof');
Osamu Nakamura 0:a40b9a259b52 1538 var parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 1539 var parseuri = _dereq_('parseuri');
Osamu Nakamura 0:a40b9a259b52 1540 var parsejson = _dereq_('parsejson');
Osamu Nakamura 0:a40b9a259b52 1541 var parseqs = _dereq_('parseqs');
Osamu Nakamura 0:a40b9a259b52 1542
Osamu Nakamura 0:a40b9a259b52 1543 /**
Osamu Nakamura 0:a40b9a259b52 1544 * Module exports.
Osamu Nakamura 0:a40b9a259b52 1545 */
Osamu Nakamura 0:a40b9a259b52 1546
Osamu Nakamura 0:a40b9a259b52 1547 module.exports = Socket;
Osamu Nakamura 0:a40b9a259b52 1548
Osamu Nakamura 0:a40b9a259b52 1549 /**
Osamu Nakamura 0:a40b9a259b52 1550 * Noop function.
Osamu Nakamura 0:a40b9a259b52 1551 *
Osamu Nakamura 0:a40b9a259b52 1552 * @api private
Osamu Nakamura 0:a40b9a259b52 1553 */
Osamu Nakamura 0:a40b9a259b52 1554
Osamu Nakamura 0:a40b9a259b52 1555 function noop(){}
Osamu Nakamura 0:a40b9a259b52 1556
Osamu Nakamura 0:a40b9a259b52 1557 /**
Osamu Nakamura 0:a40b9a259b52 1558 * Socket constructor.
Osamu Nakamura 0:a40b9a259b52 1559 *
Osamu Nakamura 0:a40b9a259b52 1560 * @param {String|Object} uri or options
Osamu Nakamura 0:a40b9a259b52 1561 * @param {Object} options
Osamu Nakamura 0:a40b9a259b52 1562 * @api public
Osamu Nakamura 0:a40b9a259b52 1563 */
Osamu Nakamura 0:a40b9a259b52 1564
Osamu Nakamura 0:a40b9a259b52 1565 function Socket(uri, opts){
Osamu Nakamura 0:a40b9a259b52 1566 if (!(this instanceof Socket)) return new Socket(uri, opts);
Osamu Nakamura 0:a40b9a259b52 1567
Osamu Nakamura 0:a40b9a259b52 1568 opts = opts || {};
Osamu Nakamura 0:a40b9a259b52 1569
Osamu Nakamura 0:a40b9a259b52 1570 if (uri && 'object' == typeof uri) {
Osamu Nakamura 0:a40b9a259b52 1571 opts = uri;
Osamu Nakamura 0:a40b9a259b52 1572 uri = null;
Osamu Nakamura 0:a40b9a259b52 1573 }
Osamu Nakamura 0:a40b9a259b52 1574
Osamu Nakamura 0:a40b9a259b52 1575 if (uri) {
Osamu Nakamura 0:a40b9a259b52 1576 uri = parseuri(uri);
Osamu Nakamura 0:a40b9a259b52 1577 opts.host = uri.host;
Osamu Nakamura 0:a40b9a259b52 1578 opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
Osamu Nakamura 0:a40b9a259b52 1579 opts.port = uri.port;
Osamu Nakamura 0:a40b9a259b52 1580 if (uri.query) opts.query = uri.query;
Osamu Nakamura 0:a40b9a259b52 1581 }
Osamu Nakamura 0:a40b9a259b52 1582
Osamu Nakamura 0:a40b9a259b52 1583 this.secure = null != opts.secure ? opts.secure :
Osamu Nakamura 0:a40b9a259b52 1584 (global.location && 'https:' == location.protocol);
Osamu Nakamura 0:a40b9a259b52 1585
Osamu Nakamura 0:a40b9a259b52 1586 if (opts.host) {
Osamu Nakamura 0:a40b9a259b52 1587 var pieces = opts.host.split(':');
Osamu Nakamura 0:a40b9a259b52 1588 opts.hostname = pieces.shift();
Osamu Nakamura 0:a40b9a259b52 1589 if (pieces.length) {
Osamu Nakamura 0:a40b9a259b52 1590 opts.port = pieces.pop();
Osamu Nakamura 0:a40b9a259b52 1591 } else if (!opts.port) {
Osamu Nakamura 0:a40b9a259b52 1592 // if no port is specified manually, use the protocol default
Osamu Nakamura 0:a40b9a259b52 1593 opts.port = this.secure ? '443' : '80';
Osamu Nakamura 0:a40b9a259b52 1594 }
Osamu Nakamura 0:a40b9a259b52 1595 }
Osamu Nakamura 0:a40b9a259b52 1596
Osamu Nakamura 0:a40b9a259b52 1597 this.agent = opts.agent || false;
Osamu Nakamura 0:a40b9a259b52 1598 this.hostname = opts.hostname ||
Osamu Nakamura 0:a40b9a259b52 1599 (global.location ? location.hostname : 'localhost');
Osamu Nakamura 0:a40b9a259b52 1600 this.port = opts.port || (global.location && location.port ?
Osamu Nakamura 0:a40b9a259b52 1601 location.port :
Osamu Nakamura 0:a40b9a259b52 1602 (this.secure ? 443 : 80));
Osamu Nakamura 0:a40b9a259b52 1603 this.query = opts.query || {};
Osamu Nakamura 0:a40b9a259b52 1604 if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
Osamu Nakamura 0:a40b9a259b52 1605 this.upgrade = false !== opts.upgrade;
Osamu Nakamura 0:a40b9a259b52 1606 this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
Osamu Nakamura 0:a40b9a259b52 1607 this.forceJSONP = !!opts.forceJSONP;
Osamu Nakamura 0:a40b9a259b52 1608 this.jsonp = false !== opts.jsonp;
Osamu Nakamura 0:a40b9a259b52 1609 this.forceBase64 = !!opts.forceBase64;
Osamu Nakamura 0:a40b9a259b52 1610 this.enablesXDR = !!opts.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 1611 this.timestampParam = opts.timestampParam || 't';
Osamu Nakamura 0:a40b9a259b52 1612 this.timestampRequests = opts.timestampRequests;
Osamu Nakamura 0:a40b9a259b52 1613 this.transports = opts.transports || ['polling', 'websocket'];
Osamu Nakamura 0:a40b9a259b52 1614 this.readyState = '';
Osamu Nakamura 0:a40b9a259b52 1615 this.writeBuffer = [];
Osamu Nakamura 0:a40b9a259b52 1616 this.callbackBuffer = [];
Osamu Nakamura 0:a40b9a259b52 1617 this.policyPort = opts.policyPort || 843;
Osamu Nakamura 0:a40b9a259b52 1618 this.rememberUpgrade = opts.rememberUpgrade || false;
Osamu Nakamura 0:a40b9a259b52 1619 this.binaryType = null;
Osamu Nakamura 0:a40b9a259b52 1620 this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
Osamu Nakamura 0:a40b9a259b52 1621
Osamu Nakamura 0:a40b9a259b52 1622 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 1623 this.pfx = opts.pfx || null;
Osamu Nakamura 0:a40b9a259b52 1624 this.key = opts.key || null;
Osamu Nakamura 0:a40b9a259b52 1625 this.passphrase = opts.passphrase || null;
Osamu Nakamura 0:a40b9a259b52 1626 this.cert = opts.cert || null;
Osamu Nakamura 0:a40b9a259b52 1627 this.ca = opts.ca || null;
Osamu Nakamura 0:a40b9a259b52 1628 this.ciphers = opts.ciphers || null;
Osamu Nakamura 0:a40b9a259b52 1629 this.rejectUnauthorized = opts.rejectUnauthorized || null;
Osamu Nakamura 0:a40b9a259b52 1630
Osamu Nakamura 0:a40b9a259b52 1631 this.open();
Osamu Nakamura 0:a40b9a259b52 1632 }
Osamu Nakamura 0:a40b9a259b52 1633
Osamu Nakamura 0:a40b9a259b52 1634 Socket.priorWebsocketSuccess = false;
Osamu Nakamura 0:a40b9a259b52 1635
Osamu Nakamura 0:a40b9a259b52 1636 /**
Osamu Nakamura 0:a40b9a259b52 1637 * Mix in `Emitter`.
Osamu Nakamura 0:a40b9a259b52 1638 */
Osamu Nakamura 0:a40b9a259b52 1639
Osamu Nakamura 0:a40b9a259b52 1640 Emitter(Socket.prototype);
Osamu Nakamura 0:a40b9a259b52 1641
Osamu Nakamura 0:a40b9a259b52 1642 /**
Osamu Nakamura 0:a40b9a259b52 1643 * Protocol version.
Osamu Nakamura 0:a40b9a259b52 1644 *
Osamu Nakamura 0:a40b9a259b52 1645 * @api public
Osamu Nakamura 0:a40b9a259b52 1646 */
Osamu Nakamura 0:a40b9a259b52 1647
Osamu Nakamura 0:a40b9a259b52 1648 Socket.protocol = parser.protocol; // this is an int
Osamu Nakamura 0:a40b9a259b52 1649
Osamu Nakamura 0:a40b9a259b52 1650 /**
Osamu Nakamura 0:a40b9a259b52 1651 * Expose deps for legacy compatibility
Osamu Nakamura 0:a40b9a259b52 1652 * and standalone browser access.
Osamu Nakamura 0:a40b9a259b52 1653 */
Osamu Nakamura 0:a40b9a259b52 1654
Osamu Nakamura 0:a40b9a259b52 1655 Socket.Socket = Socket;
Osamu Nakamura 0:a40b9a259b52 1656 Socket.Transport = _dereq_('./transport');
Osamu Nakamura 0:a40b9a259b52 1657 Socket.transports = _dereq_('./transports');
Osamu Nakamura 0:a40b9a259b52 1658 Socket.parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 1659
Osamu Nakamura 0:a40b9a259b52 1660 /**
Osamu Nakamura 0:a40b9a259b52 1661 * Creates transport of the given type.
Osamu Nakamura 0:a40b9a259b52 1662 *
Osamu Nakamura 0:a40b9a259b52 1663 * @param {String} transport name
Osamu Nakamura 0:a40b9a259b52 1664 * @return {Transport}
Osamu Nakamura 0:a40b9a259b52 1665 * @api private
Osamu Nakamura 0:a40b9a259b52 1666 */
Osamu Nakamura 0:a40b9a259b52 1667
Osamu Nakamura 0:a40b9a259b52 1668 Socket.prototype.createTransport = function (name) {
Osamu Nakamura 0:a40b9a259b52 1669 debug('creating transport "%s"', name);
Osamu Nakamura 0:a40b9a259b52 1670 var query = clone(this.query);
Osamu Nakamura 0:a40b9a259b52 1671
Osamu Nakamura 0:a40b9a259b52 1672 // append engine.io protocol identifier
Osamu Nakamura 0:a40b9a259b52 1673 query.EIO = parser.protocol;
Osamu Nakamura 0:a40b9a259b52 1674
Osamu Nakamura 0:a40b9a259b52 1675 // transport name
Osamu Nakamura 0:a40b9a259b52 1676 query.transport = name;
Osamu Nakamura 0:a40b9a259b52 1677
Osamu Nakamura 0:a40b9a259b52 1678 // session id if we already have one
Osamu Nakamura 0:a40b9a259b52 1679 if (this.id) query.sid = this.id;
Osamu Nakamura 0:a40b9a259b52 1680
Osamu Nakamura 0:a40b9a259b52 1681 var transport = new transports[name]({
Osamu Nakamura 0:a40b9a259b52 1682 agent: this.agent,
Osamu Nakamura 0:a40b9a259b52 1683 hostname: this.hostname,
Osamu Nakamura 0:a40b9a259b52 1684 port: this.port,
Osamu Nakamura 0:a40b9a259b52 1685 secure: this.secure,
Osamu Nakamura 0:a40b9a259b52 1686 path: this.path,
Osamu Nakamura 0:a40b9a259b52 1687 query: query,
Osamu Nakamura 0:a40b9a259b52 1688 forceJSONP: this.forceJSONP,
Osamu Nakamura 0:a40b9a259b52 1689 jsonp: this.jsonp,
Osamu Nakamura 0:a40b9a259b52 1690 forceBase64: this.forceBase64,
Osamu Nakamura 0:a40b9a259b52 1691 enablesXDR: this.enablesXDR,
Osamu Nakamura 0:a40b9a259b52 1692 timestampRequests: this.timestampRequests,
Osamu Nakamura 0:a40b9a259b52 1693 timestampParam: this.timestampParam,
Osamu Nakamura 0:a40b9a259b52 1694 policyPort: this.policyPort,
Osamu Nakamura 0:a40b9a259b52 1695 socket: this,
Osamu Nakamura 0:a40b9a259b52 1696 pfx: this.pfx,
Osamu Nakamura 0:a40b9a259b52 1697 key: this.key,
Osamu Nakamura 0:a40b9a259b52 1698 passphrase: this.passphrase,
Osamu Nakamura 0:a40b9a259b52 1699 cert: this.cert,
Osamu Nakamura 0:a40b9a259b52 1700 ca: this.ca,
Osamu Nakamura 0:a40b9a259b52 1701 ciphers: this.ciphers,
Osamu Nakamura 0:a40b9a259b52 1702 rejectUnauthorized: this.rejectUnauthorized
Osamu Nakamura 0:a40b9a259b52 1703 });
Osamu Nakamura 0:a40b9a259b52 1704
Osamu Nakamura 0:a40b9a259b52 1705 return transport;
Osamu Nakamura 0:a40b9a259b52 1706 };
Osamu Nakamura 0:a40b9a259b52 1707
Osamu Nakamura 0:a40b9a259b52 1708 function clone (obj) {
Osamu Nakamura 0:a40b9a259b52 1709 var o = {};
Osamu Nakamura 0:a40b9a259b52 1710 for (var i in obj) {
Osamu Nakamura 0:a40b9a259b52 1711 if (obj.hasOwnProperty(i)) {
Osamu Nakamura 0:a40b9a259b52 1712 o[i] = obj[i];
Osamu Nakamura 0:a40b9a259b52 1713 }
Osamu Nakamura 0:a40b9a259b52 1714 }
Osamu Nakamura 0:a40b9a259b52 1715 return o;
Osamu Nakamura 0:a40b9a259b52 1716 }
Osamu Nakamura 0:a40b9a259b52 1717
Osamu Nakamura 0:a40b9a259b52 1718 /**
Osamu Nakamura 0:a40b9a259b52 1719 * Initializes transport to use and starts probe.
Osamu Nakamura 0:a40b9a259b52 1720 *
Osamu Nakamura 0:a40b9a259b52 1721 * @api private
Osamu Nakamura 0:a40b9a259b52 1722 */
Osamu Nakamura 0:a40b9a259b52 1723 Socket.prototype.open = function () {
Osamu Nakamura 0:a40b9a259b52 1724 var transport;
Osamu Nakamura 0:a40b9a259b52 1725 if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
Osamu Nakamura 0:a40b9a259b52 1726 transport = 'websocket';
Osamu Nakamura 0:a40b9a259b52 1727 } else if (0 == this.transports.length) {
Osamu Nakamura 0:a40b9a259b52 1728 // Emit error on next tick so it can be listened to
Osamu Nakamura 0:a40b9a259b52 1729 var self = this;
Osamu Nakamura 0:a40b9a259b52 1730 setTimeout(function() {
Osamu Nakamura 0:a40b9a259b52 1731 self.emit('error', 'No transports available');
Osamu Nakamura 0:a40b9a259b52 1732 }, 0);
Osamu Nakamura 0:a40b9a259b52 1733 return;
Osamu Nakamura 0:a40b9a259b52 1734 } else {
Osamu Nakamura 0:a40b9a259b52 1735 transport = this.transports[0];
Osamu Nakamura 0:a40b9a259b52 1736 }
Osamu Nakamura 0:a40b9a259b52 1737 this.readyState = 'opening';
Osamu Nakamura 0:a40b9a259b52 1738
Osamu Nakamura 0:a40b9a259b52 1739 // Retry with the next transport if the transport is disabled (jsonp: false)
Osamu Nakamura 0:a40b9a259b52 1740 var transport;
Osamu Nakamura 0:a40b9a259b52 1741 try {
Osamu Nakamura 0:a40b9a259b52 1742 transport = this.createTransport(transport);
Osamu Nakamura 0:a40b9a259b52 1743 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 1744 this.transports.shift();
Osamu Nakamura 0:a40b9a259b52 1745 this.open();
Osamu Nakamura 0:a40b9a259b52 1746 return;
Osamu Nakamura 0:a40b9a259b52 1747 }
Osamu Nakamura 0:a40b9a259b52 1748
Osamu Nakamura 0:a40b9a259b52 1749 transport.open();
Osamu Nakamura 0:a40b9a259b52 1750 this.setTransport(transport);
Osamu Nakamura 0:a40b9a259b52 1751 };
Osamu Nakamura 0:a40b9a259b52 1752
Osamu Nakamura 0:a40b9a259b52 1753 /**
Osamu Nakamura 0:a40b9a259b52 1754 * Sets the current transport. Disables the existing one (if any).
Osamu Nakamura 0:a40b9a259b52 1755 *
Osamu Nakamura 0:a40b9a259b52 1756 * @api private
Osamu Nakamura 0:a40b9a259b52 1757 */
Osamu Nakamura 0:a40b9a259b52 1758
Osamu Nakamura 0:a40b9a259b52 1759 Socket.prototype.setTransport = function(transport){
Osamu Nakamura 0:a40b9a259b52 1760 debug('setting transport %s', transport.name);
Osamu Nakamura 0:a40b9a259b52 1761 var self = this;
Osamu Nakamura 0:a40b9a259b52 1762
Osamu Nakamura 0:a40b9a259b52 1763 if (this.transport) {
Osamu Nakamura 0:a40b9a259b52 1764 debug('clearing existing transport %s', this.transport.name);
Osamu Nakamura 0:a40b9a259b52 1765 this.transport.removeAllListeners();
Osamu Nakamura 0:a40b9a259b52 1766 }
Osamu Nakamura 0:a40b9a259b52 1767
Osamu Nakamura 0:a40b9a259b52 1768 // set up transport
Osamu Nakamura 0:a40b9a259b52 1769 this.transport = transport;
Osamu Nakamura 0:a40b9a259b52 1770
Osamu Nakamura 0:a40b9a259b52 1771 // set up transport listeners
Osamu Nakamura 0:a40b9a259b52 1772 transport
Osamu Nakamura 0:a40b9a259b52 1773 .on('drain', function(){
Osamu Nakamura 0:a40b9a259b52 1774 self.onDrain();
Osamu Nakamura 0:a40b9a259b52 1775 })
Osamu Nakamura 0:a40b9a259b52 1776 .on('packet', function(packet){
Osamu Nakamura 0:a40b9a259b52 1777 self.onPacket(packet);
Osamu Nakamura 0:a40b9a259b52 1778 })
Osamu Nakamura 0:a40b9a259b52 1779 .on('error', function(e){
Osamu Nakamura 0:a40b9a259b52 1780 self.onError(e);
Osamu Nakamura 0:a40b9a259b52 1781 })
Osamu Nakamura 0:a40b9a259b52 1782 .on('close', function(){
Osamu Nakamura 0:a40b9a259b52 1783 self.onClose('transport close');
Osamu Nakamura 0:a40b9a259b52 1784 });
Osamu Nakamura 0:a40b9a259b52 1785 };
Osamu Nakamura 0:a40b9a259b52 1786
Osamu Nakamura 0:a40b9a259b52 1787 /**
Osamu Nakamura 0:a40b9a259b52 1788 * Probes a transport.
Osamu Nakamura 0:a40b9a259b52 1789 *
Osamu Nakamura 0:a40b9a259b52 1790 * @param {String} transport name
Osamu Nakamura 0:a40b9a259b52 1791 * @api private
Osamu Nakamura 0:a40b9a259b52 1792 */
Osamu Nakamura 0:a40b9a259b52 1793
Osamu Nakamura 0:a40b9a259b52 1794 Socket.prototype.probe = function (name) {
Osamu Nakamura 0:a40b9a259b52 1795 debug('probing transport "%s"', name);
Osamu Nakamura 0:a40b9a259b52 1796 var transport = this.createTransport(name, { probe: 1 })
Osamu Nakamura 0:a40b9a259b52 1797 , failed = false
Osamu Nakamura 0:a40b9a259b52 1798 , self = this;
Osamu Nakamura 0:a40b9a259b52 1799
Osamu Nakamura 0:a40b9a259b52 1800 Socket.priorWebsocketSuccess = false;
Osamu Nakamura 0:a40b9a259b52 1801
Osamu Nakamura 0:a40b9a259b52 1802 function onTransportOpen(){
Osamu Nakamura 0:a40b9a259b52 1803 if (self.onlyBinaryUpgrades) {
Osamu Nakamura 0:a40b9a259b52 1804 var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
Osamu Nakamura 0:a40b9a259b52 1805 failed = failed || upgradeLosesBinary;
Osamu Nakamura 0:a40b9a259b52 1806 }
Osamu Nakamura 0:a40b9a259b52 1807 if (failed) return;
Osamu Nakamura 0:a40b9a259b52 1808
Osamu Nakamura 0:a40b9a259b52 1809 debug('probe transport "%s" opened', name);
Osamu Nakamura 0:a40b9a259b52 1810 transport.send([{ type: 'ping', data: 'probe' }]);
Osamu Nakamura 0:a40b9a259b52 1811 transport.once('packet', function (msg) {
Osamu Nakamura 0:a40b9a259b52 1812 if (failed) return;
Osamu Nakamura 0:a40b9a259b52 1813 if ('pong' == msg.type && 'probe' == msg.data) {
Osamu Nakamura 0:a40b9a259b52 1814 debug('probe transport "%s" pong', name);
Osamu Nakamura 0:a40b9a259b52 1815 self.upgrading = true;
Osamu Nakamura 0:a40b9a259b52 1816 self.emit('upgrading', transport);
Osamu Nakamura 0:a40b9a259b52 1817 if (!transport) return;
Osamu Nakamura 0:a40b9a259b52 1818 Socket.priorWebsocketSuccess = 'websocket' == transport.name;
Osamu Nakamura 0:a40b9a259b52 1819
Osamu Nakamura 0:a40b9a259b52 1820 debug('pausing current transport "%s"', self.transport.name);
Osamu Nakamura 0:a40b9a259b52 1821 self.transport.pause(function () {
Osamu Nakamura 0:a40b9a259b52 1822 if (failed) return;
Osamu Nakamura 0:a40b9a259b52 1823 if ('closed' == self.readyState) return;
Osamu Nakamura 0:a40b9a259b52 1824 debug('changing transport and sending upgrade packet');
Osamu Nakamura 0:a40b9a259b52 1825
Osamu Nakamura 0:a40b9a259b52 1826 cleanup();
Osamu Nakamura 0:a40b9a259b52 1827
Osamu Nakamura 0:a40b9a259b52 1828 self.setTransport(transport);
Osamu Nakamura 0:a40b9a259b52 1829 transport.send([{ type: 'upgrade' }]);
Osamu Nakamura 0:a40b9a259b52 1830 self.emit('upgrade', transport);
Osamu Nakamura 0:a40b9a259b52 1831 transport = null;
Osamu Nakamura 0:a40b9a259b52 1832 self.upgrading = false;
Osamu Nakamura 0:a40b9a259b52 1833 self.flush();
Osamu Nakamura 0:a40b9a259b52 1834 });
Osamu Nakamura 0:a40b9a259b52 1835 } else {
Osamu Nakamura 0:a40b9a259b52 1836 debug('probe transport "%s" failed', name);
Osamu Nakamura 0:a40b9a259b52 1837 var err = new Error('probe error');
Osamu Nakamura 0:a40b9a259b52 1838 err.transport = transport.name;
Osamu Nakamura 0:a40b9a259b52 1839 self.emit('upgradeError', err);
Osamu Nakamura 0:a40b9a259b52 1840 }
Osamu Nakamura 0:a40b9a259b52 1841 });
Osamu Nakamura 0:a40b9a259b52 1842 }
Osamu Nakamura 0:a40b9a259b52 1843
Osamu Nakamura 0:a40b9a259b52 1844 function freezeTransport() {
Osamu Nakamura 0:a40b9a259b52 1845 if (failed) return;
Osamu Nakamura 0:a40b9a259b52 1846
Osamu Nakamura 0:a40b9a259b52 1847 // Any callback called by transport should be ignored since now
Osamu Nakamura 0:a40b9a259b52 1848 failed = true;
Osamu Nakamura 0:a40b9a259b52 1849
Osamu Nakamura 0:a40b9a259b52 1850 cleanup();
Osamu Nakamura 0:a40b9a259b52 1851
Osamu Nakamura 0:a40b9a259b52 1852 transport.close();
Osamu Nakamura 0:a40b9a259b52 1853 transport = null;
Osamu Nakamura 0:a40b9a259b52 1854 }
Osamu Nakamura 0:a40b9a259b52 1855
Osamu Nakamura 0:a40b9a259b52 1856 //Handle any error that happens while probing
Osamu Nakamura 0:a40b9a259b52 1857 function onerror(err) {
Osamu Nakamura 0:a40b9a259b52 1858 var error = new Error('probe error: ' + err);
Osamu Nakamura 0:a40b9a259b52 1859 error.transport = transport.name;
Osamu Nakamura 0:a40b9a259b52 1860
Osamu Nakamura 0:a40b9a259b52 1861 freezeTransport();
Osamu Nakamura 0:a40b9a259b52 1862
Osamu Nakamura 0:a40b9a259b52 1863 debug('probe transport "%s" failed because of error: %s', name, err);
Osamu Nakamura 0:a40b9a259b52 1864
Osamu Nakamura 0:a40b9a259b52 1865 self.emit('upgradeError', error);
Osamu Nakamura 0:a40b9a259b52 1866 }
Osamu Nakamura 0:a40b9a259b52 1867
Osamu Nakamura 0:a40b9a259b52 1868 function onTransportClose(){
Osamu Nakamura 0:a40b9a259b52 1869 onerror("transport closed");
Osamu Nakamura 0:a40b9a259b52 1870 }
Osamu Nakamura 0:a40b9a259b52 1871
Osamu Nakamura 0:a40b9a259b52 1872 //When the socket is closed while we're probing
Osamu Nakamura 0:a40b9a259b52 1873 function onclose(){
Osamu Nakamura 0:a40b9a259b52 1874 onerror("socket closed");
Osamu Nakamura 0:a40b9a259b52 1875 }
Osamu Nakamura 0:a40b9a259b52 1876
Osamu Nakamura 0:a40b9a259b52 1877 //When the socket is upgraded while we're probing
Osamu Nakamura 0:a40b9a259b52 1878 function onupgrade(to){
Osamu Nakamura 0:a40b9a259b52 1879 if (transport && to.name != transport.name) {
Osamu Nakamura 0:a40b9a259b52 1880 debug('"%s" works - aborting "%s"', to.name, transport.name);
Osamu Nakamura 0:a40b9a259b52 1881 freezeTransport();
Osamu Nakamura 0:a40b9a259b52 1882 }
Osamu Nakamura 0:a40b9a259b52 1883 }
Osamu Nakamura 0:a40b9a259b52 1884
Osamu Nakamura 0:a40b9a259b52 1885 //Remove all listeners on the transport and on self
Osamu Nakamura 0:a40b9a259b52 1886 function cleanup(){
Osamu Nakamura 0:a40b9a259b52 1887 transport.removeListener('open', onTransportOpen);
Osamu Nakamura 0:a40b9a259b52 1888 transport.removeListener('error', onerror);
Osamu Nakamura 0:a40b9a259b52 1889 transport.removeListener('close', onTransportClose);
Osamu Nakamura 0:a40b9a259b52 1890 self.removeListener('close', onclose);
Osamu Nakamura 0:a40b9a259b52 1891 self.removeListener('upgrading', onupgrade);
Osamu Nakamura 0:a40b9a259b52 1892 }
Osamu Nakamura 0:a40b9a259b52 1893
Osamu Nakamura 0:a40b9a259b52 1894 transport.once('open', onTransportOpen);
Osamu Nakamura 0:a40b9a259b52 1895 transport.once('error', onerror);
Osamu Nakamura 0:a40b9a259b52 1896 transport.once('close', onTransportClose);
Osamu Nakamura 0:a40b9a259b52 1897
Osamu Nakamura 0:a40b9a259b52 1898 this.once('close', onclose);
Osamu Nakamura 0:a40b9a259b52 1899 this.once('upgrading', onupgrade);
Osamu Nakamura 0:a40b9a259b52 1900
Osamu Nakamura 0:a40b9a259b52 1901 transport.open();
Osamu Nakamura 0:a40b9a259b52 1902
Osamu Nakamura 0:a40b9a259b52 1903 };
Osamu Nakamura 0:a40b9a259b52 1904
Osamu Nakamura 0:a40b9a259b52 1905 /**
Osamu Nakamura 0:a40b9a259b52 1906 * Called when connection is deemed open.
Osamu Nakamura 0:a40b9a259b52 1907 *
Osamu Nakamura 0:a40b9a259b52 1908 * @api public
Osamu Nakamura 0:a40b9a259b52 1909 */
Osamu Nakamura 0:a40b9a259b52 1910
Osamu Nakamura 0:a40b9a259b52 1911 Socket.prototype.onOpen = function () {
Osamu Nakamura 0:a40b9a259b52 1912 debug('socket open');
Osamu Nakamura 0:a40b9a259b52 1913 this.readyState = 'open';
Osamu Nakamura 0:a40b9a259b52 1914 Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
Osamu Nakamura 0:a40b9a259b52 1915 this.emit('open');
Osamu Nakamura 0:a40b9a259b52 1916 this.flush();
Osamu Nakamura 0:a40b9a259b52 1917
Osamu Nakamura 0:a40b9a259b52 1918 // we check for `readyState` in case an `open`
Osamu Nakamura 0:a40b9a259b52 1919 // listener already closed the socket
Osamu Nakamura 0:a40b9a259b52 1920 if ('open' == this.readyState && this.upgrade && this.transport.pause) {
Osamu Nakamura 0:a40b9a259b52 1921 debug('starting upgrade probes');
Osamu Nakamura 0:a40b9a259b52 1922 for (var i = 0, l = this.upgrades.length; i < l; i++) {
Osamu Nakamura 0:a40b9a259b52 1923 this.probe(this.upgrades[i]);
Osamu Nakamura 0:a40b9a259b52 1924 }
Osamu Nakamura 0:a40b9a259b52 1925 }
Osamu Nakamura 0:a40b9a259b52 1926 };
Osamu Nakamura 0:a40b9a259b52 1927
Osamu Nakamura 0:a40b9a259b52 1928 /**
Osamu Nakamura 0:a40b9a259b52 1929 * Handles a packet.
Osamu Nakamura 0:a40b9a259b52 1930 *
Osamu Nakamura 0:a40b9a259b52 1931 * @api private
Osamu Nakamura 0:a40b9a259b52 1932 */
Osamu Nakamura 0:a40b9a259b52 1933
Osamu Nakamura 0:a40b9a259b52 1934 Socket.prototype.onPacket = function (packet) {
Osamu Nakamura 0:a40b9a259b52 1935 if ('opening' == this.readyState || 'open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 1936 debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
Osamu Nakamura 0:a40b9a259b52 1937
Osamu Nakamura 0:a40b9a259b52 1938 this.emit('packet', packet);
Osamu Nakamura 0:a40b9a259b52 1939
Osamu Nakamura 0:a40b9a259b52 1940 // Socket is live - any packet counts
Osamu Nakamura 0:a40b9a259b52 1941 this.emit('heartbeat');
Osamu Nakamura 0:a40b9a259b52 1942
Osamu Nakamura 0:a40b9a259b52 1943 switch (packet.type) {
Osamu Nakamura 0:a40b9a259b52 1944 case 'open':
Osamu Nakamura 0:a40b9a259b52 1945 this.onHandshake(parsejson(packet.data));
Osamu Nakamura 0:a40b9a259b52 1946 break;
Osamu Nakamura 0:a40b9a259b52 1947
Osamu Nakamura 0:a40b9a259b52 1948 case 'pong':
Osamu Nakamura 0:a40b9a259b52 1949 this.setPing();
Osamu Nakamura 0:a40b9a259b52 1950 break;
Osamu Nakamura 0:a40b9a259b52 1951
Osamu Nakamura 0:a40b9a259b52 1952 case 'error':
Osamu Nakamura 0:a40b9a259b52 1953 var err = new Error('server error');
Osamu Nakamura 0:a40b9a259b52 1954 err.code = packet.data;
Osamu Nakamura 0:a40b9a259b52 1955 this.emit('error', err);
Osamu Nakamura 0:a40b9a259b52 1956 break;
Osamu Nakamura 0:a40b9a259b52 1957
Osamu Nakamura 0:a40b9a259b52 1958 case 'message':
Osamu Nakamura 0:a40b9a259b52 1959 this.emit('data', packet.data);
Osamu Nakamura 0:a40b9a259b52 1960 this.emit('message', packet.data);
Osamu Nakamura 0:a40b9a259b52 1961 break;
Osamu Nakamura 0:a40b9a259b52 1962 }
Osamu Nakamura 0:a40b9a259b52 1963 } else {
Osamu Nakamura 0:a40b9a259b52 1964 debug('packet received with socket readyState "%s"', this.readyState);
Osamu Nakamura 0:a40b9a259b52 1965 }
Osamu Nakamura 0:a40b9a259b52 1966 };
Osamu Nakamura 0:a40b9a259b52 1967
Osamu Nakamura 0:a40b9a259b52 1968 /**
Osamu Nakamura 0:a40b9a259b52 1969 * Called upon handshake completion.
Osamu Nakamura 0:a40b9a259b52 1970 *
Osamu Nakamura 0:a40b9a259b52 1971 * @param {Object} handshake obj
Osamu Nakamura 0:a40b9a259b52 1972 * @api private
Osamu Nakamura 0:a40b9a259b52 1973 */
Osamu Nakamura 0:a40b9a259b52 1974
Osamu Nakamura 0:a40b9a259b52 1975 Socket.prototype.onHandshake = function (data) {
Osamu Nakamura 0:a40b9a259b52 1976 this.emit('handshake', data);
Osamu Nakamura 0:a40b9a259b52 1977 this.id = data.sid;
Osamu Nakamura 0:a40b9a259b52 1978 this.transport.query.sid = data.sid;
Osamu Nakamura 0:a40b9a259b52 1979 this.upgrades = this.filterUpgrades(data.upgrades);
Osamu Nakamura 0:a40b9a259b52 1980 this.pingInterval = data.pingInterval;
Osamu Nakamura 0:a40b9a259b52 1981 this.pingTimeout = data.pingTimeout;
Osamu Nakamura 0:a40b9a259b52 1982 this.onOpen();
Osamu Nakamura 0:a40b9a259b52 1983 // In case open handler closes socket
Osamu Nakamura 0:a40b9a259b52 1984 if ('closed' == this.readyState) return;
Osamu Nakamura 0:a40b9a259b52 1985 this.setPing();
Osamu Nakamura 0:a40b9a259b52 1986
Osamu Nakamura 0:a40b9a259b52 1987 // Prolong liveness of socket on heartbeat
Osamu Nakamura 0:a40b9a259b52 1988 this.removeListener('heartbeat', this.onHeartbeat);
Osamu Nakamura 0:a40b9a259b52 1989 this.on('heartbeat', this.onHeartbeat);
Osamu Nakamura 0:a40b9a259b52 1990 };
Osamu Nakamura 0:a40b9a259b52 1991
Osamu Nakamura 0:a40b9a259b52 1992 /**
Osamu Nakamura 0:a40b9a259b52 1993 * Resets ping timeout.
Osamu Nakamura 0:a40b9a259b52 1994 *
Osamu Nakamura 0:a40b9a259b52 1995 * @api private
Osamu Nakamura 0:a40b9a259b52 1996 */
Osamu Nakamura 0:a40b9a259b52 1997
Osamu Nakamura 0:a40b9a259b52 1998 Socket.prototype.onHeartbeat = function (timeout) {
Osamu Nakamura 0:a40b9a259b52 1999 clearTimeout(this.pingTimeoutTimer);
Osamu Nakamura 0:a40b9a259b52 2000 var self = this;
Osamu Nakamura 0:a40b9a259b52 2001 self.pingTimeoutTimer = setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 2002 if ('closed' == self.readyState) return;
Osamu Nakamura 0:a40b9a259b52 2003 self.onClose('ping timeout');
Osamu Nakamura 0:a40b9a259b52 2004 }, timeout || (self.pingInterval + self.pingTimeout));
Osamu Nakamura 0:a40b9a259b52 2005 };
Osamu Nakamura 0:a40b9a259b52 2006
Osamu Nakamura 0:a40b9a259b52 2007 /**
Osamu Nakamura 0:a40b9a259b52 2008 * Pings server every `this.pingInterval` and expects response
Osamu Nakamura 0:a40b9a259b52 2009 * within `this.pingTimeout` or closes connection.
Osamu Nakamura 0:a40b9a259b52 2010 *
Osamu Nakamura 0:a40b9a259b52 2011 * @api private
Osamu Nakamura 0:a40b9a259b52 2012 */
Osamu Nakamura 0:a40b9a259b52 2013
Osamu Nakamura 0:a40b9a259b52 2014 Socket.prototype.setPing = function () {
Osamu Nakamura 0:a40b9a259b52 2015 var self = this;
Osamu Nakamura 0:a40b9a259b52 2016 clearTimeout(self.pingIntervalTimer);
Osamu Nakamura 0:a40b9a259b52 2017 self.pingIntervalTimer = setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 2018 debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
Osamu Nakamura 0:a40b9a259b52 2019 self.ping();
Osamu Nakamura 0:a40b9a259b52 2020 self.onHeartbeat(self.pingTimeout);
Osamu Nakamura 0:a40b9a259b52 2021 }, self.pingInterval);
Osamu Nakamura 0:a40b9a259b52 2022 };
Osamu Nakamura 0:a40b9a259b52 2023
Osamu Nakamura 0:a40b9a259b52 2024 /**
Osamu Nakamura 0:a40b9a259b52 2025 * Sends a ping packet.
Osamu Nakamura 0:a40b9a259b52 2026 *
Osamu Nakamura 0:a40b9a259b52 2027 * @api public
Osamu Nakamura 0:a40b9a259b52 2028 */
Osamu Nakamura 0:a40b9a259b52 2029
Osamu Nakamura 0:a40b9a259b52 2030 Socket.prototype.ping = function () {
Osamu Nakamura 0:a40b9a259b52 2031 this.sendPacket('ping');
Osamu Nakamura 0:a40b9a259b52 2032 };
Osamu Nakamura 0:a40b9a259b52 2033
Osamu Nakamura 0:a40b9a259b52 2034 /**
Osamu Nakamura 0:a40b9a259b52 2035 * Called on `drain` event
Osamu Nakamura 0:a40b9a259b52 2036 *
Osamu Nakamura 0:a40b9a259b52 2037 * @api private
Osamu Nakamura 0:a40b9a259b52 2038 */
Osamu Nakamura 0:a40b9a259b52 2039
Osamu Nakamura 0:a40b9a259b52 2040 Socket.prototype.onDrain = function() {
Osamu Nakamura 0:a40b9a259b52 2041 for (var i = 0; i < this.prevBufferLen; i++) {
Osamu Nakamura 0:a40b9a259b52 2042 if (this.callbackBuffer[i]) {
Osamu Nakamura 0:a40b9a259b52 2043 this.callbackBuffer[i]();
Osamu Nakamura 0:a40b9a259b52 2044 }
Osamu Nakamura 0:a40b9a259b52 2045 }
Osamu Nakamura 0:a40b9a259b52 2046
Osamu Nakamura 0:a40b9a259b52 2047 this.writeBuffer.splice(0, this.prevBufferLen);
Osamu Nakamura 0:a40b9a259b52 2048 this.callbackBuffer.splice(0, this.prevBufferLen);
Osamu Nakamura 0:a40b9a259b52 2049
Osamu Nakamura 0:a40b9a259b52 2050 // setting prevBufferLen = 0 is very important
Osamu Nakamura 0:a40b9a259b52 2051 // for example, when upgrading, upgrade packet is sent over,
Osamu Nakamura 0:a40b9a259b52 2052 // and a nonzero prevBufferLen could cause problems on `drain`
Osamu Nakamura 0:a40b9a259b52 2053 this.prevBufferLen = 0;
Osamu Nakamura 0:a40b9a259b52 2054
Osamu Nakamura 0:a40b9a259b52 2055 if (this.writeBuffer.length == 0) {
Osamu Nakamura 0:a40b9a259b52 2056 this.emit('drain');
Osamu Nakamura 0:a40b9a259b52 2057 } else {
Osamu Nakamura 0:a40b9a259b52 2058 this.flush();
Osamu Nakamura 0:a40b9a259b52 2059 }
Osamu Nakamura 0:a40b9a259b52 2060 };
Osamu Nakamura 0:a40b9a259b52 2061
Osamu Nakamura 0:a40b9a259b52 2062 /**
Osamu Nakamura 0:a40b9a259b52 2063 * Flush write buffers.
Osamu Nakamura 0:a40b9a259b52 2064 *
Osamu Nakamura 0:a40b9a259b52 2065 * @api private
Osamu Nakamura 0:a40b9a259b52 2066 */
Osamu Nakamura 0:a40b9a259b52 2067
Osamu Nakamura 0:a40b9a259b52 2068 Socket.prototype.flush = function () {
Osamu Nakamura 0:a40b9a259b52 2069 if ('closed' != this.readyState && this.transport.writable &&
Osamu Nakamura 0:a40b9a259b52 2070 !this.upgrading && this.writeBuffer.length) {
Osamu Nakamura 0:a40b9a259b52 2071 debug('flushing %d packets in socket', this.writeBuffer.length);
Osamu Nakamura 0:a40b9a259b52 2072 this.transport.send(this.writeBuffer);
Osamu Nakamura 0:a40b9a259b52 2073 // keep track of current length of writeBuffer
Osamu Nakamura 0:a40b9a259b52 2074 // splice writeBuffer and callbackBuffer on `drain`
Osamu Nakamura 0:a40b9a259b52 2075 this.prevBufferLen = this.writeBuffer.length;
Osamu Nakamura 0:a40b9a259b52 2076 this.emit('flush');
Osamu Nakamura 0:a40b9a259b52 2077 }
Osamu Nakamura 0:a40b9a259b52 2078 };
Osamu Nakamura 0:a40b9a259b52 2079
Osamu Nakamura 0:a40b9a259b52 2080 /**
Osamu Nakamura 0:a40b9a259b52 2081 * Sends a message.
Osamu Nakamura 0:a40b9a259b52 2082 *
Osamu Nakamura 0:a40b9a259b52 2083 * @param {String} message.
Osamu Nakamura 0:a40b9a259b52 2084 * @param {Function} callback function.
Osamu Nakamura 0:a40b9a259b52 2085 * @return {Socket} for chaining.
Osamu Nakamura 0:a40b9a259b52 2086 * @api public
Osamu Nakamura 0:a40b9a259b52 2087 */
Osamu Nakamura 0:a40b9a259b52 2088
Osamu Nakamura 0:a40b9a259b52 2089 Socket.prototype.write =
Osamu Nakamura 0:a40b9a259b52 2090 Socket.prototype.send = function (msg, fn) {
Osamu Nakamura 0:a40b9a259b52 2091 this.sendPacket('message', msg, fn);
Osamu Nakamura 0:a40b9a259b52 2092 return this;
Osamu Nakamura 0:a40b9a259b52 2093 };
Osamu Nakamura 0:a40b9a259b52 2094
Osamu Nakamura 0:a40b9a259b52 2095 /**
Osamu Nakamura 0:a40b9a259b52 2096 * Sends a packet.
Osamu Nakamura 0:a40b9a259b52 2097 *
Osamu Nakamura 0:a40b9a259b52 2098 * @param {String} packet type.
Osamu Nakamura 0:a40b9a259b52 2099 * @param {String} data.
Osamu Nakamura 0:a40b9a259b52 2100 * @param {Function} callback function.
Osamu Nakamura 0:a40b9a259b52 2101 * @api private
Osamu Nakamura 0:a40b9a259b52 2102 */
Osamu Nakamura 0:a40b9a259b52 2103
Osamu Nakamura 0:a40b9a259b52 2104 Socket.prototype.sendPacket = function (type, data, fn) {
Osamu Nakamura 0:a40b9a259b52 2105 if ('closing' == this.readyState || 'closed' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2106 return;
Osamu Nakamura 0:a40b9a259b52 2107 }
Osamu Nakamura 0:a40b9a259b52 2108
Osamu Nakamura 0:a40b9a259b52 2109 var packet = { type: type, data: data };
Osamu Nakamura 0:a40b9a259b52 2110 this.emit('packetCreate', packet);
Osamu Nakamura 0:a40b9a259b52 2111 this.writeBuffer.push(packet);
Osamu Nakamura 0:a40b9a259b52 2112 this.callbackBuffer.push(fn);
Osamu Nakamura 0:a40b9a259b52 2113 this.flush();
Osamu Nakamura 0:a40b9a259b52 2114 };
Osamu Nakamura 0:a40b9a259b52 2115
Osamu Nakamura 0:a40b9a259b52 2116 /**
Osamu Nakamura 0:a40b9a259b52 2117 * Closes the connection.
Osamu Nakamura 0:a40b9a259b52 2118 *
Osamu Nakamura 0:a40b9a259b52 2119 * @api private
Osamu Nakamura 0:a40b9a259b52 2120 */
Osamu Nakamura 0:a40b9a259b52 2121
Osamu Nakamura 0:a40b9a259b52 2122 Socket.prototype.close = function () {
Osamu Nakamura 0:a40b9a259b52 2123 if ('opening' == this.readyState || 'open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2124 this.readyState = 'closing';
Osamu Nakamura 0:a40b9a259b52 2125
Osamu Nakamura 0:a40b9a259b52 2126 var self = this;
Osamu Nakamura 0:a40b9a259b52 2127
Osamu Nakamura 0:a40b9a259b52 2128 function close() {
Osamu Nakamura 0:a40b9a259b52 2129 self.onClose('forced close');
Osamu Nakamura 0:a40b9a259b52 2130 debug('socket closing - telling transport to close');
Osamu Nakamura 0:a40b9a259b52 2131 self.transport.close();
Osamu Nakamura 0:a40b9a259b52 2132 }
Osamu Nakamura 0:a40b9a259b52 2133
Osamu Nakamura 0:a40b9a259b52 2134 function cleanupAndClose() {
Osamu Nakamura 0:a40b9a259b52 2135 self.removeListener('upgrade', cleanupAndClose);
Osamu Nakamura 0:a40b9a259b52 2136 self.removeListener('upgradeError', cleanupAndClose);
Osamu Nakamura 0:a40b9a259b52 2137 close();
Osamu Nakamura 0:a40b9a259b52 2138 }
Osamu Nakamura 0:a40b9a259b52 2139
Osamu Nakamura 0:a40b9a259b52 2140 function waitForUpgrade() {
Osamu Nakamura 0:a40b9a259b52 2141 // wait for upgrade to finish since we can't send packets while pausing a transport
Osamu Nakamura 0:a40b9a259b52 2142 self.once('upgrade', cleanupAndClose);
Osamu Nakamura 0:a40b9a259b52 2143 self.once('upgradeError', cleanupAndClose);
Osamu Nakamura 0:a40b9a259b52 2144 }
Osamu Nakamura 0:a40b9a259b52 2145
Osamu Nakamura 0:a40b9a259b52 2146 if (this.writeBuffer.length) {
Osamu Nakamura 0:a40b9a259b52 2147 this.once('drain', function() {
Osamu Nakamura 0:a40b9a259b52 2148 if (this.upgrading) {
Osamu Nakamura 0:a40b9a259b52 2149 waitForUpgrade();
Osamu Nakamura 0:a40b9a259b52 2150 } else {
Osamu Nakamura 0:a40b9a259b52 2151 close();
Osamu Nakamura 0:a40b9a259b52 2152 }
Osamu Nakamura 0:a40b9a259b52 2153 });
Osamu Nakamura 0:a40b9a259b52 2154 } else if (this.upgrading) {
Osamu Nakamura 0:a40b9a259b52 2155 waitForUpgrade();
Osamu Nakamura 0:a40b9a259b52 2156 } else {
Osamu Nakamura 0:a40b9a259b52 2157 close();
Osamu Nakamura 0:a40b9a259b52 2158 }
Osamu Nakamura 0:a40b9a259b52 2159 }
Osamu Nakamura 0:a40b9a259b52 2160
Osamu Nakamura 0:a40b9a259b52 2161 return this;
Osamu Nakamura 0:a40b9a259b52 2162 };
Osamu Nakamura 0:a40b9a259b52 2163
Osamu Nakamura 0:a40b9a259b52 2164 /**
Osamu Nakamura 0:a40b9a259b52 2165 * Called upon transport error
Osamu Nakamura 0:a40b9a259b52 2166 *
Osamu Nakamura 0:a40b9a259b52 2167 * @api private
Osamu Nakamura 0:a40b9a259b52 2168 */
Osamu Nakamura 0:a40b9a259b52 2169
Osamu Nakamura 0:a40b9a259b52 2170 Socket.prototype.onError = function (err) {
Osamu Nakamura 0:a40b9a259b52 2171 debug('socket error %j', err);
Osamu Nakamura 0:a40b9a259b52 2172 Socket.priorWebsocketSuccess = false;
Osamu Nakamura 0:a40b9a259b52 2173 this.emit('error', err);
Osamu Nakamura 0:a40b9a259b52 2174 this.onClose('transport error', err);
Osamu Nakamura 0:a40b9a259b52 2175 };
Osamu Nakamura 0:a40b9a259b52 2176
Osamu Nakamura 0:a40b9a259b52 2177 /**
Osamu Nakamura 0:a40b9a259b52 2178 * Called upon transport close.
Osamu Nakamura 0:a40b9a259b52 2179 *
Osamu Nakamura 0:a40b9a259b52 2180 * @api private
Osamu Nakamura 0:a40b9a259b52 2181 */
Osamu Nakamura 0:a40b9a259b52 2182
Osamu Nakamura 0:a40b9a259b52 2183 Socket.prototype.onClose = function (reason, desc) {
Osamu Nakamura 0:a40b9a259b52 2184 if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2185 debug('socket close with reason: "%s"', reason);
Osamu Nakamura 0:a40b9a259b52 2186 var self = this;
Osamu Nakamura 0:a40b9a259b52 2187
Osamu Nakamura 0:a40b9a259b52 2188 // clear timers
Osamu Nakamura 0:a40b9a259b52 2189 clearTimeout(this.pingIntervalTimer);
Osamu Nakamura 0:a40b9a259b52 2190 clearTimeout(this.pingTimeoutTimer);
Osamu Nakamura 0:a40b9a259b52 2191
Osamu Nakamura 0:a40b9a259b52 2192 // clean buffers in next tick, so developers can still
Osamu Nakamura 0:a40b9a259b52 2193 // grab the buffers on `close` event
Osamu Nakamura 0:a40b9a259b52 2194 setTimeout(function() {
Osamu Nakamura 0:a40b9a259b52 2195 self.writeBuffer = [];
Osamu Nakamura 0:a40b9a259b52 2196 self.callbackBuffer = [];
Osamu Nakamura 0:a40b9a259b52 2197 self.prevBufferLen = 0;
Osamu Nakamura 0:a40b9a259b52 2198 }, 0);
Osamu Nakamura 0:a40b9a259b52 2199
Osamu Nakamura 0:a40b9a259b52 2200 // stop event from firing again for transport
Osamu Nakamura 0:a40b9a259b52 2201 this.transport.removeAllListeners('close');
Osamu Nakamura 0:a40b9a259b52 2202
Osamu Nakamura 0:a40b9a259b52 2203 // ensure transport won't stay open
Osamu Nakamura 0:a40b9a259b52 2204 this.transport.close();
Osamu Nakamura 0:a40b9a259b52 2205
Osamu Nakamura 0:a40b9a259b52 2206 // ignore further transport communication
Osamu Nakamura 0:a40b9a259b52 2207 this.transport.removeAllListeners();
Osamu Nakamura 0:a40b9a259b52 2208
Osamu Nakamura 0:a40b9a259b52 2209 // set ready state
Osamu Nakamura 0:a40b9a259b52 2210 this.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 2211
Osamu Nakamura 0:a40b9a259b52 2212 // clear session id
Osamu Nakamura 0:a40b9a259b52 2213 this.id = null;
Osamu Nakamura 0:a40b9a259b52 2214
Osamu Nakamura 0:a40b9a259b52 2215 // emit close event
Osamu Nakamura 0:a40b9a259b52 2216 this.emit('close', reason, desc);
Osamu Nakamura 0:a40b9a259b52 2217 }
Osamu Nakamura 0:a40b9a259b52 2218 };
Osamu Nakamura 0:a40b9a259b52 2219
Osamu Nakamura 0:a40b9a259b52 2220 /**
Osamu Nakamura 0:a40b9a259b52 2221 * Filters upgrades, returning only those matching client transports.
Osamu Nakamura 0:a40b9a259b52 2222 *
Osamu Nakamura 0:a40b9a259b52 2223 * @param {Array} server upgrades
Osamu Nakamura 0:a40b9a259b52 2224 * @api private
Osamu Nakamura 0:a40b9a259b52 2225 *
Osamu Nakamura 0:a40b9a259b52 2226 */
Osamu Nakamura 0:a40b9a259b52 2227
Osamu Nakamura 0:a40b9a259b52 2228 Socket.prototype.filterUpgrades = function (upgrades) {
Osamu Nakamura 0:a40b9a259b52 2229 var filteredUpgrades = [];
Osamu Nakamura 0:a40b9a259b52 2230 for (var i = 0, j = upgrades.length; i<j; i++) {
Osamu Nakamura 0:a40b9a259b52 2231 if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
Osamu Nakamura 0:a40b9a259b52 2232 }
Osamu Nakamura 0:a40b9a259b52 2233 return filteredUpgrades;
Osamu Nakamura 0:a40b9a259b52 2234 };
Osamu Nakamura 0:a40b9a259b52 2235
Osamu Nakamura 0:a40b9a259b52 2236 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 2237 },{"./transport":14,"./transports":15,"component-emitter":9,"debug":22,"engine.io-parser":25,"indexof":42,"parsejson":34,"parseqs":35,"parseuri":36}],14:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 2238 /**
Osamu Nakamura 0:a40b9a259b52 2239 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 2240 */
Osamu Nakamura 0:a40b9a259b52 2241
Osamu Nakamura 0:a40b9a259b52 2242 var parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 2243 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 2244
Osamu Nakamura 0:a40b9a259b52 2245 /**
Osamu Nakamura 0:a40b9a259b52 2246 * Module exports.
Osamu Nakamura 0:a40b9a259b52 2247 */
Osamu Nakamura 0:a40b9a259b52 2248
Osamu Nakamura 0:a40b9a259b52 2249 module.exports = Transport;
Osamu Nakamura 0:a40b9a259b52 2250
Osamu Nakamura 0:a40b9a259b52 2251 /**
Osamu Nakamura 0:a40b9a259b52 2252 * Transport abstract constructor.
Osamu Nakamura 0:a40b9a259b52 2253 *
Osamu Nakamura 0:a40b9a259b52 2254 * @param {Object} options.
Osamu Nakamura 0:a40b9a259b52 2255 * @api private
Osamu Nakamura 0:a40b9a259b52 2256 */
Osamu Nakamura 0:a40b9a259b52 2257
Osamu Nakamura 0:a40b9a259b52 2258 function Transport (opts) {
Osamu Nakamura 0:a40b9a259b52 2259 this.path = opts.path;
Osamu Nakamura 0:a40b9a259b52 2260 this.hostname = opts.hostname;
Osamu Nakamura 0:a40b9a259b52 2261 this.port = opts.port;
Osamu Nakamura 0:a40b9a259b52 2262 this.secure = opts.secure;
Osamu Nakamura 0:a40b9a259b52 2263 this.query = opts.query;
Osamu Nakamura 0:a40b9a259b52 2264 this.timestampParam = opts.timestampParam;
Osamu Nakamura 0:a40b9a259b52 2265 this.timestampRequests = opts.timestampRequests;
Osamu Nakamura 0:a40b9a259b52 2266 this.readyState = '';
Osamu Nakamura 0:a40b9a259b52 2267 this.agent = opts.agent || false;
Osamu Nakamura 0:a40b9a259b52 2268 this.socket = opts.socket;
Osamu Nakamura 0:a40b9a259b52 2269 this.enablesXDR = opts.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 2270
Osamu Nakamura 0:a40b9a259b52 2271 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 2272 this.pfx = opts.pfx;
Osamu Nakamura 0:a40b9a259b52 2273 this.key = opts.key;
Osamu Nakamura 0:a40b9a259b52 2274 this.passphrase = opts.passphrase;
Osamu Nakamura 0:a40b9a259b52 2275 this.cert = opts.cert;
Osamu Nakamura 0:a40b9a259b52 2276 this.ca = opts.ca;
Osamu Nakamura 0:a40b9a259b52 2277 this.ciphers = opts.ciphers;
Osamu Nakamura 0:a40b9a259b52 2278 this.rejectUnauthorized = opts.rejectUnauthorized;
Osamu Nakamura 0:a40b9a259b52 2279 }
Osamu Nakamura 0:a40b9a259b52 2280
Osamu Nakamura 0:a40b9a259b52 2281 /**
Osamu Nakamura 0:a40b9a259b52 2282 * Mix in `Emitter`.
Osamu Nakamura 0:a40b9a259b52 2283 */
Osamu Nakamura 0:a40b9a259b52 2284
Osamu Nakamura 0:a40b9a259b52 2285 Emitter(Transport.prototype);
Osamu Nakamura 0:a40b9a259b52 2286
Osamu Nakamura 0:a40b9a259b52 2287 /**
Osamu Nakamura 0:a40b9a259b52 2288 * A counter used to prevent collisions in the timestamps used
Osamu Nakamura 0:a40b9a259b52 2289 * for cache busting.
Osamu Nakamura 0:a40b9a259b52 2290 */
Osamu Nakamura 0:a40b9a259b52 2291
Osamu Nakamura 0:a40b9a259b52 2292 Transport.timestamps = 0;
Osamu Nakamura 0:a40b9a259b52 2293
Osamu Nakamura 0:a40b9a259b52 2294 /**
Osamu Nakamura 0:a40b9a259b52 2295 * Emits an error.
Osamu Nakamura 0:a40b9a259b52 2296 *
Osamu Nakamura 0:a40b9a259b52 2297 * @param {String} str
Osamu Nakamura 0:a40b9a259b52 2298 * @return {Transport} for chaining
Osamu Nakamura 0:a40b9a259b52 2299 * @api public
Osamu Nakamura 0:a40b9a259b52 2300 */
Osamu Nakamura 0:a40b9a259b52 2301
Osamu Nakamura 0:a40b9a259b52 2302 Transport.prototype.onError = function (msg, desc) {
Osamu Nakamura 0:a40b9a259b52 2303 var err = new Error(msg);
Osamu Nakamura 0:a40b9a259b52 2304 err.type = 'TransportError';
Osamu Nakamura 0:a40b9a259b52 2305 err.description = desc;
Osamu Nakamura 0:a40b9a259b52 2306 this.emit('error', err);
Osamu Nakamura 0:a40b9a259b52 2307 return this;
Osamu Nakamura 0:a40b9a259b52 2308 };
Osamu Nakamura 0:a40b9a259b52 2309
Osamu Nakamura 0:a40b9a259b52 2310 /**
Osamu Nakamura 0:a40b9a259b52 2311 * Opens the transport.
Osamu Nakamura 0:a40b9a259b52 2312 *
Osamu Nakamura 0:a40b9a259b52 2313 * @api public
Osamu Nakamura 0:a40b9a259b52 2314 */
Osamu Nakamura 0:a40b9a259b52 2315
Osamu Nakamura 0:a40b9a259b52 2316 Transport.prototype.open = function () {
Osamu Nakamura 0:a40b9a259b52 2317 if ('closed' == this.readyState || '' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2318 this.readyState = 'opening';
Osamu Nakamura 0:a40b9a259b52 2319 this.doOpen();
Osamu Nakamura 0:a40b9a259b52 2320 }
Osamu Nakamura 0:a40b9a259b52 2321
Osamu Nakamura 0:a40b9a259b52 2322 return this;
Osamu Nakamura 0:a40b9a259b52 2323 };
Osamu Nakamura 0:a40b9a259b52 2324
Osamu Nakamura 0:a40b9a259b52 2325 /**
Osamu Nakamura 0:a40b9a259b52 2326 * Closes the transport.
Osamu Nakamura 0:a40b9a259b52 2327 *
Osamu Nakamura 0:a40b9a259b52 2328 * @api private
Osamu Nakamura 0:a40b9a259b52 2329 */
Osamu Nakamura 0:a40b9a259b52 2330
Osamu Nakamura 0:a40b9a259b52 2331 Transport.prototype.close = function () {
Osamu Nakamura 0:a40b9a259b52 2332 if ('opening' == this.readyState || 'open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2333 this.doClose();
Osamu Nakamura 0:a40b9a259b52 2334 this.onClose();
Osamu Nakamura 0:a40b9a259b52 2335 }
Osamu Nakamura 0:a40b9a259b52 2336
Osamu Nakamura 0:a40b9a259b52 2337 return this;
Osamu Nakamura 0:a40b9a259b52 2338 };
Osamu Nakamura 0:a40b9a259b52 2339
Osamu Nakamura 0:a40b9a259b52 2340 /**
Osamu Nakamura 0:a40b9a259b52 2341 * Sends multiple packets.
Osamu Nakamura 0:a40b9a259b52 2342 *
Osamu Nakamura 0:a40b9a259b52 2343 * @param {Array} packets
Osamu Nakamura 0:a40b9a259b52 2344 * @api private
Osamu Nakamura 0:a40b9a259b52 2345 */
Osamu Nakamura 0:a40b9a259b52 2346
Osamu Nakamura 0:a40b9a259b52 2347 Transport.prototype.send = function(packets){
Osamu Nakamura 0:a40b9a259b52 2348 if ('open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 2349 this.write(packets);
Osamu Nakamura 0:a40b9a259b52 2350 } else {
Osamu Nakamura 0:a40b9a259b52 2351 throw new Error('Transport not open');
Osamu Nakamura 0:a40b9a259b52 2352 }
Osamu Nakamura 0:a40b9a259b52 2353 };
Osamu Nakamura 0:a40b9a259b52 2354
Osamu Nakamura 0:a40b9a259b52 2355 /**
Osamu Nakamura 0:a40b9a259b52 2356 * Called upon open
Osamu Nakamura 0:a40b9a259b52 2357 *
Osamu Nakamura 0:a40b9a259b52 2358 * @api private
Osamu Nakamura 0:a40b9a259b52 2359 */
Osamu Nakamura 0:a40b9a259b52 2360
Osamu Nakamura 0:a40b9a259b52 2361 Transport.prototype.onOpen = function () {
Osamu Nakamura 0:a40b9a259b52 2362 this.readyState = 'open';
Osamu Nakamura 0:a40b9a259b52 2363 this.writable = true;
Osamu Nakamura 0:a40b9a259b52 2364 this.emit('open');
Osamu Nakamura 0:a40b9a259b52 2365 };
Osamu Nakamura 0:a40b9a259b52 2366
Osamu Nakamura 0:a40b9a259b52 2367 /**
Osamu Nakamura 0:a40b9a259b52 2368 * Called with data.
Osamu Nakamura 0:a40b9a259b52 2369 *
Osamu Nakamura 0:a40b9a259b52 2370 * @param {String} data
Osamu Nakamura 0:a40b9a259b52 2371 * @api private
Osamu Nakamura 0:a40b9a259b52 2372 */
Osamu Nakamura 0:a40b9a259b52 2373
Osamu Nakamura 0:a40b9a259b52 2374 Transport.prototype.onData = function(data){
Osamu Nakamura 0:a40b9a259b52 2375 var packet = parser.decodePacket(data, this.socket.binaryType);
Osamu Nakamura 0:a40b9a259b52 2376 this.onPacket(packet);
Osamu Nakamura 0:a40b9a259b52 2377 };
Osamu Nakamura 0:a40b9a259b52 2378
Osamu Nakamura 0:a40b9a259b52 2379 /**
Osamu Nakamura 0:a40b9a259b52 2380 * Called with a decoded packet.
Osamu Nakamura 0:a40b9a259b52 2381 */
Osamu Nakamura 0:a40b9a259b52 2382
Osamu Nakamura 0:a40b9a259b52 2383 Transport.prototype.onPacket = function (packet) {
Osamu Nakamura 0:a40b9a259b52 2384 this.emit('packet', packet);
Osamu Nakamura 0:a40b9a259b52 2385 };
Osamu Nakamura 0:a40b9a259b52 2386
Osamu Nakamura 0:a40b9a259b52 2387 /**
Osamu Nakamura 0:a40b9a259b52 2388 * Called upon close.
Osamu Nakamura 0:a40b9a259b52 2389 *
Osamu Nakamura 0:a40b9a259b52 2390 * @api private
Osamu Nakamura 0:a40b9a259b52 2391 */
Osamu Nakamura 0:a40b9a259b52 2392
Osamu Nakamura 0:a40b9a259b52 2393 Transport.prototype.onClose = function () {
Osamu Nakamura 0:a40b9a259b52 2394 this.readyState = 'closed';
Osamu Nakamura 0:a40b9a259b52 2395 this.emit('close');
Osamu Nakamura 0:a40b9a259b52 2396 };
Osamu Nakamura 0:a40b9a259b52 2397
Osamu Nakamura 0:a40b9a259b52 2398 },{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 2399 (function (global){
Osamu Nakamura 0:a40b9a259b52 2400 /**
Osamu Nakamura 0:a40b9a259b52 2401 * Module dependencies
Osamu Nakamura 0:a40b9a259b52 2402 */
Osamu Nakamura 0:a40b9a259b52 2403
Osamu Nakamura 0:a40b9a259b52 2404 var XMLHttpRequest = _dereq_('xmlhttprequest');
Osamu Nakamura 0:a40b9a259b52 2405 var XHR = _dereq_('./polling-xhr');
Osamu Nakamura 0:a40b9a259b52 2406 var JSONP = _dereq_('./polling-jsonp');
Osamu Nakamura 0:a40b9a259b52 2407 var websocket = _dereq_('./websocket');
Osamu Nakamura 0:a40b9a259b52 2408
Osamu Nakamura 0:a40b9a259b52 2409 /**
Osamu Nakamura 0:a40b9a259b52 2410 * Export transports.
Osamu Nakamura 0:a40b9a259b52 2411 */
Osamu Nakamura 0:a40b9a259b52 2412
Osamu Nakamura 0:a40b9a259b52 2413 exports.polling = polling;
Osamu Nakamura 0:a40b9a259b52 2414 exports.websocket = websocket;
Osamu Nakamura 0:a40b9a259b52 2415
Osamu Nakamura 0:a40b9a259b52 2416 /**
Osamu Nakamura 0:a40b9a259b52 2417 * Polling transport polymorphic constructor.
Osamu Nakamura 0:a40b9a259b52 2418 * Decides on xhr vs jsonp based on feature detection.
Osamu Nakamura 0:a40b9a259b52 2419 *
Osamu Nakamura 0:a40b9a259b52 2420 * @api private
Osamu Nakamura 0:a40b9a259b52 2421 */
Osamu Nakamura 0:a40b9a259b52 2422
Osamu Nakamura 0:a40b9a259b52 2423 function polling(opts){
Osamu Nakamura 0:a40b9a259b52 2424 var xhr;
Osamu Nakamura 0:a40b9a259b52 2425 var xd = false;
Osamu Nakamura 0:a40b9a259b52 2426 var xs = false;
Osamu Nakamura 0:a40b9a259b52 2427 var jsonp = false !== opts.jsonp;
Osamu Nakamura 0:a40b9a259b52 2428
Osamu Nakamura 0:a40b9a259b52 2429 if (global.location) {
Osamu Nakamura 0:a40b9a259b52 2430 var isSSL = 'https:' == location.protocol;
Osamu Nakamura 0:a40b9a259b52 2431 var port = location.port;
Osamu Nakamura 0:a40b9a259b52 2432
Osamu Nakamura 0:a40b9a259b52 2433 // some user agents have empty `location.port`
Osamu Nakamura 0:a40b9a259b52 2434 if (!port) {
Osamu Nakamura 0:a40b9a259b52 2435 port = isSSL ? 443 : 80;
Osamu Nakamura 0:a40b9a259b52 2436 }
Osamu Nakamura 0:a40b9a259b52 2437
Osamu Nakamura 0:a40b9a259b52 2438 xd = opts.hostname != location.hostname || port != opts.port;
Osamu Nakamura 0:a40b9a259b52 2439 xs = opts.secure != isSSL;
Osamu Nakamura 0:a40b9a259b52 2440 }
Osamu Nakamura 0:a40b9a259b52 2441
Osamu Nakamura 0:a40b9a259b52 2442 opts.xdomain = xd;
Osamu Nakamura 0:a40b9a259b52 2443 opts.xscheme = xs;
Osamu Nakamura 0:a40b9a259b52 2444 xhr = new XMLHttpRequest(opts);
Osamu Nakamura 0:a40b9a259b52 2445
Osamu Nakamura 0:a40b9a259b52 2446 if ('open' in xhr && !opts.forceJSONP) {
Osamu Nakamura 0:a40b9a259b52 2447 return new XHR(opts);
Osamu Nakamura 0:a40b9a259b52 2448 } else {
Osamu Nakamura 0:a40b9a259b52 2449 if (!jsonp) throw new Error('JSONP disabled');
Osamu Nakamura 0:a40b9a259b52 2450 return new JSONP(opts);
Osamu Nakamura 0:a40b9a259b52 2451 }
Osamu Nakamura 0:a40b9a259b52 2452 }
Osamu Nakamura 0:a40b9a259b52 2453
Osamu Nakamura 0:a40b9a259b52 2454 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 2455 },{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 2456 (function (global){
Osamu Nakamura 0:a40b9a259b52 2457
Osamu Nakamura 0:a40b9a259b52 2458 /**
Osamu Nakamura 0:a40b9a259b52 2459 * Module requirements.
Osamu Nakamura 0:a40b9a259b52 2460 */
Osamu Nakamura 0:a40b9a259b52 2461
Osamu Nakamura 0:a40b9a259b52 2462 var Polling = _dereq_('./polling');
Osamu Nakamura 0:a40b9a259b52 2463 var inherit = _dereq_('component-inherit');
Osamu Nakamura 0:a40b9a259b52 2464
Osamu Nakamura 0:a40b9a259b52 2465 /**
Osamu Nakamura 0:a40b9a259b52 2466 * Module exports.
Osamu Nakamura 0:a40b9a259b52 2467 */
Osamu Nakamura 0:a40b9a259b52 2468
Osamu Nakamura 0:a40b9a259b52 2469 module.exports = JSONPPolling;
Osamu Nakamura 0:a40b9a259b52 2470
Osamu Nakamura 0:a40b9a259b52 2471 /**
Osamu Nakamura 0:a40b9a259b52 2472 * Cached regular expressions.
Osamu Nakamura 0:a40b9a259b52 2473 */
Osamu Nakamura 0:a40b9a259b52 2474
Osamu Nakamura 0:a40b9a259b52 2475 var rNewline = /\n/g;
Osamu Nakamura 0:a40b9a259b52 2476 var rEscapedNewline = /\\n/g;
Osamu Nakamura 0:a40b9a259b52 2477
Osamu Nakamura 0:a40b9a259b52 2478 /**
Osamu Nakamura 0:a40b9a259b52 2479 * Global JSONP callbacks.
Osamu Nakamura 0:a40b9a259b52 2480 */
Osamu Nakamura 0:a40b9a259b52 2481
Osamu Nakamura 0:a40b9a259b52 2482 var callbacks;
Osamu Nakamura 0:a40b9a259b52 2483
Osamu Nakamura 0:a40b9a259b52 2484 /**
Osamu Nakamura 0:a40b9a259b52 2485 * Callbacks count.
Osamu Nakamura 0:a40b9a259b52 2486 */
Osamu Nakamura 0:a40b9a259b52 2487
Osamu Nakamura 0:a40b9a259b52 2488 var index = 0;
Osamu Nakamura 0:a40b9a259b52 2489
Osamu Nakamura 0:a40b9a259b52 2490 /**
Osamu Nakamura 0:a40b9a259b52 2491 * Noop.
Osamu Nakamura 0:a40b9a259b52 2492 */
Osamu Nakamura 0:a40b9a259b52 2493
Osamu Nakamura 0:a40b9a259b52 2494 function empty () { }
Osamu Nakamura 0:a40b9a259b52 2495
Osamu Nakamura 0:a40b9a259b52 2496 /**
Osamu Nakamura 0:a40b9a259b52 2497 * JSONP Polling constructor.
Osamu Nakamura 0:a40b9a259b52 2498 *
Osamu Nakamura 0:a40b9a259b52 2499 * @param {Object} opts.
Osamu Nakamura 0:a40b9a259b52 2500 * @api public
Osamu Nakamura 0:a40b9a259b52 2501 */
Osamu Nakamura 0:a40b9a259b52 2502
Osamu Nakamura 0:a40b9a259b52 2503 function JSONPPolling (opts) {
Osamu Nakamura 0:a40b9a259b52 2504 Polling.call(this, opts);
Osamu Nakamura 0:a40b9a259b52 2505
Osamu Nakamura 0:a40b9a259b52 2506 this.query = this.query || {};
Osamu Nakamura 0:a40b9a259b52 2507
Osamu Nakamura 0:a40b9a259b52 2508 // define global callbacks array if not present
Osamu Nakamura 0:a40b9a259b52 2509 // we do this here (lazily) to avoid unneeded global pollution
Osamu Nakamura 0:a40b9a259b52 2510 if (!callbacks) {
Osamu Nakamura 0:a40b9a259b52 2511 // we need to consider multiple engines in the same page
Osamu Nakamura 0:a40b9a259b52 2512 if (!global.___eio) global.___eio = [];
Osamu Nakamura 0:a40b9a259b52 2513 callbacks = global.___eio;
Osamu Nakamura 0:a40b9a259b52 2514 }
Osamu Nakamura 0:a40b9a259b52 2515
Osamu Nakamura 0:a40b9a259b52 2516 // callback identifier
Osamu Nakamura 0:a40b9a259b52 2517 this.index = callbacks.length;
Osamu Nakamura 0:a40b9a259b52 2518
Osamu Nakamura 0:a40b9a259b52 2519 // add callback to jsonp global
Osamu Nakamura 0:a40b9a259b52 2520 var self = this;
Osamu Nakamura 0:a40b9a259b52 2521 callbacks.push(function (msg) {
Osamu Nakamura 0:a40b9a259b52 2522 self.onData(msg);
Osamu Nakamura 0:a40b9a259b52 2523 });
Osamu Nakamura 0:a40b9a259b52 2524
Osamu Nakamura 0:a40b9a259b52 2525 // append to query string
Osamu Nakamura 0:a40b9a259b52 2526 this.query.j = this.index;
Osamu Nakamura 0:a40b9a259b52 2527
Osamu Nakamura 0:a40b9a259b52 2528 // prevent spurious errors from being emitted when the window is unloaded
Osamu Nakamura 0:a40b9a259b52 2529 if (global.document && global.addEventListener) {
Osamu Nakamura 0:a40b9a259b52 2530 global.addEventListener('beforeunload', function () {
Osamu Nakamura 0:a40b9a259b52 2531 if (self.script) self.script.onerror = empty;
Osamu Nakamura 0:a40b9a259b52 2532 }, false);
Osamu Nakamura 0:a40b9a259b52 2533 }
Osamu Nakamura 0:a40b9a259b52 2534 }
Osamu Nakamura 0:a40b9a259b52 2535
Osamu Nakamura 0:a40b9a259b52 2536 /**
Osamu Nakamura 0:a40b9a259b52 2537 * Inherits from Polling.
Osamu Nakamura 0:a40b9a259b52 2538 */
Osamu Nakamura 0:a40b9a259b52 2539
Osamu Nakamura 0:a40b9a259b52 2540 inherit(JSONPPolling, Polling);
Osamu Nakamura 0:a40b9a259b52 2541
Osamu Nakamura 0:a40b9a259b52 2542 /*
Osamu Nakamura 0:a40b9a259b52 2543 * JSONP only supports binary as base64 encoded strings
Osamu Nakamura 0:a40b9a259b52 2544 */
Osamu Nakamura 0:a40b9a259b52 2545
Osamu Nakamura 0:a40b9a259b52 2546 JSONPPolling.prototype.supportsBinary = false;
Osamu Nakamura 0:a40b9a259b52 2547
Osamu Nakamura 0:a40b9a259b52 2548 /**
Osamu Nakamura 0:a40b9a259b52 2549 * Closes the socket.
Osamu Nakamura 0:a40b9a259b52 2550 *
Osamu Nakamura 0:a40b9a259b52 2551 * @api private
Osamu Nakamura 0:a40b9a259b52 2552 */
Osamu Nakamura 0:a40b9a259b52 2553
Osamu Nakamura 0:a40b9a259b52 2554 JSONPPolling.prototype.doClose = function () {
Osamu Nakamura 0:a40b9a259b52 2555 if (this.script) {
Osamu Nakamura 0:a40b9a259b52 2556 this.script.parentNode.removeChild(this.script);
Osamu Nakamura 0:a40b9a259b52 2557 this.script = null;
Osamu Nakamura 0:a40b9a259b52 2558 }
Osamu Nakamura 0:a40b9a259b52 2559
Osamu Nakamura 0:a40b9a259b52 2560 if (this.form) {
Osamu Nakamura 0:a40b9a259b52 2561 this.form.parentNode.removeChild(this.form);
Osamu Nakamura 0:a40b9a259b52 2562 this.form = null;
Osamu Nakamura 0:a40b9a259b52 2563 this.iframe = null;
Osamu Nakamura 0:a40b9a259b52 2564 }
Osamu Nakamura 0:a40b9a259b52 2565
Osamu Nakamura 0:a40b9a259b52 2566 Polling.prototype.doClose.call(this);
Osamu Nakamura 0:a40b9a259b52 2567 };
Osamu Nakamura 0:a40b9a259b52 2568
Osamu Nakamura 0:a40b9a259b52 2569 /**
Osamu Nakamura 0:a40b9a259b52 2570 * Starts a poll cycle.
Osamu Nakamura 0:a40b9a259b52 2571 *
Osamu Nakamura 0:a40b9a259b52 2572 * @api private
Osamu Nakamura 0:a40b9a259b52 2573 */
Osamu Nakamura 0:a40b9a259b52 2574
Osamu Nakamura 0:a40b9a259b52 2575 JSONPPolling.prototype.doPoll = function () {
Osamu Nakamura 0:a40b9a259b52 2576 var self = this;
Osamu Nakamura 0:a40b9a259b52 2577 var script = document.createElement('script');
Osamu Nakamura 0:a40b9a259b52 2578
Osamu Nakamura 0:a40b9a259b52 2579 if (this.script) {
Osamu Nakamura 0:a40b9a259b52 2580 this.script.parentNode.removeChild(this.script);
Osamu Nakamura 0:a40b9a259b52 2581 this.script = null;
Osamu Nakamura 0:a40b9a259b52 2582 }
Osamu Nakamura 0:a40b9a259b52 2583
Osamu Nakamura 0:a40b9a259b52 2584 script.async = true;
Osamu Nakamura 0:a40b9a259b52 2585 script.src = this.uri();
Osamu Nakamura 0:a40b9a259b52 2586 script.onerror = function(e){
Osamu Nakamura 0:a40b9a259b52 2587 self.onError('jsonp poll error',e);
Osamu Nakamura 0:a40b9a259b52 2588 };
Osamu Nakamura 0:a40b9a259b52 2589
Osamu Nakamura 0:a40b9a259b52 2590 var insertAt = document.getElementsByTagName('script')[0];
Osamu Nakamura 0:a40b9a259b52 2591 insertAt.parentNode.insertBefore(script, insertAt);
Osamu Nakamura 0:a40b9a259b52 2592 this.script = script;
Osamu Nakamura 0:a40b9a259b52 2593
Osamu Nakamura 0:a40b9a259b52 2594 var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent);
Osamu Nakamura 0:a40b9a259b52 2595
Osamu Nakamura 0:a40b9a259b52 2596 if (isUAgecko) {
Osamu Nakamura 0:a40b9a259b52 2597 setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 2598 var iframe = document.createElement('iframe');
Osamu Nakamura 0:a40b9a259b52 2599 document.body.appendChild(iframe);
Osamu Nakamura 0:a40b9a259b52 2600 document.body.removeChild(iframe);
Osamu Nakamura 0:a40b9a259b52 2601 }, 100);
Osamu Nakamura 0:a40b9a259b52 2602 }
Osamu Nakamura 0:a40b9a259b52 2603 };
Osamu Nakamura 0:a40b9a259b52 2604
Osamu Nakamura 0:a40b9a259b52 2605 /**
Osamu Nakamura 0:a40b9a259b52 2606 * Writes with a hidden iframe.
Osamu Nakamura 0:a40b9a259b52 2607 *
Osamu Nakamura 0:a40b9a259b52 2608 * @param {String} data to send
Osamu Nakamura 0:a40b9a259b52 2609 * @param {Function} called upon flush.
Osamu Nakamura 0:a40b9a259b52 2610 * @api private
Osamu Nakamura 0:a40b9a259b52 2611 */
Osamu Nakamura 0:a40b9a259b52 2612
Osamu Nakamura 0:a40b9a259b52 2613 JSONPPolling.prototype.doWrite = function (data, fn) {
Osamu Nakamura 0:a40b9a259b52 2614 var self = this;
Osamu Nakamura 0:a40b9a259b52 2615
Osamu Nakamura 0:a40b9a259b52 2616 if (!this.form) {
Osamu Nakamura 0:a40b9a259b52 2617 var form = document.createElement('form');
Osamu Nakamura 0:a40b9a259b52 2618 var area = document.createElement('textarea');
Osamu Nakamura 0:a40b9a259b52 2619 var id = this.iframeId = 'eio_iframe_' + this.index;
Osamu Nakamura 0:a40b9a259b52 2620 var iframe;
Osamu Nakamura 0:a40b9a259b52 2621
Osamu Nakamura 0:a40b9a259b52 2622 form.className = 'socketio';
Osamu Nakamura 0:a40b9a259b52 2623 form.style.position = 'absolute';
Osamu Nakamura 0:a40b9a259b52 2624 form.style.top = '-1000px';
Osamu Nakamura 0:a40b9a259b52 2625 form.style.left = '-1000px';
Osamu Nakamura 0:a40b9a259b52 2626 form.target = id;
Osamu Nakamura 0:a40b9a259b52 2627 form.method = 'POST';
Osamu Nakamura 0:a40b9a259b52 2628 form.setAttribute('accept-charset', 'utf-8');
Osamu Nakamura 0:a40b9a259b52 2629 area.name = 'd';
Osamu Nakamura 0:a40b9a259b52 2630 form.appendChild(area);
Osamu Nakamura 0:a40b9a259b52 2631 document.body.appendChild(form);
Osamu Nakamura 0:a40b9a259b52 2632
Osamu Nakamura 0:a40b9a259b52 2633 this.form = form;
Osamu Nakamura 0:a40b9a259b52 2634 this.area = area;
Osamu Nakamura 0:a40b9a259b52 2635 }
Osamu Nakamura 0:a40b9a259b52 2636
Osamu Nakamura 0:a40b9a259b52 2637 this.form.action = this.uri();
Osamu Nakamura 0:a40b9a259b52 2638
Osamu Nakamura 0:a40b9a259b52 2639 function complete () {
Osamu Nakamura 0:a40b9a259b52 2640 initIframe();
Osamu Nakamura 0:a40b9a259b52 2641 fn();
Osamu Nakamura 0:a40b9a259b52 2642 }
Osamu Nakamura 0:a40b9a259b52 2643
Osamu Nakamura 0:a40b9a259b52 2644 function initIframe () {
Osamu Nakamura 0:a40b9a259b52 2645 if (self.iframe) {
Osamu Nakamura 0:a40b9a259b52 2646 try {
Osamu Nakamura 0:a40b9a259b52 2647 self.form.removeChild(self.iframe);
Osamu Nakamura 0:a40b9a259b52 2648 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 2649 self.onError('jsonp polling iframe removal error', e);
Osamu Nakamura 0:a40b9a259b52 2650 }
Osamu Nakamura 0:a40b9a259b52 2651 }
Osamu Nakamura 0:a40b9a259b52 2652
Osamu Nakamura 0:a40b9a259b52 2653 try {
Osamu Nakamura 0:a40b9a259b52 2654 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
Osamu Nakamura 0:a40b9a259b52 2655 var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">';
Osamu Nakamura 0:a40b9a259b52 2656 iframe = document.createElement(html);
Osamu Nakamura 0:a40b9a259b52 2657 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 2658 iframe = document.createElement('iframe');
Osamu Nakamura 0:a40b9a259b52 2659 iframe.name = self.iframeId;
Osamu Nakamura 0:a40b9a259b52 2660 iframe.src = 'javascript:0';
Osamu Nakamura 0:a40b9a259b52 2661 }
Osamu Nakamura 0:a40b9a259b52 2662
Osamu Nakamura 0:a40b9a259b52 2663 iframe.id = self.iframeId;
Osamu Nakamura 0:a40b9a259b52 2664
Osamu Nakamura 0:a40b9a259b52 2665 self.form.appendChild(iframe);
Osamu Nakamura 0:a40b9a259b52 2666 self.iframe = iframe;
Osamu Nakamura 0:a40b9a259b52 2667 }
Osamu Nakamura 0:a40b9a259b52 2668
Osamu Nakamura 0:a40b9a259b52 2669 initIframe();
Osamu Nakamura 0:a40b9a259b52 2670
Osamu Nakamura 0:a40b9a259b52 2671 // escape \n to prevent it from being converted into \r\n by some UAs
Osamu Nakamura 0:a40b9a259b52 2672 // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
Osamu Nakamura 0:a40b9a259b52 2673 data = data.replace(rEscapedNewline, '\\\n');
Osamu Nakamura 0:a40b9a259b52 2674 this.area.value = data.replace(rNewline, '\\n');
Osamu Nakamura 0:a40b9a259b52 2675
Osamu Nakamura 0:a40b9a259b52 2676 try {
Osamu Nakamura 0:a40b9a259b52 2677 this.form.submit();
Osamu Nakamura 0:a40b9a259b52 2678 } catch(e) {}
Osamu Nakamura 0:a40b9a259b52 2679
Osamu Nakamura 0:a40b9a259b52 2680 if (this.iframe.attachEvent) {
Osamu Nakamura 0:a40b9a259b52 2681 this.iframe.onreadystatechange = function(){
Osamu Nakamura 0:a40b9a259b52 2682 if (self.iframe.readyState == 'complete') {
Osamu Nakamura 0:a40b9a259b52 2683 complete();
Osamu Nakamura 0:a40b9a259b52 2684 }
Osamu Nakamura 0:a40b9a259b52 2685 };
Osamu Nakamura 0:a40b9a259b52 2686 } else {
Osamu Nakamura 0:a40b9a259b52 2687 this.iframe.onload = complete;
Osamu Nakamura 0:a40b9a259b52 2688 }
Osamu Nakamura 0:a40b9a259b52 2689 };
Osamu Nakamura 0:a40b9a259b52 2690
Osamu Nakamura 0:a40b9a259b52 2691 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 2692 },{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 2693 (function (global){
Osamu Nakamura 0:a40b9a259b52 2694 /**
Osamu Nakamura 0:a40b9a259b52 2695 * Module requirements.
Osamu Nakamura 0:a40b9a259b52 2696 */
Osamu Nakamura 0:a40b9a259b52 2697
Osamu Nakamura 0:a40b9a259b52 2698 var XMLHttpRequest = _dereq_('xmlhttprequest');
Osamu Nakamura 0:a40b9a259b52 2699 var Polling = _dereq_('./polling');
Osamu Nakamura 0:a40b9a259b52 2700 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 2701 var inherit = _dereq_('component-inherit');
Osamu Nakamura 0:a40b9a259b52 2702 var debug = _dereq_('debug')('engine.io-client:polling-xhr');
Osamu Nakamura 0:a40b9a259b52 2703
Osamu Nakamura 0:a40b9a259b52 2704 /**
Osamu Nakamura 0:a40b9a259b52 2705 * Module exports.
Osamu Nakamura 0:a40b9a259b52 2706 */
Osamu Nakamura 0:a40b9a259b52 2707
Osamu Nakamura 0:a40b9a259b52 2708 module.exports = XHR;
Osamu Nakamura 0:a40b9a259b52 2709 module.exports.Request = Request;
Osamu Nakamura 0:a40b9a259b52 2710
Osamu Nakamura 0:a40b9a259b52 2711 /**
Osamu Nakamura 0:a40b9a259b52 2712 * Empty function
Osamu Nakamura 0:a40b9a259b52 2713 */
Osamu Nakamura 0:a40b9a259b52 2714
Osamu Nakamura 0:a40b9a259b52 2715 function empty(){}
Osamu Nakamura 0:a40b9a259b52 2716
Osamu Nakamura 0:a40b9a259b52 2717 /**
Osamu Nakamura 0:a40b9a259b52 2718 * XHR Polling constructor.
Osamu Nakamura 0:a40b9a259b52 2719 *
Osamu Nakamura 0:a40b9a259b52 2720 * @param {Object} opts
Osamu Nakamura 0:a40b9a259b52 2721 * @api public
Osamu Nakamura 0:a40b9a259b52 2722 */
Osamu Nakamura 0:a40b9a259b52 2723
Osamu Nakamura 0:a40b9a259b52 2724 function XHR(opts){
Osamu Nakamura 0:a40b9a259b52 2725 Polling.call(this, opts);
Osamu Nakamura 0:a40b9a259b52 2726
Osamu Nakamura 0:a40b9a259b52 2727 if (global.location) {
Osamu Nakamura 0:a40b9a259b52 2728 var isSSL = 'https:' == location.protocol;
Osamu Nakamura 0:a40b9a259b52 2729 var port = location.port;
Osamu Nakamura 0:a40b9a259b52 2730
Osamu Nakamura 0:a40b9a259b52 2731 // some user agents have empty `location.port`
Osamu Nakamura 0:a40b9a259b52 2732 if (!port) {
Osamu Nakamura 0:a40b9a259b52 2733 port = isSSL ? 443 : 80;
Osamu Nakamura 0:a40b9a259b52 2734 }
Osamu Nakamura 0:a40b9a259b52 2735
Osamu Nakamura 0:a40b9a259b52 2736 this.xd = opts.hostname != global.location.hostname ||
Osamu Nakamura 0:a40b9a259b52 2737 port != opts.port;
Osamu Nakamura 0:a40b9a259b52 2738 this.xs = opts.secure != isSSL;
Osamu Nakamura 0:a40b9a259b52 2739 }
Osamu Nakamura 0:a40b9a259b52 2740 }
Osamu Nakamura 0:a40b9a259b52 2741
Osamu Nakamura 0:a40b9a259b52 2742 /**
Osamu Nakamura 0:a40b9a259b52 2743 * Inherits from Polling.
Osamu Nakamura 0:a40b9a259b52 2744 */
Osamu Nakamura 0:a40b9a259b52 2745
Osamu Nakamura 0:a40b9a259b52 2746 inherit(XHR, Polling);
Osamu Nakamura 0:a40b9a259b52 2747
Osamu Nakamura 0:a40b9a259b52 2748 /**
Osamu Nakamura 0:a40b9a259b52 2749 * XHR supports binary
Osamu Nakamura 0:a40b9a259b52 2750 */
Osamu Nakamura 0:a40b9a259b52 2751
Osamu Nakamura 0:a40b9a259b52 2752 XHR.prototype.supportsBinary = true;
Osamu Nakamura 0:a40b9a259b52 2753
Osamu Nakamura 0:a40b9a259b52 2754 /**
Osamu Nakamura 0:a40b9a259b52 2755 * Creates a request.
Osamu Nakamura 0:a40b9a259b52 2756 *
Osamu Nakamura 0:a40b9a259b52 2757 * @param {String} method
Osamu Nakamura 0:a40b9a259b52 2758 * @api private
Osamu Nakamura 0:a40b9a259b52 2759 */
Osamu Nakamura 0:a40b9a259b52 2760
Osamu Nakamura 0:a40b9a259b52 2761 XHR.prototype.request = function(opts){
Osamu Nakamura 0:a40b9a259b52 2762 opts = opts || {};
Osamu Nakamura 0:a40b9a259b52 2763 opts.uri = this.uri();
Osamu Nakamura 0:a40b9a259b52 2764 opts.xd = this.xd;
Osamu Nakamura 0:a40b9a259b52 2765 opts.xs = this.xs;
Osamu Nakamura 0:a40b9a259b52 2766 opts.agent = this.agent || false;
Osamu Nakamura 0:a40b9a259b52 2767 opts.supportsBinary = this.supportsBinary;
Osamu Nakamura 0:a40b9a259b52 2768 opts.enablesXDR = this.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 2769
Osamu Nakamura 0:a40b9a259b52 2770 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 2771 opts.pfx = this.pfx;
Osamu Nakamura 0:a40b9a259b52 2772 opts.key = this.key;
Osamu Nakamura 0:a40b9a259b52 2773 opts.passphrase = this.passphrase;
Osamu Nakamura 0:a40b9a259b52 2774 opts.cert = this.cert;
Osamu Nakamura 0:a40b9a259b52 2775 opts.ca = this.ca;
Osamu Nakamura 0:a40b9a259b52 2776 opts.ciphers = this.ciphers;
Osamu Nakamura 0:a40b9a259b52 2777 opts.rejectUnauthorized = this.rejectUnauthorized;
Osamu Nakamura 0:a40b9a259b52 2778
Osamu Nakamura 0:a40b9a259b52 2779 return new Request(opts);
Osamu Nakamura 0:a40b9a259b52 2780 };
Osamu Nakamura 0:a40b9a259b52 2781
Osamu Nakamura 0:a40b9a259b52 2782 /**
Osamu Nakamura 0:a40b9a259b52 2783 * Sends data.
Osamu Nakamura 0:a40b9a259b52 2784 *
Osamu Nakamura 0:a40b9a259b52 2785 * @param {String} data to send.
Osamu Nakamura 0:a40b9a259b52 2786 * @param {Function} called upon flush.
Osamu Nakamura 0:a40b9a259b52 2787 * @api private
Osamu Nakamura 0:a40b9a259b52 2788 */
Osamu Nakamura 0:a40b9a259b52 2789
Osamu Nakamura 0:a40b9a259b52 2790 XHR.prototype.doWrite = function(data, fn){
Osamu Nakamura 0:a40b9a259b52 2791 var isBinary = typeof data !== 'string' && data !== undefined;
Osamu Nakamura 0:a40b9a259b52 2792 var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
Osamu Nakamura 0:a40b9a259b52 2793 var self = this;
Osamu Nakamura 0:a40b9a259b52 2794 req.on('success', fn);
Osamu Nakamura 0:a40b9a259b52 2795 req.on('error', function(err){
Osamu Nakamura 0:a40b9a259b52 2796 self.onError('xhr post error', err);
Osamu Nakamura 0:a40b9a259b52 2797 });
Osamu Nakamura 0:a40b9a259b52 2798 this.sendXhr = req;
Osamu Nakamura 0:a40b9a259b52 2799 };
Osamu Nakamura 0:a40b9a259b52 2800
Osamu Nakamura 0:a40b9a259b52 2801 /**
Osamu Nakamura 0:a40b9a259b52 2802 * Starts a poll cycle.
Osamu Nakamura 0:a40b9a259b52 2803 *
Osamu Nakamura 0:a40b9a259b52 2804 * @api private
Osamu Nakamura 0:a40b9a259b52 2805 */
Osamu Nakamura 0:a40b9a259b52 2806
Osamu Nakamura 0:a40b9a259b52 2807 XHR.prototype.doPoll = function(){
Osamu Nakamura 0:a40b9a259b52 2808 debug('xhr poll');
Osamu Nakamura 0:a40b9a259b52 2809 var req = this.request();
Osamu Nakamura 0:a40b9a259b52 2810 var self = this;
Osamu Nakamura 0:a40b9a259b52 2811 req.on('data', function(data){
Osamu Nakamura 0:a40b9a259b52 2812 self.onData(data);
Osamu Nakamura 0:a40b9a259b52 2813 });
Osamu Nakamura 0:a40b9a259b52 2814 req.on('error', function(err){
Osamu Nakamura 0:a40b9a259b52 2815 self.onError('xhr poll error', err);
Osamu Nakamura 0:a40b9a259b52 2816 });
Osamu Nakamura 0:a40b9a259b52 2817 this.pollXhr = req;
Osamu Nakamura 0:a40b9a259b52 2818 };
Osamu Nakamura 0:a40b9a259b52 2819
Osamu Nakamura 0:a40b9a259b52 2820 /**
Osamu Nakamura 0:a40b9a259b52 2821 * Request constructor
Osamu Nakamura 0:a40b9a259b52 2822 *
Osamu Nakamura 0:a40b9a259b52 2823 * @param {Object} options
Osamu Nakamura 0:a40b9a259b52 2824 * @api public
Osamu Nakamura 0:a40b9a259b52 2825 */
Osamu Nakamura 0:a40b9a259b52 2826
Osamu Nakamura 0:a40b9a259b52 2827 function Request(opts){
Osamu Nakamura 0:a40b9a259b52 2828 this.method = opts.method || 'GET';
Osamu Nakamura 0:a40b9a259b52 2829 this.uri = opts.uri;
Osamu Nakamura 0:a40b9a259b52 2830 this.xd = !!opts.xd;
Osamu Nakamura 0:a40b9a259b52 2831 this.xs = !!opts.xs;
Osamu Nakamura 0:a40b9a259b52 2832 this.async = false !== opts.async;
Osamu Nakamura 0:a40b9a259b52 2833 this.data = undefined != opts.data ? opts.data : null;
Osamu Nakamura 0:a40b9a259b52 2834 this.agent = opts.agent;
Osamu Nakamura 0:a40b9a259b52 2835 this.isBinary = opts.isBinary;
Osamu Nakamura 0:a40b9a259b52 2836 this.supportsBinary = opts.supportsBinary;
Osamu Nakamura 0:a40b9a259b52 2837 this.enablesXDR = opts.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 2838
Osamu Nakamura 0:a40b9a259b52 2839 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 2840 this.pfx = opts.pfx;
Osamu Nakamura 0:a40b9a259b52 2841 this.key = opts.key;
Osamu Nakamura 0:a40b9a259b52 2842 this.passphrase = opts.passphrase;
Osamu Nakamura 0:a40b9a259b52 2843 this.cert = opts.cert;
Osamu Nakamura 0:a40b9a259b52 2844 this.ca = opts.ca;
Osamu Nakamura 0:a40b9a259b52 2845 this.ciphers = opts.ciphers;
Osamu Nakamura 0:a40b9a259b52 2846 this.rejectUnauthorized = opts.rejectUnauthorized;
Osamu Nakamura 0:a40b9a259b52 2847
Osamu Nakamura 0:a40b9a259b52 2848 this.create();
Osamu Nakamura 0:a40b9a259b52 2849 }
Osamu Nakamura 0:a40b9a259b52 2850
Osamu Nakamura 0:a40b9a259b52 2851 /**
Osamu Nakamura 0:a40b9a259b52 2852 * Mix in `Emitter`.
Osamu Nakamura 0:a40b9a259b52 2853 */
Osamu Nakamura 0:a40b9a259b52 2854
Osamu Nakamura 0:a40b9a259b52 2855 Emitter(Request.prototype);
Osamu Nakamura 0:a40b9a259b52 2856
Osamu Nakamura 0:a40b9a259b52 2857 /**
Osamu Nakamura 0:a40b9a259b52 2858 * Creates the XHR object and sends the request.
Osamu Nakamura 0:a40b9a259b52 2859 *
Osamu Nakamura 0:a40b9a259b52 2860 * @api private
Osamu Nakamura 0:a40b9a259b52 2861 */
Osamu Nakamura 0:a40b9a259b52 2862
Osamu Nakamura 0:a40b9a259b52 2863 Request.prototype.create = function(){
Osamu Nakamura 0:a40b9a259b52 2864 var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
Osamu Nakamura 0:a40b9a259b52 2865
Osamu Nakamura 0:a40b9a259b52 2866 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 2867 opts.pfx = this.pfx;
Osamu Nakamura 0:a40b9a259b52 2868 opts.key = this.key;
Osamu Nakamura 0:a40b9a259b52 2869 opts.passphrase = this.passphrase;
Osamu Nakamura 0:a40b9a259b52 2870 opts.cert = this.cert;
Osamu Nakamura 0:a40b9a259b52 2871 opts.ca = this.ca;
Osamu Nakamura 0:a40b9a259b52 2872 opts.ciphers = this.ciphers;
Osamu Nakamura 0:a40b9a259b52 2873 opts.rejectUnauthorized = this.rejectUnauthorized;
Osamu Nakamura 0:a40b9a259b52 2874
Osamu Nakamura 0:a40b9a259b52 2875 var xhr = this.xhr = new XMLHttpRequest(opts);
Osamu Nakamura 0:a40b9a259b52 2876 var self = this;
Osamu Nakamura 0:a40b9a259b52 2877
Osamu Nakamura 0:a40b9a259b52 2878 try {
Osamu Nakamura 0:a40b9a259b52 2879 debug('xhr open %s: %s', this.method, this.uri);
Osamu Nakamura 0:a40b9a259b52 2880 xhr.open(this.method, this.uri, this.async);
Osamu Nakamura 0:a40b9a259b52 2881 if (this.supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 2882 // This has to be done after open because Firefox is stupid
Osamu Nakamura 0:a40b9a259b52 2883 // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
Osamu Nakamura 0:a40b9a259b52 2884 xhr.responseType = 'arraybuffer';
Osamu Nakamura 0:a40b9a259b52 2885 }
Osamu Nakamura 0:a40b9a259b52 2886
Osamu Nakamura 0:a40b9a259b52 2887 if ('POST' == this.method) {
Osamu Nakamura 0:a40b9a259b52 2888 try {
Osamu Nakamura 0:a40b9a259b52 2889 if (this.isBinary) {
Osamu Nakamura 0:a40b9a259b52 2890 xhr.setRequestHeader('Content-type', 'application/octet-stream');
Osamu Nakamura 0:a40b9a259b52 2891 } else {
Osamu Nakamura 0:a40b9a259b52 2892 xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
Osamu Nakamura 0:a40b9a259b52 2893 }
Osamu Nakamura 0:a40b9a259b52 2894 } catch (e) {}
Osamu Nakamura 0:a40b9a259b52 2895 }
Osamu Nakamura 0:a40b9a259b52 2896
Osamu Nakamura 0:a40b9a259b52 2897 // ie6 check
Osamu Nakamura 0:a40b9a259b52 2898 if ('withCredentials' in xhr) {
Osamu Nakamura 0:a40b9a259b52 2899 xhr.withCredentials = true;
Osamu Nakamura 0:a40b9a259b52 2900 }
Osamu Nakamura 0:a40b9a259b52 2901
Osamu Nakamura 0:a40b9a259b52 2902 if (this.hasXDR()) {
Osamu Nakamura 0:a40b9a259b52 2903 xhr.onload = function(){
Osamu Nakamura 0:a40b9a259b52 2904 self.onLoad();
Osamu Nakamura 0:a40b9a259b52 2905 };
Osamu Nakamura 0:a40b9a259b52 2906 xhr.onerror = function(){
Osamu Nakamura 0:a40b9a259b52 2907 self.onError(xhr.responseText);
Osamu Nakamura 0:a40b9a259b52 2908 };
Osamu Nakamura 0:a40b9a259b52 2909 } else {
Osamu Nakamura 0:a40b9a259b52 2910 xhr.onreadystatechange = function(){
Osamu Nakamura 0:a40b9a259b52 2911 if (4 != xhr.readyState) return;
Osamu Nakamura 0:a40b9a259b52 2912 if (200 == xhr.status || 1223 == xhr.status) {
Osamu Nakamura 0:a40b9a259b52 2913 self.onLoad();
Osamu Nakamura 0:a40b9a259b52 2914 } else {
Osamu Nakamura 0:a40b9a259b52 2915 // make sure the `error` event handler that's user-set
Osamu Nakamura 0:a40b9a259b52 2916 // does not throw in the same tick and gets caught here
Osamu Nakamura 0:a40b9a259b52 2917 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 2918 self.onError(xhr.status);
Osamu Nakamura 0:a40b9a259b52 2919 }, 0);
Osamu Nakamura 0:a40b9a259b52 2920 }
Osamu Nakamura 0:a40b9a259b52 2921 };
Osamu Nakamura 0:a40b9a259b52 2922 }
Osamu Nakamura 0:a40b9a259b52 2923
Osamu Nakamura 0:a40b9a259b52 2924 debug('xhr data %s', this.data);
Osamu Nakamura 0:a40b9a259b52 2925 xhr.send(this.data);
Osamu Nakamura 0:a40b9a259b52 2926 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 2927 // Need to defer since .create() is called directly fhrom the constructor
Osamu Nakamura 0:a40b9a259b52 2928 // and thus the 'error' event can only be only bound *after* this exception
Osamu Nakamura 0:a40b9a259b52 2929 // occurs. Therefore, also, we cannot throw here at all.
Osamu Nakamura 0:a40b9a259b52 2930 setTimeout(function() {
Osamu Nakamura 0:a40b9a259b52 2931 self.onError(e);
Osamu Nakamura 0:a40b9a259b52 2932 }, 0);
Osamu Nakamura 0:a40b9a259b52 2933 return;
Osamu Nakamura 0:a40b9a259b52 2934 }
Osamu Nakamura 0:a40b9a259b52 2935
Osamu Nakamura 0:a40b9a259b52 2936 if (global.document) {
Osamu Nakamura 0:a40b9a259b52 2937 this.index = Request.requestsCount++;
Osamu Nakamura 0:a40b9a259b52 2938 Request.requests[this.index] = this;
Osamu Nakamura 0:a40b9a259b52 2939 }
Osamu Nakamura 0:a40b9a259b52 2940 };
Osamu Nakamura 0:a40b9a259b52 2941
Osamu Nakamura 0:a40b9a259b52 2942 /**
Osamu Nakamura 0:a40b9a259b52 2943 * Called upon successful response.
Osamu Nakamura 0:a40b9a259b52 2944 *
Osamu Nakamura 0:a40b9a259b52 2945 * @api private
Osamu Nakamura 0:a40b9a259b52 2946 */
Osamu Nakamura 0:a40b9a259b52 2947
Osamu Nakamura 0:a40b9a259b52 2948 Request.prototype.onSuccess = function(){
Osamu Nakamura 0:a40b9a259b52 2949 this.emit('success');
Osamu Nakamura 0:a40b9a259b52 2950 this.cleanup();
Osamu Nakamura 0:a40b9a259b52 2951 };
Osamu Nakamura 0:a40b9a259b52 2952
Osamu Nakamura 0:a40b9a259b52 2953 /**
Osamu Nakamura 0:a40b9a259b52 2954 * Called if we have data.
Osamu Nakamura 0:a40b9a259b52 2955 *
Osamu Nakamura 0:a40b9a259b52 2956 * @api private
Osamu Nakamura 0:a40b9a259b52 2957 */
Osamu Nakamura 0:a40b9a259b52 2958
Osamu Nakamura 0:a40b9a259b52 2959 Request.prototype.onData = function(data){
Osamu Nakamura 0:a40b9a259b52 2960 this.emit('data', data);
Osamu Nakamura 0:a40b9a259b52 2961 this.onSuccess();
Osamu Nakamura 0:a40b9a259b52 2962 };
Osamu Nakamura 0:a40b9a259b52 2963
Osamu Nakamura 0:a40b9a259b52 2964 /**
Osamu Nakamura 0:a40b9a259b52 2965 * Called upon error.
Osamu Nakamura 0:a40b9a259b52 2966 *
Osamu Nakamura 0:a40b9a259b52 2967 * @api private
Osamu Nakamura 0:a40b9a259b52 2968 */
Osamu Nakamura 0:a40b9a259b52 2969
Osamu Nakamura 0:a40b9a259b52 2970 Request.prototype.onError = function(err){
Osamu Nakamura 0:a40b9a259b52 2971 this.emit('error', err);
Osamu Nakamura 0:a40b9a259b52 2972 this.cleanup(true);
Osamu Nakamura 0:a40b9a259b52 2973 };
Osamu Nakamura 0:a40b9a259b52 2974
Osamu Nakamura 0:a40b9a259b52 2975 /**
Osamu Nakamura 0:a40b9a259b52 2976 * Cleans up house.
Osamu Nakamura 0:a40b9a259b52 2977 *
Osamu Nakamura 0:a40b9a259b52 2978 * @api private
Osamu Nakamura 0:a40b9a259b52 2979 */
Osamu Nakamura 0:a40b9a259b52 2980
Osamu Nakamura 0:a40b9a259b52 2981 Request.prototype.cleanup = function(fromError){
Osamu Nakamura 0:a40b9a259b52 2982 if ('undefined' == typeof this.xhr || null === this.xhr) {
Osamu Nakamura 0:a40b9a259b52 2983 return;
Osamu Nakamura 0:a40b9a259b52 2984 }
Osamu Nakamura 0:a40b9a259b52 2985 // xmlhttprequest
Osamu Nakamura 0:a40b9a259b52 2986 if (this.hasXDR()) {
Osamu Nakamura 0:a40b9a259b52 2987 this.xhr.onload = this.xhr.onerror = empty;
Osamu Nakamura 0:a40b9a259b52 2988 } else {
Osamu Nakamura 0:a40b9a259b52 2989 this.xhr.onreadystatechange = empty;
Osamu Nakamura 0:a40b9a259b52 2990 }
Osamu Nakamura 0:a40b9a259b52 2991
Osamu Nakamura 0:a40b9a259b52 2992 if (fromError) {
Osamu Nakamura 0:a40b9a259b52 2993 try {
Osamu Nakamura 0:a40b9a259b52 2994 this.xhr.abort();
Osamu Nakamura 0:a40b9a259b52 2995 } catch(e) {}
Osamu Nakamura 0:a40b9a259b52 2996 }
Osamu Nakamura 0:a40b9a259b52 2997
Osamu Nakamura 0:a40b9a259b52 2998 if (global.document) {
Osamu Nakamura 0:a40b9a259b52 2999 delete Request.requests[this.index];
Osamu Nakamura 0:a40b9a259b52 3000 }
Osamu Nakamura 0:a40b9a259b52 3001
Osamu Nakamura 0:a40b9a259b52 3002 this.xhr = null;
Osamu Nakamura 0:a40b9a259b52 3003 };
Osamu Nakamura 0:a40b9a259b52 3004
Osamu Nakamura 0:a40b9a259b52 3005 /**
Osamu Nakamura 0:a40b9a259b52 3006 * Called upon load.
Osamu Nakamura 0:a40b9a259b52 3007 *
Osamu Nakamura 0:a40b9a259b52 3008 * @api private
Osamu Nakamura 0:a40b9a259b52 3009 */
Osamu Nakamura 0:a40b9a259b52 3010
Osamu Nakamura 0:a40b9a259b52 3011 Request.prototype.onLoad = function(){
Osamu Nakamura 0:a40b9a259b52 3012 var data;
Osamu Nakamura 0:a40b9a259b52 3013 try {
Osamu Nakamura 0:a40b9a259b52 3014 var contentType;
Osamu Nakamura 0:a40b9a259b52 3015 try {
Osamu Nakamura 0:a40b9a259b52 3016 contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
Osamu Nakamura 0:a40b9a259b52 3017 } catch (e) {}
Osamu Nakamura 0:a40b9a259b52 3018 if (contentType === 'application/octet-stream') {
Osamu Nakamura 0:a40b9a259b52 3019 data = this.xhr.response;
Osamu Nakamura 0:a40b9a259b52 3020 } else {
Osamu Nakamura 0:a40b9a259b52 3021 if (!this.supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 3022 data = this.xhr.responseText;
Osamu Nakamura 0:a40b9a259b52 3023 } else {
Osamu Nakamura 0:a40b9a259b52 3024 data = 'ok';
Osamu Nakamura 0:a40b9a259b52 3025 }
Osamu Nakamura 0:a40b9a259b52 3026 }
Osamu Nakamura 0:a40b9a259b52 3027 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 3028 this.onError(e);
Osamu Nakamura 0:a40b9a259b52 3029 }
Osamu Nakamura 0:a40b9a259b52 3030 if (null != data) {
Osamu Nakamura 0:a40b9a259b52 3031 this.onData(data);
Osamu Nakamura 0:a40b9a259b52 3032 }
Osamu Nakamura 0:a40b9a259b52 3033 };
Osamu Nakamura 0:a40b9a259b52 3034
Osamu Nakamura 0:a40b9a259b52 3035 /**
Osamu Nakamura 0:a40b9a259b52 3036 * Check if it has XDomainRequest.
Osamu Nakamura 0:a40b9a259b52 3037 *
Osamu Nakamura 0:a40b9a259b52 3038 * @api private
Osamu Nakamura 0:a40b9a259b52 3039 */
Osamu Nakamura 0:a40b9a259b52 3040
Osamu Nakamura 0:a40b9a259b52 3041 Request.prototype.hasXDR = function(){
Osamu Nakamura 0:a40b9a259b52 3042 return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 3043 };
Osamu Nakamura 0:a40b9a259b52 3044
Osamu Nakamura 0:a40b9a259b52 3045 /**
Osamu Nakamura 0:a40b9a259b52 3046 * Aborts the request.
Osamu Nakamura 0:a40b9a259b52 3047 *
Osamu Nakamura 0:a40b9a259b52 3048 * @api public
Osamu Nakamura 0:a40b9a259b52 3049 */
Osamu Nakamura 0:a40b9a259b52 3050
Osamu Nakamura 0:a40b9a259b52 3051 Request.prototype.abort = function(){
Osamu Nakamura 0:a40b9a259b52 3052 this.cleanup();
Osamu Nakamura 0:a40b9a259b52 3053 };
Osamu Nakamura 0:a40b9a259b52 3054
Osamu Nakamura 0:a40b9a259b52 3055 /**
Osamu Nakamura 0:a40b9a259b52 3056 * Aborts pending requests when unloading the window. This is needed to prevent
Osamu Nakamura 0:a40b9a259b52 3057 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
Osamu Nakamura 0:a40b9a259b52 3058 * emitted.
Osamu Nakamura 0:a40b9a259b52 3059 */
Osamu Nakamura 0:a40b9a259b52 3060
Osamu Nakamura 0:a40b9a259b52 3061 if (global.document) {
Osamu Nakamura 0:a40b9a259b52 3062 Request.requestsCount = 0;
Osamu Nakamura 0:a40b9a259b52 3063 Request.requests = {};
Osamu Nakamura 0:a40b9a259b52 3064 if (global.attachEvent) {
Osamu Nakamura 0:a40b9a259b52 3065 global.attachEvent('onunload', unloadHandler);
Osamu Nakamura 0:a40b9a259b52 3066 } else if (global.addEventListener) {
Osamu Nakamura 0:a40b9a259b52 3067 global.addEventListener('beforeunload', unloadHandler, false);
Osamu Nakamura 0:a40b9a259b52 3068 }
Osamu Nakamura 0:a40b9a259b52 3069 }
Osamu Nakamura 0:a40b9a259b52 3070
Osamu Nakamura 0:a40b9a259b52 3071 function unloadHandler() {
Osamu Nakamura 0:a40b9a259b52 3072 for (var i in Request.requests) {
Osamu Nakamura 0:a40b9a259b52 3073 if (Request.requests.hasOwnProperty(i)) {
Osamu Nakamura 0:a40b9a259b52 3074 Request.requests[i].abort();
Osamu Nakamura 0:a40b9a259b52 3075 }
Osamu Nakamura 0:a40b9a259b52 3076 }
Osamu Nakamura 0:a40b9a259b52 3077 }
Osamu Nakamura 0:a40b9a259b52 3078
Osamu Nakamura 0:a40b9a259b52 3079 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 3080 },{"./polling":18,"component-emitter":9,"component-inherit":21,"debug":22,"xmlhttprequest":20}],18:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3081 /**
Osamu Nakamura 0:a40b9a259b52 3082 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 3083 */
Osamu Nakamura 0:a40b9a259b52 3084
Osamu Nakamura 0:a40b9a259b52 3085 var Transport = _dereq_('../transport');
Osamu Nakamura 0:a40b9a259b52 3086 var parseqs = _dereq_('parseqs');
Osamu Nakamura 0:a40b9a259b52 3087 var parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 3088 var inherit = _dereq_('component-inherit');
Osamu Nakamura 0:a40b9a259b52 3089 var debug = _dereq_('debug')('engine.io-client:polling');
Osamu Nakamura 0:a40b9a259b52 3090
Osamu Nakamura 0:a40b9a259b52 3091 /**
Osamu Nakamura 0:a40b9a259b52 3092 * Module exports.
Osamu Nakamura 0:a40b9a259b52 3093 */
Osamu Nakamura 0:a40b9a259b52 3094
Osamu Nakamura 0:a40b9a259b52 3095 module.exports = Polling;
Osamu Nakamura 0:a40b9a259b52 3096
Osamu Nakamura 0:a40b9a259b52 3097 /**
Osamu Nakamura 0:a40b9a259b52 3098 * Is XHR2 supported?
Osamu Nakamura 0:a40b9a259b52 3099 */
Osamu Nakamura 0:a40b9a259b52 3100
Osamu Nakamura 0:a40b9a259b52 3101 var hasXHR2 = (function() {
Osamu Nakamura 0:a40b9a259b52 3102 var XMLHttpRequest = _dereq_('xmlhttprequest');
Osamu Nakamura 0:a40b9a259b52 3103 var xhr = new XMLHttpRequest({ xdomain: false });
Osamu Nakamura 0:a40b9a259b52 3104 return null != xhr.responseType;
Osamu Nakamura 0:a40b9a259b52 3105 })();
Osamu Nakamura 0:a40b9a259b52 3106
Osamu Nakamura 0:a40b9a259b52 3107 /**
Osamu Nakamura 0:a40b9a259b52 3108 * Polling interface.
Osamu Nakamura 0:a40b9a259b52 3109 *
Osamu Nakamura 0:a40b9a259b52 3110 * @param {Object} opts
Osamu Nakamura 0:a40b9a259b52 3111 * @api private
Osamu Nakamura 0:a40b9a259b52 3112 */
Osamu Nakamura 0:a40b9a259b52 3113
Osamu Nakamura 0:a40b9a259b52 3114 function Polling(opts){
Osamu Nakamura 0:a40b9a259b52 3115 var forceBase64 = (opts && opts.forceBase64);
Osamu Nakamura 0:a40b9a259b52 3116 if (!hasXHR2 || forceBase64) {
Osamu Nakamura 0:a40b9a259b52 3117 this.supportsBinary = false;
Osamu Nakamura 0:a40b9a259b52 3118 }
Osamu Nakamura 0:a40b9a259b52 3119 Transport.call(this, opts);
Osamu Nakamura 0:a40b9a259b52 3120 }
Osamu Nakamura 0:a40b9a259b52 3121
Osamu Nakamura 0:a40b9a259b52 3122 /**
Osamu Nakamura 0:a40b9a259b52 3123 * Inherits from Transport.
Osamu Nakamura 0:a40b9a259b52 3124 */
Osamu Nakamura 0:a40b9a259b52 3125
Osamu Nakamura 0:a40b9a259b52 3126 inherit(Polling, Transport);
Osamu Nakamura 0:a40b9a259b52 3127
Osamu Nakamura 0:a40b9a259b52 3128 /**
Osamu Nakamura 0:a40b9a259b52 3129 * Transport name.
Osamu Nakamura 0:a40b9a259b52 3130 */
Osamu Nakamura 0:a40b9a259b52 3131
Osamu Nakamura 0:a40b9a259b52 3132 Polling.prototype.name = 'polling';
Osamu Nakamura 0:a40b9a259b52 3133
Osamu Nakamura 0:a40b9a259b52 3134 /**
Osamu Nakamura 0:a40b9a259b52 3135 * Opens the socket (triggers polling). We write a PING message to determine
Osamu Nakamura 0:a40b9a259b52 3136 * when the transport is open.
Osamu Nakamura 0:a40b9a259b52 3137 *
Osamu Nakamura 0:a40b9a259b52 3138 * @api private
Osamu Nakamura 0:a40b9a259b52 3139 */
Osamu Nakamura 0:a40b9a259b52 3140
Osamu Nakamura 0:a40b9a259b52 3141 Polling.prototype.doOpen = function(){
Osamu Nakamura 0:a40b9a259b52 3142 this.poll();
Osamu Nakamura 0:a40b9a259b52 3143 };
Osamu Nakamura 0:a40b9a259b52 3144
Osamu Nakamura 0:a40b9a259b52 3145 /**
Osamu Nakamura 0:a40b9a259b52 3146 * Pauses polling.
Osamu Nakamura 0:a40b9a259b52 3147 *
Osamu Nakamura 0:a40b9a259b52 3148 * @param {Function} callback upon buffers are flushed and transport is paused
Osamu Nakamura 0:a40b9a259b52 3149 * @api private
Osamu Nakamura 0:a40b9a259b52 3150 */
Osamu Nakamura 0:a40b9a259b52 3151
Osamu Nakamura 0:a40b9a259b52 3152 Polling.prototype.pause = function(onPause){
Osamu Nakamura 0:a40b9a259b52 3153 var pending = 0;
Osamu Nakamura 0:a40b9a259b52 3154 var self = this;
Osamu Nakamura 0:a40b9a259b52 3155
Osamu Nakamura 0:a40b9a259b52 3156 this.readyState = 'pausing';
Osamu Nakamura 0:a40b9a259b52 3157
Osamu Nakamura 0:a40b9a259b52 3158 function pause(){
Osamu Nakamura 0:a40b9a259b52 3159 debug('paused');
Osamu Nakamura 0:a40b9a259b52 3160 self.readyState = 'paused';
Osamu Nakamura 0:a40b9a259b52 3161 onPause();
Osamu Nakamura 0:a40b9a259b52 3162 }
Osamu Nakamura 0:a40b9a259b52 3163
Osamu Nakamura 0:a40b9a259b52 3164 if (this.polling || !this.writable) {
Osamu Nakamura 0:a40b9a259b52 3165 var total = 0;
Osamu Nakamura 0:a40b9a259b52 3166
Osamu Nakamura 0:a40b9a259b52 3167 if (this.polling) {
Osamu Nakamura 0:a40b9a259b52 3168 debug('we are currently polling - waiting to pause');
Osamu Nakamura 0:a40b9a259b52 3169 total++;
Osamu Nakamura 0:a40b9a259b52 3170 this.once('pollComplete', function(){
Osamu Nakamura 0:a40b9a259b52 3171 debug('pre-pause polling complete');
Osamu Nakamura 0:a40b9a259b52 3172 --total || pause();
Osamu Nakamura 0:a40b9a259b52 3173 });
Osamu Nakamura 0:a40b9a259b52 3174 }
Osamu Nakamura 0:a40b9a259b52 3175
Osamu Nakamura 0:a40b9a259b52 3176 if (!this.writable) {
Osamu Nakamura 0:a40b9a259b52 3177 debug('we are currently writing - waiting to pause');
Osamu Nakamura 0:a40b9a259b52 3178 total++;
Osamu Nakamura 0:a40b9a259b52 3179 this.once('drain', function(){
Osamu Nakamura 0:a40b9a259b52 3180 debug('pre-pause writing complete');
Osamu Nakamura 0:a40b9a259b52 3181 --total || pause();
Osamu Nakamura 0:a40b9a259b52 3182 });
Osamu Nakamura 0:a40b9a259b52 3183 }
Osamu Nakamura 0:a40b9a259b52 3184 } else {
Osamu Nakamura 0:a40b9a259b52 3185 pause();
Osamu Nakamura 0:a40b9a259b52 3186 }
Osamu Nakamura 0:a40b9a259b52 3187 };
Osamu Nakamura 0:a40b9a259b52 3188
Osamu Nakamura 0:a40b9a259b52 3189 /**
Osamu Nakamura 0:a40b9a259b52 3190 * Starts polling cycle.
Osamu Nakamura 0:a40b9a259b52 3191 *
Osamu Nakamura 0:a40b9a259b52 3192 * @api public
Osamu Nakamura 0:a40b9a259b52 3193 */
Osamu Nakamura 0:a40b9a259b52 3194
Osamu Nakamura 0:a40b9a259b52 3195 Polling.prototype.poll = function(){
Osamu Nakamura 0:a40b9a259b52 3196 debug('polling');
Osamu Nakamura 0:a40b9a259b52 3197 this.polling = true;
Osamu Nakamura 0:a40b9a259b52 3198 this.doPoll();
Osamu Nakamura 0:a40b9a259b52 3199 this.emit('poll');
Osamu Nakamura 0:a40b9a259b52 3200 };
Osamu Nakamura 0:a40b9a259b52 3201
Osamu Nakamura 0:a40b9a259b52 3202 /**
Osamu Nakamura 0:a40b9a259b52 3203 * Overloads onData to detect payloads.
Osamu Nakamura 0:a40b9a259b52 3204 *
Osamu Nakamura 0:a40b9a259b52 3205 * @api private
Osamu Nakamura 0:a40b9a259b52 3206 */
Osamu Nakamura 0:a40b9a259b52 3207
Osamu Nakamura 0:a40b9a259b52 3208 Polling.prototype.onData = function(data){
Osamu Nakamura 0:a40b9a259b52 3209 var self = this;
Osamu Nakamura 0:a40b9a259b52 3210 debug('polling got data %s', data);
Osamu Nakamura 0:a40b9a259b52 3211 var callback = function(packet, index, total) {
Osamu Nakamura 0:a40b9a259b52 3212 // if its the first message we consider the transport open
Osamu Nakamura 0:a40b9a259b52 3213 if ('opening' == self.readyState) {
Osamu Nakamura 0:a40b9a259b52 3214 self.onOpen();
Osamu Nakamura 0:a40b9a259b52 3215 }
Osamu Nakamura 0:a40b9a259b52 3216
Osamu Nakamura 0:a40b9a259b52 3217 // if its a close packet, we close the ongoing requests
Osamu Nakamura 0:a40b9a259b52 3218 if ('close' == packet.type) {
Osamu Nakamura 0:a40b9a259b52 3219 self.onClose();
Osamu Nakamura 0:a40b9a259b52 3220 return false;
Osamu Nakamura 0:a40b9a259b52 3221 }
Osamu Nakamura 0:a40b9a259b52 3222
Osamu Nakamura 0:a40b9a259b52 3223 // otherwise bypass onData and handle the message
Osamu Nakamura 0:a40b9a259b52 3224 self.onPacket(packet);
Osamu Nakamura 0:a40b9a259b52 3225 };
Osamu Nakamura 0:a40b9a259b52 3226
Osamu Nakamura 0:a40b9a259b52 3227 // decode payload
Osamu Nakamura 0:a40b9a259b52 3228 parser.decodePayload(data, this.socket.binaryType, callback);
Osamu Nakamura 0:a40b9a259b52 3229
Osamu Nakamura 0:a40b9a259b52 3230 // if an event did not trigger closing
Osamu Nakamura 0:a40b9a259b52 3231 if ('closed' != this.readyState) {
Osamu Nakamura 0:a40b9a259b52 3232 // if we got data we're not polling
Osamu Nakamura 0:a40b9a259b52 3233 this.polling = false;
Osamu Nakamura 0:a40b9a259b52 3234 this.emit('pollComplete');
Osamu Nakamura 0:a40b9a259b52 3235
Osamu Nakamura 0:a40b9a259b52 3236 if ('open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 3237 this.poll();
Osamu Nakamura 0:a40b9a259b52 3238 } else {
Osamu Nakamura 0:a40b9a259b52 3239 debug('ignoring poll - transport state "%s"', this.readyState);
Osamu Nakamura 0:a40b9a259b52 3240 }
Osamu Nakamura 0:a40b9a259b52 3241 }
Osamu Nakamura 0:a40b9a259b52 3242 };
Osamu Nakamura 0:a40b9a259b52 3243
Osamu Nakamura 0:a40b9a259b52 3244 /**
Osamu Nakamura 0:a40b9a259b52 3245 * For polling, send a close packet.
Osamu Nakamura 0:a40b9a259b52 3246 *
Osamu Nakamura 0:a40b9a259b52 3247 * @api private
Osamu Nakamura 0:a40b9a259b52 3248 */
Osamu Nakamura 0:a40b9a259b52 3249
Osamu Nakamura 0:a40b9a259b52 3250 Polling.prototype.doClose = function(){
Osamu Nakamura 0:a40b9a259b52 3251 var self = this;
Osamu Nakamura 0:a40b9a259b52 3252
Osamu Nakamura 0:a40b9a259b52 3253 function close(){
Osamu Nakamura 0:a40b9a259b52 3254 debug('writing close packet');
Osamu Nakamura 0:a40b9a259b52 3255 self.write([{ type: 'close' }]);
Osamu Nakamura 0:a40b9a259b52 3256 }
Osamu Nakamura 0:a40b9a259b52 3257
Osamu Nakamura 0:a40b9a259b52 3258 if ('open' == this.readyState) {
Osamu Nakamura 0:a40b9a259b52 3259 debug('transport open - closing');
Osamu Nakamura 0:a40b9a259b52 3260 close();
Osamu Nakamura 0:a40b9a259b52 3261 } else {
Osamu Nakamura 0:a40b9a259b52 3262 // in case we're trying to close while
Osamu Nakamura 0:a40b9a259b52 3263 // handshaking is in progress (GH-164)
Osamu Nakamura 0:a40b9a259b52 3264 debug('transport not open - deferring close');
Osamu Nakamura 0:a40b9a259b52 3265 this.once('open', close);
Osamu Nakamura 0:a40b9a259b52 3266 }
Osamu Nakamura 0:a40b9a259b52 3267 };
Osamu Nakamura 0:a40b9a259b52 3268
Osamu Nakamura 0:a40b9a259b52 3269 /**
Osamu Nakamura 0:a40b9a259b52 3270 * Writes a packets payload.
Osamu Nakamura 0:a40b9a259b52 3271 *
Osamu Nakamura 0:a40b9a259b52 3272 * @param {Array} data packets
Osamu Nakamura 0:a40b9a259b52 3273 * @param {Function} drain callback
Osamu Nakamura 0:a40b9a259b52 3274 * @api private
Osamu Nakamura 0:a40b9a259b52 3275 */
Osamu Nakamura 0:a40b9a259b52 3276
Osamu Nakamura 0:a40b9a259b52 3277 Polling.prototype.write = function(packets){
Osamu Nakamura 0:a40b9a259b52 3278 var self = this;
Osamu Nakamura 0:a40b9a259b52 3279 this.writable = false;
Osamu Nakamura 0:a40b9a259b52 3280 var callbackfn = function() {
Osamu Nakamura 0:a40b9a259b52 3281 self.writable = true;
Osamu Nakamura 0:a40b9a259b52 3282 self.emit('drain');
Osamu Nakamura 0:a40b9a259b52 3283 };
Osamu Nakamura 0:a40b9a259b52 3284
Osamu Nakamura 0:a40b9a259b52 3285 var self = this;
Osamu Nakamura 0:a40b9a259b52 3286 parser.encodePayload(packets, this.supportsBinary, function(data) {
Osamu Nakamura 0:a40b9a259b52 3287 self.doWrite(data, callbackfn);
Osamu Nakamura 0:a40b9a259b52 3288 });
Osamu Nakamura 0:a40b9a259b52 3289 };
Osamu Nakamura 0:a40b9a259b52 3290
Osamu Nakamura 0:a40b9a259b52 3291 /**
Osamu Nakamura 0:a40b9a259b52 3292 * Generates uri for connection.
Osamu Nakamura 0:a40b9a259b52 3293 *
Osamu Nakamura 0:a40b9a259b52 3294 * @api private
Osamu Nakamura 0:a40b9a259b52 3295 */
Osamu Nakamura 0:a40b9a259b52 3296
Osamu Nakamura 0:a40b9a259b52 3297 Polling.prototype.uri = function(){
Osamu Nakamura 0:a40b9a259b52 3298 var query = this.query || {};
Osamu Nakamura 0:a40b9a259b52 3299 var schema = this.secure ? 'https' : 'http';
Osamu Nakamura 0:a40b9a259b52 3300 var port = '';
Osamu Nakamura 0:a40b9a259b52 3301
Osamu Nakamura 0:a40b9a259b52 3302 // cache busting is forced
Osamu Nakamura 0:a40b9a259b52 3303 if (false !== this.timestampRequests) {
Osamu Nakamura 0:a40b9a259b52 3304 query[this.timestampParam] = +new Date + '-' + Transport.timestamps++;
Osamu Nakamura 0:a40b9a259b52 3305 }
Osamu Nakamura 0:a40b9a259b52 3306
Osamu Nakamura 0:a40b9a259b52 3307 if (!this.supportsBinary && !query.sid) {
Osamu Nakamura 0:a40b9a259b52 3308 query.b64 = 1;
Osamu Nakamura 0:a40b9a259b52 3309 }
Osamu Nakamura 0:a40b9a259b52 3310
Osamu Nakamura 0:a40b9a259b52 3311 query = parseqs.encode(query);
Osamu Nakamura 0:a40b9a259b52 3312
Osamu Nakamura 0:a40b9a259b52 3313 // avoid port if default for schema
Osamu Nakamura 0:a40b9a259b52 3314 if (this.port && (('https' == schema && this.port != 443) ||
Osamu Nakamura 0:a40b9a259b52 3315 ('http' == schema && this.port != 80))) {
Osamu Nakamura 0:a40b9a259b52 3316 port = ':' + this.port;
Osamu Nakamura 0:a40b9a259b52 3317 }
Osamu Nakamura 0:a40b9a259b52 3318
Osamu Nakamura 0:a40b9a259b52 3319 // prepend ? to query
Osamu Nakamura 0:a40b9a259b52 3320 if (query.length) {
Osamu Nakamura 0:a40b9a259b52 3321 query = '?' + query;
Osamu Nakamura 0:a40b9a259b52 3322 }
Osamu Nakamura 0:a40b9a259b52 3323
Osamu Nakamura 0:a40b9a259b52 3324 return schema + '://' + this.hostname + port + this.path + query;
Osamu Nakamura 0:a40b9a259b52 3325 };
Osamu Nakamura 0:a40b9a259b52 3326
Osamu Nakamura 0:a40b9a259b52 3327 },{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"xmlhttprequest":20}],19:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3328 /**
Osamu Nakamura 0:a40b9a259b52 3329 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 3330 */
Osamu Nakamura 0:a40b9a259b52 3331
Osamu Nakamura 0:a40b9a259b52 3332 var Transport = _dereq_('../transport');
Osamu Nakamura 0:a40b9a259b52 3333 var parser = _dereq_('engine.io-parser');
Osamu Nakamura 0:a40b9a259b52 3334 var parseqs = _dereq_('parseqs');
Osamu Nakamura 0:a40b9a259b52 3335 var inherit = _dereq_('component-inherit');
Osamu Nakamura 0:a40b9a259b52 3336 var debug = _dereq_('debug')('engine.io-client:websocket');
Osamu Nakamura 0:a40b9a259b52 3337
Osamu Nakamura 0:a40b9a259b52 3338 /**
Osamu Nakamura 0:a40b9a259b52 3339 * `ws` exposes a WebSocket-compatible interface in
Osamu Nakamura 0:a40b9a259b52 3340 * Node, or the `WebSocket` or `MozWebSocket` globals
Osamu Nakamura 0:a40b9a259b52 3341 * in the browser.
Osamu Nakamura 0:a40b9a259b52 3342 */
Osamu Nakamura 0:a40b9a259b52 3343
Osamu Nakamura 0:a40b9a259b52 3344 var WebSocket = _dereq_('ws');
Osamu Nakamura 0:a40b9a259b52 3345
Osamu Nakamura 0:a40b9a259b52 3346 /**
Osamu Nakamura 0:a40b9a259b52 3347 * Module exports.
Osamu Nakamura 0:a40b9a259b52 3348 */
Osamu Nakamura 0:a40b9a259b52 3349
Osamu Nakamura 0:a40b9a259b52 3350 module.exports = WS;
Osamu Nakamura 0:a40b9a259b52 3351
Osamu Nakamura 0:a40b9a259b52 3352 /**
Osamu Nakamura 0:a40b9a259b52 3353 * WebSocket transport constructor.
Osamu Nakamura 0:a40b9a259b52 3354 *
Osamu Nakamura 0:a40b9a259b52 3355 * @api {Object} connection options
Osamu Nakamura 0:a40b9a259b52 3356 * @api public
Osamu Nakamura 0:a40b9a259b52 3357 */
Osamu Nakamura 0:a40b9a259b52 3358
Osamu Nakamura 0:a40b9a259b52 3359 function WS(opts){
Osamu Nakamura 0:a40b9a259b52 3360 var forceBase64 = (opts && opts.forceBase64);
Osamu Nakamura 0:a40b9a259b52 3361 if (forceBase64) {
Osamu Nakamura 0:a40b9a259b52 3362 this.supportsBinary = false;
Osamu Nakamura 0:a40b9a259b52 3363 }
Osamu Nakamura 0:a40b9a259b52 3364 Transport.call(this, opts);
Osamu Nakamura 0:a40b9a259b52 3365 }
Osamu Nakamura 0:a40b9a259b52 3366
Osamu Nakamura 0:a40b9a259b52 3367 /**
Osamu Nakamura 0:a40b9a259b52 3368 * Inherits from Transport.
Osamu Nakamura 0:a40b9a259b52 3369 */
Osamu Nakamura 0:a40b9a259b52 3370
Osamu Nakamura 0:a40b9a259b52 3371 inherit(WS, Transport);
Osamu Nakamura 0:a40b9a259b52 3372
Osamu Nakamura 0:a40b9a259b52 3373 /**
Osamu Nakamura 0:a40b9a259b52 3374 * Transport name.
Osamu Nakamura 0:a40b9a259b52 3375 *
Osamu Nakamura 0:a40b9a259b52 3376 * @api public
Osamu Nakamura 0:a40b9a259b52 3377 */
Osamu Nakamura 0:a40b9a259b52 3378
Osamu Nakamura 0:a40b9a259b52 3379 WS.prototype.name = 'websocket';
Osamu Nakamura 0:a40b9a259b52 3380
Osamu Nakamura 0:a40b9a259b52 3381 /*
Osamu Nakamura 0:a40b9a259b52 3382 * WebSockets support binary
Osamu Nakamura 0:a40b9a259b52 3383 */
Osamu Nakamura 0:a40b9a259b52 3384
Osamu Nakamura 0:a40b9a259b52 3385 WS.prototype.supportsBinary = true;
Osamu Nakamura 0:a40b9a259b52 3386
Osamu Nakamura 0:a40b9a259b52 3387 /**
Osamu Nakamura 0:a40b9a259b52 3388 * Opens socket.
Osamu Nakamura 0:a40b9a259b52 3389 *
Osamu Nakamura 0:a40b9a259b52 3390 * @api private
Osamu Nakamura 0:a40b9a259b52 3391 */
Osamu Nakamura 0:a40b9a259b52 3392
Osamu Nakamura 0:a40b9a259b52 3393 WS.prototype.doOpen = function(){
Osamu Nakamura 0:a40b9a259b52 3394 if (!this.check()) {
Osamu Nakamura 0:a40b9a259b52 3395 // let probe timeout
Osamu Nakamura 0:a40b9a259b52 3396 return;
Osamu Nakamura 0:a40b9a259b52 3397 }
Osamu Nakamura 0:a40b9a259b52 3398
Osamu Nakamura 0:a40b9a259b52 3399 var self = this;
Osamu Nakamura 0:a40b9a259b52 3400 var uri = this.uri();
Osamu Nakamura 0:a40b9a259b52 3401 var protocols = void(0);
Osamu Nakamura 0:a40b9a259b52 3402 var opts = { agent: this.agent };
Osamu Nakamura 0:a40b9a259b52 3403
Osamu Nakamura 0:a40b9a259b52 3404 // SSL options for Node.js client
Osamu Nakamura 0:a40b9a259b52 3405 opts.pfx = this.pfx;
Osamu Nakamura 0:a40b9a259b52 3406 opts.key = this.key;
Osamu Nakamura 0:a40b9a259b52 3407 opts.passphrase = this.passphrase;
Osamu Nakamura 0:a40b9a259b52 3408 opts.cert = this.cert;
Osamu Nakamura 0:a40b9a259b52 3409 opts.ca = this.ca;
Osamu Nakamura 0:a40b9a259b52 3410 opts.ciphers = this.ciphers;
Osamu Nakamura 0:a40b9a259b52 3411 opts.rejectUnauthorized = this.rejectUnauthorized;
Osamu Nakamura 0:a40b9a259b52 3412
Osamu Nakamura 0:a40b9a259b52 3413 this.ws = new WebSocket(uri, protocols, opts);
Osamu Nakamura 0:a40b9a259b52 3414
Osamu Nakamura 0:a40b9a259b52 3415 if (this.ws.binaryType === undefined) {
Osamu Nakamura 0:a40b9a259b52 3416 this.supportsBinary = false;
Osamu Nakamura 0:a40b9a259b52 3417 }
Osamu Nakamura 0:a40b9a259b52 3418
Osamu Nakamura 0:a40b9a259b52 3419 this.ws.binaryType = 'arraybuffer';
Osamu Nakamura 0:a40b9a259b52 3420 this.addEventListeners();
Osamu Nakamura 0:a40b9a259b52 3421 };
Osamu Nakamura 0:a40b9a259b52 3422
Osamu Nakamura 0:a40b9a259b52 3423 /**
Osamu Nakamura 0:a40b9a259b52 3424 * Adds event listeners to the socket
Osamu Nakamura 0:a40b9a259b52 3425 *
Osamu Nakamura 0:a40b9a259b52 3426 * @api private
Osamu Nakamura 0:a40b9a259b52 3427 */
Osamu Nakamura 0:a40b9a259b52 3428
Osamu Nakamura 0:a40b9a259b52 3429 WS.prototype.addEventListeners = function(){
Osamu Nakamura 0:a40b9a259b52 3430 var self = this;
Osamu Nakamura 0:a40b9a259b52 3431
Osamu Nakamura 0:a40b9a259b52 3432 this.ws.onopen = function(){
Osamu Nakamura 0:a40b9a259b52 3433 self.onOpen();
Osamu Nakamura 0:a40b9a259b52 3434 };
Osamu Nakamura 0:a40b9a259b52 3435 this.ws.onclose = function(){
Osamu Nakamura 0:a40b9a259b52 3436 self.onClose();
Osamu Nakamura 0:a40b9a259b52 3437 };
Osamu Nakamura 0:a40b9a259b52 3438 this.ws.onmessage = function(ev){
Osamu Nakamura 0:a40b9a259b52 3439 self.onData(ev.data);
Osamu Nakamura 0:a40b9a259b52 3440 };
Osamu Nakamura 0:a40b9a259b52 3441 this.ws.onerror = function(e){
Osamu Nakamura 0:a40b9a259b52 3442 self.onError('websocket error', e);
Osamu Nakamura 0:a40b9a259b52 3443 };
Osamu Nakamura 0:a40b9a259b52 3444 };
Osamu Nakamura 0:a40b9a259b52 3445
Osamu Nakamura 0:a40b9a259b52 3446 /**
Osamu Nakamura 0:a40b9a259b52 3447 * Override `onData` to use a timer on iOS.
Osamu Nakamura 0:a40b9a259b52 3448 * See: https://gist.github.com/mloughran/2052006
Osamu Nakamura 0:a40b9a259b52 3449 *
Osamu Nakamura 0:a40b9a259b52 3450 * @api private
Osamu Nakamura 0:a40b9a259b52 3451 */
Osamu Nakamura 0:a40b9a259b52 3452
Osamu Nakamura 0:a40b9a259b52 3453 if ('undefined' != typeof navigator
Osamu Nakamura 0:a40b9a259b52 3454 && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
Osamu Nakamura 0:a40b9a259b52 3455 WS.prototype.onData = function(data){
Osamu Nakamura 0:a40b9a259b52 3456 var self = this;
Osamu Nakamura 0:a40b9a259b52 3457 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 3458 Transport.prototype.onData.call(self, data);
Osamu Nakamura 0:a40b9a259b52 3459 }, 0);
Osamu Nakamura 0:a40b9a259b52 3460 };
Osamu Nakamura 0:a40b9a259b52 3461 }
Osamu Nakamura 0:a40b9a259b52 3462
Osamu Nakamura 0:a40b9a259b52 3463 /**
Osamu Nakamura 0:a40b9a259b52 3464 * Writes data to socket.
Osamu Nakamura 0:a40b9a259b52 3465 *
Osamu Nakamura 0:a40b9a259b52 3466 * @param {Array} array of packets.
Osamu Nakamura 0:a40b9a259b52 3467 * @api private
Osamu Nakamura 0:a40b9a259b52 3468 */
Osamu Nakamura 0:a40b9a259b52 3469
Osamu Nakamura 0:a40b9a259b52 3470 WS.prototype.write = function(packets){
Osamu Nakamura 0:a40b9a259b52 3471 var self = this;
Osamu Nakamura 0:a40b9a259b52 3472 this.writable = false;
Osamu Nakamura 0:a40b9a259b52 3473 // encodePacket efficient as it uses WS framing
Osamu Nakamura 0:a40b9a259b52 3474 // no need for encodePayload
Osamu Nakamura 0:a40b9a259b52 3475 for (var i = 0, l = packets.length; i < l; i++) {
Osamu Nakamura 0:a40b9a259b52 3476 parser.encodePacket(packets[i], this.supportsBinary, function(data) {
Osamu Nakamura 0:a40b9a259b52 3477 //Sometimes the websocket has already been closed but the browser didn't
Osamu Nakamura 0:a40b9a259b52 3478 //have a chance of informing us about it yet, in that case send will
Osamu Nakamura 0:a40b9a259b52 3479 //throw an error
Osamu Nakamura 0:a40b9a259b52 3480 try {
Osamu Nakamura 0:a40b9a259b52 3481 self.ws.send(data);
Osamu Nakamura 0:a40b9a259b52 3482 } catch (e){
Osamu Nakamura 0:a40b9a259b52 3483 debug('websocket closed before onclose event');
Osamu Nakamura 0:a40b9a259b52 3484 }
Osamu Nakamura 0:a40b9a259b52 3485 });
Osamu Nakamura 0:a40b9a259b52 3486 }
Osamu Nakamura 0:a40b9a259b52 3487
Osamu Nakamura 0:a40b9a259b52 3488 function ondrain() {
Osamu Nakamura 0:a40b9a259b52 3489 self.writable = true;
Osamu Nakamura 0:a40b9a259b52 3490 self.emit('drain');
Osamu Nakamura 0:a40b9a259b52 3491 }
Osamu Nakamura 0:a40b9a259b52 3492 // fake drain
Osamu Nakamura 0:a40b9a259b52 3493 // defer to next tick to allow Socket to clear writeBuffer
Osamu Nakamura 0:a40b9a259b52 3494 setTimeout(ondrain, 0);
Osamu Nakamura 0:a40b9a259b52 3495 };
Osamu Nakamura 0:a40b9a259b52 3496
Osamu Nakamura 0:a40b9a259b52 3497 /**
Osamu Nakamura 0:a40b9a259b52 3498 * Called upon close
Osamu Nakamura 0:a40b9a259b52 3499 *
Osamu Nakamura 0:a40b9a259b52 3500 * @api private
Osamu Nakamura 0:a40b9a259b52 3501 */
Osamu Nakamura 0:a40b9a259b52 3502
Osamu Nakamura 0:a40b9a259b52 3503 WS.prototype.onClose = function(){
Osamu Nakamura 0:a40b9a259b52 3504 Transport.prototype.onClose.call(this);
Osamu Nakamura 0:a40b9a259b52 3505 };
Osamu Nakamura 0:a40b9a259b52 3506
Osamu Nakamura 0:a40b9a259b52 3507 /**
Osamu Nakamura 0:a40b9a259b52 3508 * Closes socket.
Osamu Nakamura 0:a40b9a259b52 3509 *
Osamu Nakamura 0:a40b9a259b52 3510 * @api private
Osamu Nakamura 0:a40b9a259b52 3511 */
Osamu Nakamura 0:a40b9a259b52 3512
Osamu Nakamura 0:a40b9a259b52 3513 WS.prototype.doClose = function(){
Osamu Nakamura 0:a40b9a259b52 3514 if (typeof this.ws !== 'undefined') {
Osamu Nakamura 0:a40b9a259b52 3515 this.ws.close();
Osamu Nakamura 0:a40b9a259b52 3516 }
Osamu Nakamura 0:a40b9a259b52 3517 };
Osamu Nakamura 0:a40b9a259b52 3518
Osamu Nakamura 0:a40b9a259b52 3519 /**
Osamu Nakamura 0:a40b9a259b52 3520 * Generates uri for connection.
Osamu Nakamura 0:a40b9a259b52 3521 *
Osamu Nakamura 0:a40b9a259b52 3522 * @api private
Osamu Nakamura 0:a40b9a259b52 3523 */
Osamu Nakamura 0:a40b9a259b52 3524
Osamu Nakamura 0:a40b9a259b52 3525 WS.prototype.uri = function(){
Osamu Nakamura 0:a40b9a259b52 3526 var query = this.query || {};
Osamu Nakamura 0:a40b9a259b52 3527 var schema = this.secure ? 'wss' : 'ws';
Osamu Nakamura 0:a40b9a259b52 3528 var port = '';
Osamu Nakamura 0:a40b9a259b52 3529
Osamu Nakamura 0:a40b9a259b52 3530 // avoid port if default for schema
Osamu Nakamura 0:a40b9a259b52 3531 if (this.port && (('wss' == schema && this.port != 443)
Osamu Nakamura 0:a40b9a259b52 3532 || ('ws' == schema && this.port != 80))) {
Osamu Nakamura 0:a40b9a259b52 3533 port = ':' + this.port;
Osamu Nakamura 0:a40b9a259b52 3534 }
Osamu Nakamura 0:a40b9a259b52 3535
Osamu Nakamura 0:a40b9a259b52 3536 // append timestamp to URI
Osamu Nakamura 0:a40b9a259b52 3537 if (this.timestampRequests) {
Osamu Nakamura 0:a40b9a259b52 3538 query[this.timestampParam] = +new Date;
Osamu Nakamura 0:a40b9a259b52 3539 }
Osamu Nakamura 0:a40b9a259b52 3540
Osamu Nakamura 0:a40b9a259b52 3541 // communicate binary support capabilities
Osamu Nakamura 0:a40b9a259b52 3542 if (!this.supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 3543 query.b64 = 1;
Osamu Nakamura 0:a40b9a259b52 3544 }
Osamu Nakamura 0:a40b9a259b52 3545
Osamu Nakamura 0:a40b9a259b52 3546 query = parseqs.encode(query);
Osamu Nakamura 0:a40b9a259b52 3547
Osamu Nakamura 0:a40b9a259b52 3548 // prepend ? to query
Osamu Nakamura 0:a40b9a259b52 3549 if (query.length) {
Osamu Nakamura 0:a40b9a259b52 3550 query = '?' + query;
Osamu Nakamura 0:a40b9a259b52 3551 }
Osamu Nakamura 0:a40b9a259b52 3552
Osamu Nakamura 0:a40b9a259b52 3553 return schema + '://' + this.hostname + port + this.path + query;
Osamu Nakamura 0:a40b9a259b52 3554 };
Osamu Nakamura 0:a40b9a259b52 3555
Osamu Nakamura 0:a40b9a259b52 3556 /**
Osamu Nakamura 0:a40b9a259b52 3557 * Feature detection for WebSocket.
Osamu Nakamura 0:a40b9a259b52 3558 *
Osamu Nakamura 0:a40b9a259b52 3559 * @return {Boolean} whether this transport is available.
Osamu Nakamura 0:a40b9a259b52 3560 * @api public
Osamu Nakamura 0:a40b9a259b52 3561 */
Osamu Nakamura 0:a40b9a259b52 3562
Osamu Nakamura 0:a40b9a259b52 3563 WS.prototype.check = function(){
Osamu Nakamura 0:a40b9a259b52 3564 return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
Osamu Nakamura 0:a40b9a259b52 3565 };
Osamu Nakamura 0:a40b9a259b52 3566
Osamu Nakamura 0:a40b9a259b52 3567 },{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"ws":37}],20:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3568 // browser shim for xmlhttprequest module
Osamu Nakamura 0:a40b9a259b52 3569 var hasCORS = _dereq_('has-cors');
Osamu Nakamura 0:a40b9a259b52 3570
Osamu Nakamura 0:a40b9a259b52 3571 module.exports = function(opts) {
Osamu Nakamura 0:a40b9a259b52 3572 var xdomain = opts.xdomain;
Osamu Nakamura 0:a40b9a259b52 3573
Osamu Nakamura 0:a40b9a259b52 3574 // scheme must be same when usign XDomainRequest
Osamu Nakamura 0:a40b9a259b52 3575 // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
Osamu Nakamura 0:a40b9a259b52 3576 var xscheme = opts.xscheme;
Osamu Nakamura 0:a40b9a259b52 3577
Osamu Nakamura 0:a40b9a259b52 3578 // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
Osamu Nakamura 0:a40b9a259b52 3579 // https://github.com/Automattic/engine.io-client/pull/217
Osamu Nakamura 0:a40b9a259b52 3580 var enablesXDR = opts.enablesXDR;
Osamu Nakamura 0:a40b9a259b52 3581
Osamu Nakamura 0:a40b9a259b52 3582 // XMLHttpRequest can be disabled on IE
Osamu Nakamura 0:a40b9a259b52 3583 try {
Osamu Nakamura 0:a40b9a259b52 3584 if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) {
Osamu Nakamura 0:a40b9a259b52 3585 return new XMLHttpRequest();
Osamu Nakamura 0:a40b9a259b52 3586 }
Osamu Nakamura 0:a40b9a259b52 3587 } catch (e) { }
Osamu Nakamura 0:a40b9a259b52 3588
Osamu Nakamura 0:a40b9a259b52 3589 // Use XDomainRequest for IE8 if enablesXDR is true
Osamu Nakamura 0:a40b9a259b52 3590 // because loading bar keeps flashing when using jsonp-polling
Osamu Nakamura 0:a40b9a259b52 3591 // https://github.com/yujiosaka/socke.io-ie8-loading-example
Osamu Nakamura 0:a40b9a259b52 3592 try {
Osamu Nakamura 0:a40b9a259b52 3593 if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) {
Osamu Nakamura 0:a40b9a259b52 3594 return new XDomainRequest();
Osamu Nakamura 0:a40b9a259b52 3595 }
Osamu Nakamura 0:a40b9a259b52 3596 } catch (e) { }
Osamu Nakamura 0:a40b9a259b52 3597
Osamu Nakamura 0:a40b9a259b52 3598 if (!xdomain) {
Osamu Nakamura 0:a40b9a259b52 3599 try {
Osamu Nakamura 0:a40b9a259b52 3600 return new ActiveXObject('Microsoft.XMLHTTP');
Osamu Nakamura 0:a40b9a259b52 3601 } catch(e) { }
Osamu Nakamura 0:a40b9a259b52 3602 }
Osamu Nakamura 0:a40b9a259b52 3603 }
Osamu Nakamura 0:a40b9a259b52 3604
Osamu Nakamura 0:a40b9a259b52 3605 },{"has-cors":40}],21:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3606
Osamu Nakamura 0:a40b9a259b52 3607 module.exports = function(a, b){
Osamu Nakamura 0:a40b9a259b52 3608 var fn = function(){};
Osamu Nakamura 0:a40b9a259b52 3609 fn.prototype = b.prototype;
Osamu Nakamura 0:a40b9a259b52 3610 a.prototype = new fn;
Osamu Nakamura 0:a40b9a259b52 3611 a.prototype.constructor = a;
Osamu Nakamura 0:a40b9a259b52 3612 };
Osamu Nakamura 0:a40b9a259b52 3613 },{}],22:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3614
Osamu Nakamura 0:a40b9a259b52 3615 /**
Osamu Nakamura 0:a40b9a259b52 3616 * This is the web browser implementation of `debug()`.
Osamu Nakamura 0:a40b9a259b52 3617 *
Osamu Nakamura 0:a40b9a259b52 3618 * Expose `debug()` as the module.
Osamu Nakamura 0:a40b9a259b52 3619 */
Osamu Nakamura 0:a40b9a259b52 3620
Osamu Nakamura 0:a40b9a259b52 3621 exports = module.exports = _dereq_('./debug');
Osamu Nakamura 0:a40b9a259b52 3622 exports.log = log;
Osamu Nakamura 0:a40b9a259b52 3623 exports.formatArgs = formatArgs;
Osamu Nakamura 0:a40b9a259b52 3624 exports.save = save;
Osamu Nakamura 0:a40b9a259b52 3625 exports.load = load;
Osamu Nakamura 0:a40b9a259b52 3626 exports.useColors = useColors;
Osamu Nakamura 0:a40b9a259b52 3627
Osamu Nakamura 0:a40b9a259b52 3628 /**
Osamu Nakamura 0:a40b9a259b52 3629 * Colors.
Osamu Nakamura 0:a40b9a259b52 3630 */
Osamu Nakamura 0:a40b9a259b52 3631
Osamu Nakamura 0:a40b9a259b52 3632 exports.colors = [
Osamu Nakamura 0:a40b9a259b52 3633 'lightseagreen',
Osamu Nakamura 0:a40b9a259b52 3634 'forestgreen',
Osamu Nakamura 0:a40b9a259b52 3635 'goldenrod',
Osamu Nakamura 0:a40b9a259b52 3636 'dodgerblue',
Osamu Nakamura 0:a40b9a259b52 3637 'darkorchid',
Osamu Nakamura 0:a40b9a259b52 3638 'crimson'
Osamu Nakamura 0:a40b9a259b52 3639 ];
Osamu Nakamura 0:a40b9a259b52 3640
Osamu Nakamura 0:a40b9a259b52 3641 /**
Osamu Nakamura 0:a40b9a259b52 3642 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
Osamu Nakamura 0:a40b9a259b52 3643 * and the Firebug extension (any Firefox version) are known
Osamu Nakamura 0:a40b9a259b52 3644 * to support "%c" CSS customizations.
Osamu Nakamura 0:a40b9a259b52 3645 *
Osamu Nakamura 0:a40b9a259b52 3646 * TODO: add a `localStorage` variable to explicitly enable/disable colors
Osamu Nakamura 0:a40b9a259b52 3647 */
Osamu Nakamura 0:a40b9a259b52 3648
Osamu Nakamura 0:a40b9a259b52 3649 function useColors() {
Osamu Nakamura 0:a40b9a259b52 3650 // is webkit? http://stackoverflow.com/a/16459606/376773
Osamu Nakamura 0:a40b9a259b52 3651 return ('WebkitAppearance' in document.documentElement.style) ||
Osamu Nakamura 0:a40b9a259b52 3652 // is firebug? http://stackoverflow.com/a/398120/376773
Osamu Nakamura 0:a40b9a259b52 3653 (window.console && (console.firebug || (console.exception && console.table))) ||
Osamu Nakamura 0:a40b9a259b52 3654 // is firefox >= v31?
Osamu Nakamura 0:a40b9a259b52 3655 // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
Osamu Nakamura 0:a40b9a259b52 3656 (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
Osamu Nakamura 0:a40b9a259b52 3657 }
Osamu Nakamura 0:a40b9a259b52 3658
Osamu Nakamura 0:a40b9a259b52 3659 /**
Osamu Nakamura 0:a40b9a259b52 3660 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
Osamu Nakamura 0:a40b9a259b52 3661 */
Osamu Nakamura 0:a40b9a259b52 3662
Osamu Nakamura 0:a40b9a259b52 3663 exports.formatters.j = function(v) {
Osamu Nakamura 0:a40b9a259b52 3664 return JSON.stringify(v);
Osamu Nakamura 0:a40b9a259b52 3665 };
Osamu Nakamura 0:a40b9a259b52 3666
Osamu Nakamura 0:a40b9a259b52 3667
Osamu Nakamura 0:a40b9a259b52 3668 /**
Osamu Nakamura 0:a40b9a259b52 3669 * Colorize log arguments if enabled.
Osamu Nakamura 0:a40b9a259b52 3670 *
Osamu Nakamura 0:a40b9a259b52 3671 * @api public
Osamu Nakamura 0:a40b9a259b52 3672 */
Osamu Nakamura 0:a40b9a259b52 3673
Osamu Nakamura 0:a40b9a259b52 3674 function formatArgs() {
Osamu Nakamura 0:a40b9a259b52 3675 var args = arguments;
Osamu Nakamura 0:a40b9a259b52 3676 var useColors = this.useColors;
Osamu Nakamura 0:a40b9a259b52 3677
Osamu Nakamura 0:a40b9a259b52 3678 args[0] = (useColors ? '%c' : '')
Osamu Nakamura 0:a40b9a259b52 3679 + this.namespace
Osamu Nakamura 0:a40b9a259b52 3680 + (useColors ? ' %c' : ' ')
Osamu Nakamura 0:a40b9a259b52 3681 + args[0]
Osamu Nakamura 0:a40b9a259b52 3682 + (useColors ? '%c ' : ' ')
Osamu Nakamura 0:a40b9a259b52 3683 + '+' + exports.humanize(this.diff);
Osamu Nakamura 0:a40b9a259b52 3684
Osamu Nakamura 0:a40b9a259b52 3685 if (!useColors) return args;
Osamu Nakamura 0:a40b9a259b52 3686
Osamu Nakamura 0:a40b9a259b52 3687 var c = 'color: ' + this.color;
Osamu Nakamura 0:a40b9a259b52 3688 args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
Osamu Nakamura 0:a40b9a259b52 3689
Osamu Nakamura 0:a40b9a259b52 3690 // the final "%c" is somewhat tricky, because there could be other
Osamu Nakamura 0:a40b9a259b52 3691 // arguments passed either before or after the %c, so we need to
Osamu Nakamura 0:a40b9a259b52 3692 // figure out the correct index to insert the CSS into
Osamu Nakamura 0:a40b9a259b52 3693 var index = 0;
Osamu Nakamura 0:a40b9a259b52 3694 var lastC = 0;
Osamu Nakamura 0:a40b9a259b52 3695 args[0].replace(/%[a-z%]/g, function(match) {
Osamu Nakamura 0:a40b9a259b52 3696 if ('%' === match) return;
Osamu Nakamura 0:a40b9a259b52 3697 index++;
Osamu Nakamura 0:a40b9a259b52 3698 if ('%c' === match) {
Osamu Nakamura 0:a40b9a259b52 3699 // we only are interested in the *last* %c
Osamu Nakamura 0:a40b9a259b52 3700 // (the user may have provided their own)
Osamu Nakamura 0:a40b9a259b52 3701 lastC = index;
Osamu Nakamura 0:a40b9a259b52 3702 }
Osamu Nakamura 0:a40b9a259b52 3703 });
Osamu Nakamura 0:a40b9a259b52 3704
Osamu Nakamura 0:a40b9a259b52 3705 args.splice(lastC, 0, c);
Osamu Nakamura 0:a40b9a259b52 3706 return args;
Osamu Nakamura 0:a40b9a259b52 3707 }
Osamu Nakamura 0:a40b9a259b52 3708
Osamu Nakamura 0:a40b9a259b52 3709 /**
Osamu Nakamura 0:a40b9a259b52 3710 * Invokes `console.log()` when available.
Osamu Nakamura 0:a40b9a259b52 3711 * No-op when `console.log` is not a "function".
Osamu Nakamura 0:a40b9a259b52 3712 *
Osamu Nakamura 0:a40b9a259b52 3713 * @api public
Osamu Nakamura 0:a40b9a259b52 3714 */
Osamu Nakamura 0:a40b9a259b52 3715
Osamu Nakamura 0:a40b9a259b52 3716 function log() {
Osamu Nakamura 0:a40b9a259b52 3717 // This hackery is required for IE8,
Osamu Nakamura 0:a40b9a259b52 3718 // where the `console.log` function doesn't have 'apply'
Osamu Nakamura 0:a40b9a259b52 3719 return 'object' == typeof console
Osamu Nakamura 0:a40b9a259b52 3720 && 'function' == typeof console.log
Osamu Nakamura 0:a40b9a259b52 3721 && Function.prototype.apply.call(console.log, console, arguments);
Osamu Nakamura 0:a40b9a259b52 3722 }
Osamu Nakamura 0:a40b9a259b52 3723
Osamu Nakamura 0:a40b9a259b52 3724 /**
Osamu Nakamura 0:a40b9a259b52 3725 * Save `namespaces`.
Osamu Nakamura 0:a40b9a259b52 3726 *
Osamu Nakamura 0:a40b9a259b52 3727 * @param {String} namespaces
Osamu Nakamura 0:a40b9a259b52 3728 * @api private
Osamu Nakamura 0:a40b9a259b52 3729 */
Osamu Nakamura 0:a40b9a259b52 3730
Osamu Nakamura 0:a40b9a259b52 3731 function save(namespaces) {
Osamu Nakamura 0:a40b9a259b52 3732 try {
Osamu Nakamura 0:a40b9a259b52 3733 if (null == namespaces) {
Osamu Nakamura 0:a40b9a259b52 3734 localStorage.removeItem('debug');
Osamu Nakamura 0:a40b9a259b52 3735 } else {
Osamu Nakamura 0:a40b9a259b52 3736 localStorage.debug = namespaces;
Osamu Nakamura 0:a40b9a259b52 3737 }
Osamu Nakamura 0:a40b9a259b52 3738 } catch(e) {}
Osamu Nakamura 0:a40b9a259b52 3739 }
Osamu Nakamura 0:a40b9a259b52 3740
Osamu Nakamura 0:a40b9a259b52 3741 /**
Osamu Nakamura 0:a40b9a259b52 3742 * Load `namespaces`.
Osamu Nakamura 0:a40b9a259b52 3743 *
Osamu Nakamura 0:a40b9a259b52 3744 * @return {String} returns the previously persisted debug modes
Osamu Nakamura 0:a40b9a259b52 3745 * @api private
Osamu Nakamura 0:a40b9a259b52 3746 */
Osamu Nakamura 0:a40b9a259b52 3747
Osamu Nakamura 0:a40b9a259b52 3748 function load() {
Osamu Nakamura 0:a40b9a259b52 3749 var r;
Osamu Nakamura 0:a40b9a259b52 3750 try {
Osamu Nakamura 0:a40b9a259b52 3751 r = localStorage.debug;
Osamu Nakamura 0:a40b9a259b52 3752 } catch(e) {}
Osamu Nakamura 0:a40b9a259b52 3753 return r;
Osamu Nakamura 0:a40b9a259b52 3754 }
Osamu Nakamura 0:a40b9a259b52 3755
Osamu Nakamura 0:a40b9a259b52 3756 /**
Osamu Nakamura 0:a40b9a259b52 3757 * Enable namespaces listed in `localStorage.debug` initially.
Osamu Nakamura 0:a40b9a259b52 3758 */
Osamu Nakamura 0:a40b9a259b52 3759
Osamu Nakamura 0:a40b9a259b52 3760 exports.enable(load());
Osamu Nakamura 0:a40b9a259b52 3761
Osamu Nakamura 0:a40b9a259b52 3762 },{"./debug":23}],23:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3763
Osamu Nakamura 0:a40b9a259b52 3764 /**
Osamu Nakamura 0:a40b9a259b52 3765 * This is the common logic for both the Node.js and web browser
Osamu Nakamura 0:a40b9a259b52 3766 * implementations of `debug()`.
Osamu Nakamura 0:a40b9a259b52 3767 *
Osamu Nakamura 0:a40b9a259b52 3768 * Expose `debug()` as the module.
Osamu Nakamura 0:a40b9a259b52 3769 */
Osamu Nakamura 0:a40b9a259b52 3770
Osamu Nakamura 0:a40b9a259b52 3771 exports = module.exports = debug;
Osamu Nakamura 0:a40b9a259b52 3772 exports.coerce = coerce;
Osamu Nakamura 0:a40b9a259b52 3773 exports.disable = disable;
Osamu Nakamura 0:a40b9a259b52 3774 exports.enable = enable;
Osamu Nakamura 0:a40b9a259b52 3775 exports.enabled = enabled;
Osamu Nakamura 0:a40b9a259b52 3776 exports.humanize = _dereq_('ms');
Osamu Nakamura 0:a40b9a259b52 3777
Osamu Nakamura 0:a40b9a259b52 3778 /**
Osamu Nakamura 0:a40b9a259b52 3779 * The currently active debug mode names, and names to skip.
Osamu Nakamura 0:a40b9a259b52 3780 */
Osamu Nakamura 0:a40b9a259b52 3781
Osamu Nakamura 0:a40b9a259b52 3782 exports.names = [];
Osamu Nakamura 0:a40b9a259b52 3783 exports.skips = [];
Osamu Nakamura 0:a40b9a259b52 3784
Osamu Nakamura 0:a40b9a259b52 3785 /**
Osamu Nakamura 0:a40b9a259b52 3786 * Map of special "%n" handling functions, for the debug "format" argument.
Osamu Nakamura 0:a40b9a259b52 3787 *
Osamu Nakamura 0:a40b9a259b52 3788 * Valid key names are a single, lowercased letter, i.e. "n".
Osamu Nakamura 0:a40b9a259b52 3789 */
Osamu Nakamura 0:a40b9a259b52 3790
Osamu Nakamura 0:a40b9a259b52 3791 exports.formatters = {};
Osamu Nakamura 0:a40b9a259b52 3792
Osamu Nakamura 0:a40b9a259b52 3793 /**
Osamu Nakamura 0:a40b9a259b52 3794 * Previously assigned color.
Osamu Nakamura 0:a40b9a259b52 3795 */
Osamu Nakamura 0:a40b9a259b52 3796
Osamu Nakamura 0:a40b9a259b52 3797 var prevColor = 0;
Osamu Nakamura 0:a40b9a259b52 3798
Osamu Nakamura 0:a40b9a259b52 3799 /**
Osamu Nakamura 0:a40b9a259b52 3800 * Previous log timestamp.
Osamu Nakamura 0:a40b9a259b52 3801 */
Osamu Nakamura 0:a40b9a259b52 3802
Osamu Nakamura 0:a40b9a259b52 3803 var prevTime;
Osamu Nakamura 0:a40b9a259b52 3804
Osamu Nakamura 0:a40b9a259b52 3805 /**
Osamu Nakamura 0:a40b9a259b52 3806 * Select a color.
Osamu Nakamura 0:a40b9a259b52 3807 *
Osamu Nakamura 0:a40b9a259b52 3808 * @return {Number}
Osamu Nakamura 0:a40b9a259b52 3809 * @api private
Osamu Nakamura 0:a40b9a259b52 3810 */
Osamu Nakamura 0:a40b9a259b52 3811
Osamu Nakamura 0:a40b9a259b52 3812 function selectColor() {
Osamu Nakamura 0:a40b9a259b52 3813 return exports.colors[prevColor++ % exports.colors.length];
Osamu Nakamura 0:a40b9a259b52 3814 }
Osamu Nakamura 0:a40b9a259b52 3815
Osamu Nakamura 0:a40b9a259b52 3816 /**
Osamu Nakamura 0:a40b9a259b52 3817 * Create a debugger with the given `namespace`.
Osamu Nakamura 0:a40b9a259b52 3818 *
Osamu Nakamura 0:a40b9a259b52 3819 * @param {String} namespace
Osamu Nakamura 0:a40b9a259b52 3820 * @return {Function}
Osamu Nakamura 0:a40b9a259b52 3821 * @api public
Osamu Nakamura 0:a40b9a259b52 3822 */
Osamu Nakamura 0:a40b9a259b52 3823
Osamu Nakamura 0:a40b9a259b52 3824 function debug(namespace) {
Osamu Nakamura 0:a40b9a259b52 3825
Osamu Nakamura 0:a40b9a259b52 3826 // define the `disabled` version
Osamu Nakamura 0:a40b9a259b52 3827 function disabled() {
Osamu Nakamura 0:a40b9a259b52 3828 }
Osamu Nakamura 0:a40b9a259b52 3829 disabled.enabled = false;
Osamu Nakamura 0:a40b9a259b52 3830
Osamu Nakamura 0:a40b9a259b52 3831 // define the `enabled` version
Osamu Nakamura 0:a40b9a259b52 3832 function enabled() {
Osamu Nakamura 0:a40b9a259b52 3833
Osamu Nakamura 0:a40b9a259b52 3834 var self = enabled;
Osamu Nakamura 0:a40b9a259b52 3835
Osamu Nakamura 0:a40b9a259b52 3836 // set `diff` timestamp
Osamu Nakamura 0:a40b9a259b52 3837 var curr = +new Date();
Osamu Nakamura 0:a40b9a259b52 3838 var ms = curr - (prevTime || curr);
Osamu Nakamura 0:a40b9a259b52 3839 self.diff = ms;
Osamu Nakamura 0:a40b9a259b52 3840 self.prev = prevTime;
Osamu Nakamura 0:a40b9a259b52 3841 self.curr = curr;
Osamu Nakamura 0:a40b9a259b52 3842 prevTime = curr;
Osamu Nakamura 0:a40b9a259b52 3843
Osamu Nakamura 0:a40b9a259b52 3844 // add the `color` if not set
Osamu Nakamura 0:a40b9a259b52 3845 if (null == self.useColors) self.useColors = exports.useColors();
Osamu Nakamura 0:a40b9a259b52 3846 if (null == self.color && self.useColors) self.color = selectColor();
Osamu Nakamura 0:a40b9a259b52 3847
Osamu Nakamura 0:a40b9a259b52 3848 var args = Array.prototype.slice.call(arguments);
Osamu Nakamura 0:a40b9a259b52 3849
Osamu Nakamura 0:a40b9a259b52 3850 args[0] = exports.coerce(args[0]);
Osamu Nakamura 0:a40b9a259b52 3851
Osamu Nakamura 0:a40b9a259b52 3852 if ('string' !== typeof args[0]) {
Osamu Nakamura 0:a40b9a259b52 3853 // anything else let's inspect with %o
Osamu Nakamura 0:a40b9a259b52 3854 args = ['%o'].concat(args);
Osamu Nakamura 0:a40b9a259b52 3855 }
Osamu Nakamura 0:a40b9a259b52 3856
Osamu Nakamura 0:a40b9a259b52 3857 // apply any `formatters` transformations
Osamu Nakamura 0:a40b9a259b52 3858 var index = 0;
Osamu Nakamura 0:a40b9a259b52 3859 args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
Osamu Nakamura 0:a40b9a259b52 3860 // if we encounter an escaped % then don't increase the array index
Osamu Nakamura 0:a40b9a259b52 3861 if (match === '%') return match;
Osamu Nakamura 0:a40b9a259b52 3862 index++;
Osamu Nakamura 0:a40b9a259b52 3863 var formatter = exports.formatters[format];
Osamu Nakamura 0:a40b9a259b52 3864 if ('function' === typeof formatter) {
Osamu Nakamura 0:a40b9a259b52 3865 var val = args[index];
Osamu Nakamura 0:a40b9a259b52 3866 match = formatter.call(self, val);
Osamu Nakamura 0:a40b9a259b52 3867
Osamu Nakamura 0:a40b9a259b52 3868 // now we need to remove `args[index]` since it's inlined in the `format`
Osamu Nakamura 0:a40b9a259b52 3869 args.splice(index, 1);
Osamu Nakamura 0:a40b9a259b52 3870 index--;
Osamu Nakamura 0:a40b9a259b52 3871 }
Osamu Nakamura 0:a40b9a259b52 3872 return match;
Osamu Nakamura 0:a40b9a259b52 3873 });
Osamu Nakamura 0:a40b9a259b52 3874
Osamu Nakamura 0:a40b9a259b52 3875 if ('function' === typeof exports.formatArgs) {
Osamu Nakamura 0:a40b9a259b52 3876 args = exports.formatArgs.apply(self, args);
Osamu Nakamura 0:a40b9a259b52 3877 }
Osamu Nakamura 0:a40b9a259b52 3878 var logFn = enabled.log || exports.log || console.log.bind(console);
Osamu Nakamura 0:a40b9a259b52 3879 logFn.apply(self, args);
Osamu Nakamura 0:a40b9a259b52 3880 }
Osamu Nakamura 0:a40b9a259b52 3881 enabled.enabled = true;
Osamu Nakamura 0:a40b9a259b52 3882
Osamu Nakamura 0:a40b9a259b52 3883 var fn = exports.enabled(namespace) ? enabled : disabled;
Osamu Nakamura 0:a40b9a259b52 3884
Osamu Nakamura 0:a40b9a259b52 3885 fn.namespace = namespace;
Osamu Nakamura 0:a40b9a259b52 3886
Osamu Nakamura 0:a40b9a259b52 3887 return fn;
Osamu Nakamura 0:a40b9a259b52 3888 }
Osamu Nakamura 0:a40b9a259b52 3889
Osamu Nakamura 0:a40b9a259b52 3890 /**
Osamu Nakamura 0:a40b9a259b52 3891 * Enables a debug mode by namespaces. This can include modes
Osamu Nakamura 0:a40b9a259b52 3892 * separated by a colon and wildcards.
Osamu Nakamura 0:a40b9a259b52 3893 *
Osamu Nakamura 0:a40b9a259b52 3894 * @param {String} namespaces
Osamu Nakamura 0:a40b9a259b52 3895 * @api public
Osamu Nakamura 0:a40b9a259b52 3896 */
Osamu Nakamura 0:a40b9a259b52 3897
Osamu Nakamura 0:a40b9a259b52 3898 function enable(namespaces) {
Osamu Nakamura 0:a40b9a259b52 3899 exports.save(namespaces);
Osamu Nakamura 0:a40b9a259b52 3900
Osamu Nakamura 0:a40b9a259b52 3901 var split = (namespaces || '').split(/[\s,]+/);
Osamu Nakamura 0:a40b9a259b52 3902 var len = split.length;
Osamu Nakamura 0:a40b9a259b52 3903
Osamu Nakamura 0:a40b9a259b52 3904 for (var i = 0; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 3905 if (!split[i]) continue; // ignore empty strings
Osamu Nakamura 0:a40b9a259b52 3906 namespaces = split[i].replace(/\*/g, '.*?');
Osamu Nakamura 0:a40b9a259b52 3907 if (namespaces[0] === '-') {
Osamu Nakamura 0:a40b9a259b52 3908 exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
Osamu Nakamura 0:a40b9a259b52 3909 } else {
Osamu Nakamura 0:a40b9a259b52 3910 exports.names.push(new RegExp('^' + namespaces + '$'));
Osamu Nakamura 0:a40b9a259b52 3911 }
Osamu Nakamura 0:a40b9a259b52 3912 }
Osamu Nakamura 0:a40b9a259b52 3913 }
Osamu Nakamura 0:a40b9a259b52 3914
Osamu Nakamura 0:a40b9a259b52 3915 /**
Osamu Nakamura 0:a40b9a259b52 3916 * Disable debug output.
Osamu Nakamura 0:a40b9a259b52 3917 *
Osamu Nakamura 0:a40b9a259b52 3918 * @api public
Osamu Nakamura 0:a40b9a259b52 3919 */
Osamu Nakamura 0:a40b9a259b52 3920
Osamu Nakamura 0:a40b9a259b52 3921 function disable() {
Osamu Nakamura 0:a40b9a259b52 3922 exports.enable('');
Osamu Nakamura 0:a40b9a259b52 3923 }
Osamu Nakamura 0:a40b9a259b52 3924
Osamu Nakamura 0:a40b9a259b52 3925 /**
Osamu Nakamura 0:a40b9a259b52 3926 * Returns true if the given mode name is enabled, false otherwise.
Osamu Nakamura 0:a40b9a259b52 3927 *
Osamu Nakamura 0:a40b9a259b52 3928 * @param {String} name
Osamu Nakamura 0:a40b9a259b52 3929 * @return {Boolean}
Osamu Nakamura 0:a40b9a259b52 3930 * @api public
Osamu Nakamura 0:a40b9a259b52 3931 */
Osamu Nakamura 0:a40b9a259b52 3932
Osamu Nakamura 0:a40b9a259b52 3933 function enabled(name) {
Osamu Nakamura 0:a40b9a259b52 3934 var i, len;
Osamu Nakamura 0:a40b9a259b52 3935 for (i = 0, len = exports.skips.length; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 3936 if (exports.skips[i].test(name)) {
Osamu Nakamura 0:a40b9a259b52 3937 return false;
Osamu Nakamura 0:a40b9a259b52 3938 }
Osamu Nakamura 0:a40b9a259b52 3939 }
Osamu Nakamura 0:a40b9a259b52 3940 for (i = 0, len = exports.names.length; i < len; i++) {
Osamu Nakamura 0:a40b9a259b52 3941 if (exports.names[i].test(name)) {
Osamu Nakamura 0:a40b9a259b52 3942 return true;
Osamu Nakamura 0:a40b9a259b52 3943 }
Osamu Nakamura 0:a40b9a259b52 3944 }
Osamu Nakamura 0:a40b9a259b52 3945 return false;
Osamu Nakamura 0:a40b9a259b52 3946 }
Osamu Nakamura 0:a40b9a259b52 3947
Osamu Nakamura 0:a40b9a259b52 3948 /**
Osamu Nakamura 0:a40b9a259b52 3949 * Coerce `val`.
Osamu Nakamura 0:a40b9a259b52 3950 *
Osamu Nakamura 0:a40b9a259b52 3951 * @param {Mixed} val
Osamu Nakamura 0:a40b9a259b52 3952 * @return {Mixed}
Osamu Nakamura 0:a40b9a259b52 3953 * @api private
Osamu Nakamura 0:a40b9a259b52 3954 */
Osamu Nakamura 0:a40b9a259b52 3955
Osamu Nakamura 0:a40b9a259b52 3956 function coerce(val) {
Osamu Nakamura 0:a40b9a259b52 3957 if (val instanceof Error) return val.stack || val.message;
Osamu Nakamura 0:a40b9a259b52 3958 return val;
Osamu Nakamura 0:a40b9a259b52 3959 }
Osamu Nakamura 0:a40b9a259b52 3960
Osamu Nakamura 0:a40b9a259b52 3961 },{"ms":24}],24:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 3962 /**
Osamu Nakamura 0:a40b9a259b52 3963 * Helpers.
Osamu Nakamura 0:a40b9a259b52 3964 */
Osamu Nakamura 0:a40b9a259b52 3965
Osamu Nakamura 0:a40b9a259b52 3966 var s = 1000;
Osamu Nakamura 0:a40b9a259b52 3967 var m = s * 60;
Osamu Nakamura 0:a40b9a259b52 3968 var h = m * 60;
Osamu Nakamura 0:a40b9a259b52 3969 var d = h * 24;
Osamu Nakamura 0:a40b9a259b52 3970 var y = d * 365.25;
Osamu Nakamura 0:a40b9a259b52 3971
Osamu Nakamura 0:a40b9a259b52 3972 /**
Osamu Nakamura 0:a40b9a259b52 3973 * Parse or format the given `val`.
Osamu Nakamura 0:a40b9a259b52 3974 *
Osamu Nakamura 0:a40b9a259b52 3975 * Options:
Osamu Nakamura 0:a40b9a259b52 3976 *
Osamu Nakamura 0:a40b9a259b52 3977 * - `long` verbose formatting [false]
Osamu Nakamura 0:a40b9a259b52 3978 *
Osamu Nakamura 0:a40b9a259b52 3979 * @param {String|Number} val
Osamu Nakamura 0:a40b9a259b52 3980 * @param {Object} options
Osamu Nakamura 0:a40b9a259b52 3981 * @return {String|Number}
Osamu Nakamura 0:a40b9a259b52 3982 * @api public
Osamu Nakamura 0:a40b9a259b52 3983 */
Osamu Nakamura 0:a40b9a259b52 3984
Osamu Nakamura 0:a40b9a259b52 3985 module.exports = function(val, options){
Osamu Nakamura 0:a40b9a259b52 3986 options = options || {};
Osamu Nakamura 0:a40b9a259b52 3987 if ('string' == typeof val) return parse(val);
Osamu Nakamura 0:a40b9a259b52 3988 return options.long
Osamu Nakamura 0:a40b9a259b52 3989 ? long(val)
Osamu Nakamura 0:a40b9a259b52 3990 : short(val);
Osamu Nakamura 0:a40b9a259b52 3991 };
Osamu Nakamura 0:a40b9a259b52 3992
Osamu Nakamura 0:a40b9a259b52 3993 /**
Osamu Nakamura 0:a40b9a259b52 3994 * Parse the given `str` and return milliseconds.
Osamu Nakamura 0:a40b9a259b52 3995 *
Osamu Nakamura 0:a40b9a259b52 3996 * @param {String} str
Osamu Nakamura 0:a40b9a259b52 3997 * @return {Number}
Osamu Nakamura 0:a40b9a259b52 3998 * @api private
Osamu Nakamura 0:a40b9a259b52 3999 */
Osamu Nakamura 0:a40b9a259b52 4000
Osamu Nakamura 0:a40b9a259b52 4001 function parse(str) {
Osamu Nakamura 0:a40b9a259b52 4002 var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
Osamu Nakamura 0:a40b9a259b52 4003 if (!match) return;
Osamu Nakamura 0:a40b9a259b52 4004 var n = parseFloat(match[1]);
Osamu Nakamura 0:a40b9a259b52 4005 var type = (match[2] || 'ms').toLowerCase();
Osamu Nakamura 0:a40b9a259b52 4006 switch (type) {
Osamu Nakamura 0:a40b9a259b52 4007 case 'years':
Osamu Nakamura 0:a40b9a259b52 4008 case 'year':
Osamu Nakamura 0:a40b9a259b52 4009 case 'y':
Osamu Nakamura 0:a40b9a259b52 4010 return n * y;
Osamu Nakamura 0:a40b9a259b52 4011 case 'days':
Osamu Nakamura 0:a40b9a259b52 4012 case 'day':
Osamu Nakamura 0:a40b9a259b52 4013 case 'd':
Osamu Nakamura 0:a40b9a259b52 4014 return n * d;
Osamu Nakamura 0:a40b9a259b52 4015 case 'hours':
Osamu Nakamura 0:a40b9a259b52 4016 case 'hour':
Osamu Nakamura 0:a40b9a259b52 4017 case 'h':
Osamu Nakamura 0:a40b9a259b52 4018 return n * h;
Osamu Nakamura 0:a40b9a259b52 4019 case 'minutes':
Osamu Nakamura 0:a40b9a259b52 4020 case 'minute':
Osamu Nakamura 0:a40b9a259b52 4021 case 'm':
Osamu Nakamura 0:a40b9a259b52 4022 return n * m;
Osamu Nakamura 0:a40b9a259b52 4023 case 'seconds':
Osamu Nakamura 0:a40b9a259b52 4024 case 'second':
Osamu Nakamura 0:a40b9a259b52 4025 case 's':
Osamu Nakamura 0:a40b9a259b52 4026 return n * s;
Osamu Nakamura 0:a40b9a259b52 4027 case 'ms':
Osamu Nakamura 0:a40b9a259b52 4028 return n;
Osamu Nakamura 0:a40b9a259b52 4029 }
Osamu Nakamura 0:a40b9a259b52 4030 }
Osamu Nakamura 0:a40b9a259b52 4031
Osamu Nakamura 0:a40b9a259b52 4032 /**
Osamu Nakamura 0:a40b9a259b52 4033 * Short format for `ms`.
Osamu Nakamura 0:a40b9a259b52 4034 *
Osamu Nakamura 0:a40b9a259b52 4035 * @param {Number} ms
Osamu Nakamura 0:a40b9a259b52 4036 * @return {String}
Osamu Nakamura 0:a40b9a259b52 4037 * @api private
Osamu Nakamura 0:a40b9a259b52 4038 */
Osamu Nakamura 0:a40b9a259b52 4039
Osamu Nakamura 0:a40b9a259b52 4040 function short(ms) {
Osamu Nakamura 0:a40b9a259b52 4041 if (ms >= d) return Math.round(ms / d) + 'd';
Osamu Nakamura 0:a40b9a259b52 4042 if (ms >= h) return Math.round(ms / h) + 'h';
Osamu Nakamura 0:a40b9a259b52 4043 if (ms >= m) return Math.round(ms / m) + 'm';
Osamu Nakamura 0:a40b9a259b52 4044 if (ms >= s) return Math.round(ms / s) + 's';
Osamu Nakamura 0:a40b9a259b52 4045 return ms + 'ms';
Osamu Nakamura 0:a40b9a259b52 4046 }
Osamu Nakamura 0:a40b9a259b52 4047
Osamu Nakamura 0:a40b9a259b52 4048 /**
Osamu Nakamura 0:a40b9a259b52 4049 * Long format for `ms`.
Osamu Nakamura 0:a40b9a259b52 4050 *
Osamu Nakamura 0:a40b9a259b52 4051 * @param {Number} ms
Osamu Nakamura 0:a40b9a259b52 4052 * @return {String}
Osamu Nakamura 0:a40b9a259b52 4053 * @api private
Osamu Nakamura 0:a40b9a259b52 4054 */
Osamu Nakamura 0:a40b9a259b52 4055
Osamu Nakamura 0:a40b9a259b52 4056 function long(ms) {
Osamu Nakamura 0:a40b9a259b52 4057 return plural(ms, d, 'day')
Osamu Nakamura 0:a40b9a259b52 4058 || plural(ms, h, 'hour')
Osamu Nakamura 0:a40b9a259b52 4059 || plural(ms, m, 'minute')
Osamu Nakamura 0:a40b9a259b52 4060 || plural(ms, s, 'second')
Osamu Nakamura 0:a40b9a259b52 4061 || ms + ' ms';
Osamu Nakamura 0:a40b9a259b52 4062 }
Osamu Nakamura 0:a40b9a259b52 4063
Osamu Nakamura 0:a40b9a259b52 4064 /**
Osamu Nakamura 0:a40b9a259b52 4065 * Pluralization helper.
Osamu Nakamura 0:a40b9a259b52 4066 */
Osamu Nakamura 0:a40b9a259b52 4067
Osamu Nakamura 0:a40b9a259b52 4068 function plural(ms, n, name) {
Osamu Nakamura 0:a40b9a259b52 4069 if (ms < n) return;
Osamu Nakamura 0:a40b9a259b52 4070 if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
Osamu Nakamura 0:a40b9a259b52 4071 return Math.ceil(ms / n) + ' ' + name + 's';
Osamu Nakamura 0:a40b9a259b52 4072 }
Osamu Nakamura 0:a40b9a259b52 4073
Osamu Nakamura 0:a40b9a259b52 4074 },{}],25:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4075 (function (global){
Osamu Nakamura 0:a40b9a259b52 4076 /**
Osamu Nakamura 0:a40b9a259b52 4077 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 4078 */
Osamu Nakamura 0:a40b9a259b52 4079
Osamu Nakamura 0:a40b9a259b52 4080 var keys = _dereq_('./keys');
Osamu Nakamura 0:a40b9a259b52 4081 var hasBinary = _dereq_('has-binary');
Osamu Nakamura 0:a40b9a259b52 4082 var sliceBuffer = _dereq_('arraybuffer.slice');
Osamu Nakamura 0:a40b9a259b52 4083 var base64encoder = _dereq_('base64-arraybuffer');
Osamu Nakamura 0:a40b9a259b52 4084 var after = _dereq_('after');
Osamu Nakamura 0:a40b9a259b52 4085 var utf8 = _dereq_('utf8');
Osamu Nakamura 0:a40b9a259b52 4086
Osamu Nakamura 0:a40b9a259b52 4087 /**
Osamu Nakamura 0:a40b9a259b52 4088 * Check if we are running an android browser. That requires us to use
Osamu Nakamura 0:a40b9a259b52 4089 * ArrayBuffer with polling transports...
Osamu Nakamura 0:a40b9a259b52 4090 *
Osamu Nakamura 0:a40b9a259b52 4091 * http://ghinda.net/jpeg-blob-ajax-android/
Osamu Nakamura 0:a40b9a259b52 4092 */
Osamu Nakamura 0:a40b9a259b52 4093
Osamu Nakamura 0:a40b9a259b52 4094 var isAndroid = navigator.userAgent.match(/Android/i);
Osamu Nakamura 0:a40b9a259b52 4095
Osamu Nakamura 0:a40b9a259b52 4096 /**
Osamu Nakamura 0:a40b9a259b52 4097 * Check if we are running in PhantomJS.
Osamu Nakamura 0:a40b9a259b52 4098 * Uploading a Blob with PhantomJS does not work correctly, as reported here:
Osamu Nakamura 0:a40b9a259b52 4099 * https://github.com/ariya/phantomjs/issues/11395
Osamu Nakamura 0:a40b9a259b52 4100 * @type boolean
Osamu Nakamura 0:a40b9a259b52 4101 */
Osamu Nakamura 0:a40b9a259b52 4102 var isPhantomJS = /PhantomJS/i.test(navigator.userAgent);
Osamu Nakamura 0:a40b9a259b52 4103
Osamu Nakamura 0:a40b9a259b52 4104 /**
Osamu Nakamura 0:a40b9a259b52 4105 * When true, avoids using Blobs to encode payloads.
Osamu Nakamura 0:a40b9a259b52 4106 * @type boolean
Osamu Nakamura 0:a40b9a259b52 4107 */
Osamu Nakamura 0:a40b9a259b52 4108 var dontSendBlobs = isAndroid || isPhantomJS;
Osamu Nakamura 0:a40b9a259b52 4109
Osamu Nakamura 0:a40b9a259b52 4110 /**
Osamu Nakamura 0:a40b9a259b52 4111 * Current protocol version.
Osamu Nakamura 0:a40b9a259b52 4112 */
Osamu Nakamura 0:a40b9a259b52 4113
Osamu Nakamura 0:a40b9a259b52 4114 exports.protocol = 3;
Osamu Nakamura 0:a40b9a259b52 4115
Osamu Nakamura 0:a40b9a259b52 4116 /**
Osamu Nakamura 0:a40b9a259b52 4117 * Packet types.
Osamu Nakamura 0:a40b9a259b52 4118 */
Osamu Nakamura 0:a40b9a259b52 4119
Osamu Nakamura 0:a40b9a259b52 4120 var packets = exports.packets = {
Osamu Nakamura 0:a40b9a259b52 4121 open: 0 // non-ws
Osamu Nakamura 0:a40b9a259b52 4122 , close: 1 // non-ws
Osamu Nakamura 0:a40b9a259b52 4123 , ping: 2
Osamu Nakamura 0:a40b9a259b52 4124 , pong: 3
Osamu Nakamura 0:a40b9a259b52 4125 , message: 4
Osamu Nakamura 0:a40b9a259b52 4126 , upgrade: 5
Osamu Nakamura 0:a40b9a259b52 4127 , noop: 6
Osamu Nakamura 0:a40b9a259b52 4128 };
Osamu Nakamura 0:a40b9a259b52 4129
Osamu Nakamura 0:a40b9a259b52 4130 var packetslist = keys(packets);
Osamu Nakamura 0:a40b9a259b52 4131
Osamu Nakamura 0:a40b9a259b52 4132 /**
Osamu Nakamura 0:a40b9a259b52 4133 * Premade error packet.
Osamu Nakamura 0:a40b9a259b52 4134 */
Osamu Nakamura 0:a40b9a259b52 4135
Osamu Nakamura 0:a40b9a259b52 4136 var err = { type: 'error', data: 'parser error' };
Osamu Nakamura 0:a40b9a259b52 4137
Osamu Nakamura 0:a40b9a259b52 4138 /**
Osamu Nakamura 0:a40b9a259b52 4139 * Create a blob api even for blob builder when vendor prefixes exist
Osamu Nakamura 0:a40b9a259b52 4140 */
Osamu Nakamura 0:a40b9a259b52 4141
Osamu Nakamura 0:a40b9a259b52 4142 var Blob = _dereq_('blob');
Osamu Nakamura 0:a40b9a259b52 4143
Osamu Nakamura 0:a40b9a259b52 4144 /**
Osamu Nakamura 0:a40b9a259b52 4145 * Encodes a packet.
Osamu Nakamura 0:a40b9a259b52 4146 *
Osamu Nakamura 0:a40b9a259b52 4147 * <packet type id> [ <data> ]
Osamu Nakamura 0:a40b9a259b52 4148 *
Osamu Nakamura 0:a40b9a259b52 4149 * Example:
Osamu Nakamura 0:a40b9a259b52 4150 *
Osamu Nakamura 0:a40b9a259b52 4151 * 5hello world
Osamu Nakamura 0:a40b9a259b52 4152 * 3
Osamu Nakamura 0:a40b9a259b52 4153 * 4
Osamu Nakamura 0:a40b9a259b52 4154 *
Osamu Nakamura 0:a40b9a259b52 4155 * Binary is encoded in an identical principle
Osamu Nakamura 0:a40b9a259b52 4156 *
Osamu Nakamura 0:a40b9a259b52 4157 * @api private
Osamu Nakamura 0:a40b9a259b52 4158 */
Osamu Nakamura 0:a40b9a259b52 4159
Osamu Nakamura 0:a40b9a259b52 4160 exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
Osamu Nakamura 0:a40b9a259b52 4161 if ('function' == typeof supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 4162 callback = supportsBinary;
Osamu Nakamura 0:a40b9a259b52 4163 supportsBinary = false;
Osamu Nakamura 0:a40b9a259b52 4164 }
Osamu Nakamura 0:a40b9a259b52 4165
Osamu Nakamura 0:a40b9a259b52 4166 if ('function' == typeof utf8encode) {
Osamu Nakamura 0:a40b9a259b52 4167 callback = utf8encode;
Osamu Nakamura 0:a40b9a259b52 4168 utf8encode = null;
Osamu Nakamura 0:a40b9a259b52 4169 }
Osamu Nakamura 0:a40b9a259b52 4170
Osamu Nakamura 0:a40b9a259b52 4171 var data = (packet.data === undefined)
Osamu Nakamura 0:a40b9a259b52 4172 ? undefined
Osamu Nakamura 0:a40b9a259b52 4173 : packet.data.buffer || packet.data;
Osamu Nakamura 0:a40b9a259b52 4174
Osamu Nakamura 0:a40b9a259b52 4175 if (global.ArrayBuffer && data instanceof ArrayBuffer) {
Osamu Nakamura 0:a40b9a259b52 4176 return encodeArrayBuffer(packet, supportsBinary, callback);
Osamu Nakamura 0:a40b9a259b52 4177 } else if (Blob && data instanceof global.Blob) {
Osamu Nakamura 0:a40b9a259b52 4178 return encodeBlob(packet, supportsBinary, callback);
Osamu Nakamura 0:a40b9a259b52 4179 }
Osamu Nakamura 0:a40b9a259b52 4180
Osamu Nakamura 0:a40b9a259b52 4181 // might be an object with { base64: true, data: dataAsBase64String }
Osamu Nakamura 0:a40b9a259b52 4182 if (data && data.base64) {
Osamu Nakamura 0:a40b9a259b52 4183 return encodeBase64Object(packet, callback);
Osamu Nakamura 0:a40b9a259b52 4184 }
Osamu Nakamura 0:a40b9a259b52 4185
Osamu Nakamura 0:a40b9a259b52 4186 // Sending data as a utf-8 string
Osamu Nakamura 0:a40b9a259b52 4187 var encoded = packets[packet.type];
Osamu Nakamura 0:a40b9a259b52 4188
Osamu Nakamura 0:a40b9a259b52 4189 // data fragment is optional
Osamu Nakamura 0:a40b9a259b52 4190 if (undefined !== packet.data) {
Osamu Nakamura 0:a40b9a259b52 4191 encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
Osamu Nakamura 0:a40b9a259b52 4192 }
Osamu Nakamura 0:a40b9a259b52 4193
Osamu Nakamura 0:a40b9a259b52 4194 return callback('' + encoded);
Osamu Nakamura 0:a40b9a259b52 4195
Osamu Nakamura 0:a40b9a259b52 4196 };
Osamu Nakamura 0:a40b9a259b52 4197
Osamu Nakamura 0:a40b9a259b52 4198 function encodeBase64Object(packet, callback) {
Osamu Nakamura 0:a40b9a259b52 4199 // packet data is an object { base64: true, data: dataAsBase64String }
Osamu Nakamura 0:a40b9a259b52 4200 var message = 'b' + exports.packets[packet.type] + packet.data.data;
Osamu Nakamura 0:a40b9a259b52 4201 return callback(message);
Osamu Nakamura 0:a40b9a259b52 4202 }
Osamu Nakamura 0:a40b9a259b52 4203
Osamu Nakamura 0:a40b9a259b52 4204 /**
Osamu Nakamura 0:a40b9a259b52 4205 * Encode packet helpers for binary types
Osamu Nakamura 0:a40b9a259b52 4206 */
Osamu Nakamura 0:a40b9a259b52 4207
Osamu Nakamura 0:a40b9a259b52 4208 function encodeArrayBuffer(packet, supportsBinary, callback) {
Osamu Nakamura 0:a40b9a259b52 4209 if (!supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 4210 return exports.encodeBase64Packet(packet, callback);
Osamu Nakamura 0:a40b9a259b52 4211 }
Osamu Nakamura 0:a40b9a259b52 4212
Osamu Nakamura 0:a40b9a259b52 4213 var data = packet.data;
Osamu Nakamura 0:a40b9a259b52 4214 var contentArray = new Uint8Array(data);
Osamu Nakamura 0:a40b9a259b52 4215 var resultBuffer = new Uint8Array(1 + data.byteLength);
Osamu Nakamura 0:a40b9a259b52 4216
Osamu Nakamura 0:a40b9a259b52 4217 resultBuffer[0] = packets[packet.type];
Osamu Nakamura 0:a40b9a259b52 4218 for (var i = 0; i < contentArray.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4219 resultBuffer[i+1] = contentArray[i];
Osamu Nakamura 0:a40b9a259b52 4220 }
Osamu Nakamura 0:a40b9a259b52 4221
Osamu Nakamura 0:a40b9a259b52 4222 return callback(resultBuffer.buffer);
Osamu Nakamura 0:a40b9a259b52 4223 }
Osamu Nakamura 0:a40b9a259b52 4224
Osamu Nakamura 0:a40b9a259b52 4225 function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
Osamu Nakamura 0:a40b9a259b52 4226 if (!supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 4227 return exports.encodeBase64Packet(packet, callback);
Osamu Nakamura 0:a40b9a259b52 4228 }
Osamu Nakamura 0:a40b9a259b52 4229
Osamu Nakamura 0:a40b9a259b52 4230 var fr = new FileReader();
Osamu Nakamura 0:a40b9a259b52 4231 fr.onload = function() {
Osamu Nakamura 0:a40b9a259b52 4232 packet.data = fr.result;
Osamu Nakamura 0:a40b9a259b52 4233 exports.encodePacket(packet, supportsBinary, true, callback);
Osamu Nakamura 0:a40b9a259b52 4234 };
Osamu Nakamura 0:a40b9a259b52 4235 return fr.readAsArrayBuffer(packet.data);
Osamu Nakamura 0:a40b9a259b52 4236 }
Osamu Nakamura 0:a40b9a259b52 4237
Osamu Nakamura 0:a40b9a259b52 4238 function encodeBlob(packet, supportsBinary, callback) {
Osamu Nakamura 0:a40b9a259b52 4239 if (!supportsBinary) {
Osamu Nakamura 0:a40b9a259b52 4240 return exports.encodeBase64Packet(packet, callback);
Osamu Nakamura 0:a40b9a259b52 4241 }
Osamu Nakamura 0:a40b9a259b52 4242
Osamu Nakamura 0:a40b9a259b52 4243 if (dontSendBlobs) {
Osamu Nakamura 0:a40b9a259b52 4244 return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
Osamu Nakamura 0:a40b9a259b52 4245 }
Osamu Nakamura 0:a40b9a259b52 4246
Osamu Nakamura 0:a40b9a259b52 4247 var length = new Uint8Array(1);
Osamu Nakamura 0:a40b9a259b52 4248 length[0] = packets[packet.type];
Osamu Nakamura 0:a40b9a259b52 4249 var blob = new Blob([length.buffer, packet.data]);
Osamu Nakamura 0:a40b9a259b52 4250
Osamu Nakamura 0:a40b9a259b52 4251 return callback(blob);
Osamu Nakamura 0:a40b9a259b52 4252 }
Osamu Nakamura 0:a40b9a259b52 4253
Osamu Nakamura 0:a40b9a259b52 4254 /**
Osamu Nakamura 0:a40b9a259b52 4255 * Encodes a packet with binary data in a base64 string
Osamu Nakamura 0:a40b9a259b52 4256 *
Osamu Nakamura 0:a40b9a259b52 4257 * @param {Object} packet, has `type` and `data`
Osamu Nakamura 0:a40b9a259b52 4258 * @return {String} base64 encoded message
Osamu Nakamura 0:a40b9a259b52 4259 */
Osamu Nakamura 0:a40b9a259b52 4260
Osamu Nakamura 0:a40b9a259b52 4261 exports.encodeBase64Packet = function(packet, callback) {
Osamu Nakamura 0:a40b9a259b52 4262 var message = 'b' + exports.packets[packet.type];
Osamu Nakamura 0:a40b9a259b52 4263 if (Blob && packet.data instanceof Blob) {
Osamu Nakamura 0:a40b9a259b52 4264 var fr = new FileReader();
Osamu Nakamura 0:a40b9a259b52 4265 fr.onload = function() {
Osamu Nakamura 0:a40b9a259b52 4266 var b64 = fr.result.split(',')[1];
Osamu Nakamura 0:a40b9a259b52 4267 callback(message + b64);
Osamu Nakamura 0:a40b9a259b52 4268 };
Osamu Nakamura 0:a40b9a259b52 4269 return fr.readAsDataURL(packet.data);
Osamu Nakamura 0:a40b9a259b52 4270 }
Osamu Nakamura 0:a40b9a259b52 4271
Osamu Nakamura 0:a40b9a259b52 4272 var b64data;
Osamu Nakamura 0:a40b9a259b52 4273 try {
Osamu Nakamura 0:a40b9a259b52 4274 b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
Osamu Nakamura 0:a40b9a259b52 4275 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 4276 // iPhone Safari doesn't let you apply with typed arrays
Osamu Nakamura 0:a40b9a259b52 4277 var typed = new Uint8Array(packet.data);
Osamu Nakamura 0:a40b9a259b52 4278 var basic = new Array(typed.length);
Osamu Nakamura 0:a40b9a259b52 4279 for (var i = 0; i < typed.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4280 basic[i] = typed[i];
Osamu Nakamura 0:a40b9a259b52 4281 }
Osamu Nakamura 0:a40b9a259b52 4282 b64data = String.fromCharCode.apply(null, basic);
Osamu Nakamura 0:a40b9a259b52 4283 }
Osamu Nakamura 0:a40b9a259b52 4284 message += global.btoa(b64data);
Osamu Nakamura 0:a40b9a259b52 4285 return callback(message);
Osamu Nakamura 0:a40b9a259b52 4286 };
Osamu Nakamura 0:a40b9a259b52 4287
Osamu Nakamura 0:a40b9a259b52 4288 /**
Osamu Nakamura 0:a40b9a259b52 4289 * Decodes a packet. Changes format to Blob if requested.
Osamu Nakamura 0:a40b9a259b52 4290 *
Osamu Nakamura 0:a40b9a259b52 4291 * @return {Object} with `type` and `data` (if any)
Osamu Nakamura 0:a40b9a259b52 4292 * @api private
Osamu Nakamura 0:a40b9a259b52 4293 */
Osamu Nakamura 0:a40b9a259b52 4294
Osamu Nakamura 0:a40b9a259b52 4295 exports.decodePacket = function (data, binaryType, utf8decode) {
Osamu Nakamura 0:a40b9a259b52 4296 // String data
Osamu Nakamura 0:a40b9a259b52 4297 if (typeof data == 'string' || data === undefined) {
Osamu Nakamura 0:a40b9a259b52 4298 if (data.charAt(0) == 'b') {
Osamu Nakamura 0:a40b9a259b52 4299 return exports.decodeBase64Packet(data.substr(1), binaryType);
Osamu Nakamura 0:a40b9a259b52 4300 }
Osamu Nakamura 0:a40b9a259b52 4301
Osamu Nakamura 0:a40b9a259b52 4302 if (utf8decode) {
Osamu Nakamura 0:a40b9a259b52 4303 try {
Osamu Nakamura 0:a40b9a259b52 4304 data = utf8.decode(data);
Osamu Nakamura 0:a40b9a259b52 4305 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 4306 return err;
Osamu Nakamura 0:a40b9a259b52 4307 }
Osamu Nakamura 0:a40b9a259b52 4308 }
Osamu Nakamura 0:a40b9a259b52 4309 var type = data.charAt(0);
Osamu Nakamura 0:a40b9a259b52 4310
Osamu Nakamura 0:a40b9a259b52 4311 if (Number(type) != type || !packetslist[type]) {
Osamu Nakamura 0:a40b9a259b52 4312 return err;
Osamu Nakamura 0:a40b9a259b52 4313 }
Osamu Nakamura 0:a40b9a259b52 4314
Osamu Nakamura 0:a40b9a259b52 4315 if (data.length > 1) {
Osamu Nakamura 0:a40b9a259b52 4316 return { type: packetslist[type], data: data.substring(1) };
Osamu Nakamura 0:a40b9a259b52 4317 } else {
Osamu Nakamura 0:a40b9a259b52 4318 return { type: packetslist[type] };
Osamu Nakamura 0:a40b9a259b52 4319 }
Osamu Nakamura 0:a40b9a259b52 4320 }
Osamu Nakamura 0:a40b9a259b52 4321
Osamu Nakamura 0:a40b9a259b52 4322 var asArray = new Uint8Array(data);
Osamu Nakamura 0:a40b9a259b52 4323 var type = asArray[0];
Osamu Nakamura 0:a40b9a259b52 4324 var rest = sliceBuffer(data, 1);
Osamu Nakamura 0:a40b9a259b52 4325 if (Blob && binaryType === 'blob') {
Osamu Nakamura 0:a40b9a259b52 4326 rest = new Blob([rest]);
Osamu Nakamura 0:a40b9a259b52 4327 }
Osamu Nakamura 0:a40b9a259b52 4328 return { type: packetslist[type], data: rest };
Osamu Nakamura 0:a40b9a259b52 4329 };
Osamu Nakamura 0:a40b9a259b52 4330
Osamu Nakamura 0:a40b9a259b52 4331 /**
Osamu Nakamura 0:a40b9a259b52 4332 * Decodes a packet encoded in a base64 string
Osamu Nakamura 0:a40b9a259b52 4333 *
Osamu Nakamura 0:a40b9a259b52 4334 * @param {String} base64 encoded message
Osamu Nakamura 0:a40b9a259b52 4335 * @return {Object} with `type` and `data` (if any)
Osamu Nakamura 0:a40b9a259b52 4336 */
Osamu Nakamura 0:a40b9a259b52 4337
Osamu Nakamura 0:a40b9a259b52 4338 exports.decodeBase64Packet = function(msg, binaryType) {
Osamu Nakamura 0:a40b9a259b52 4339 var type = packetslist[msg.charAt(0)];
Osamu Nakamura 0:a40b9a259b52 4340 if (!global.ArrayBuffer) {
Osamu Nakamura 0:a40b9a259b52 4341 return { type: type, data: { base64: true, data: msg.substr(1) } };
Osamu Nakamura 0:a40b9a259b52 4342 }
Osamu Nakamura 0:a40b9a259b52 4343
Osamu Nakamura 0:a40b9a259b52 4344 var data = base64encoder.decode(msg.substr(1));
Osamu Nakamura 0:a40b9a259b52 4345
Osamu Nakamura 0:a40b9a259b52 4346 if (binaryType === 'blob' && Blob) {
Osamu Nakamura 0:a40b9a259b52 4347 data = new Blob([data]);
Osamu Nakamura 0:a40b9a259b52 4348 }
Osamu Nakamura 0:a40b9a259b52 4349
Osamu Nakamura 0:a40b9a259b52 4350 return { type: type, data: data };
Osamu Nakamura 0:a40b9a259b52 4351 };
Osamu Nakamura 0:a40b9a259b52 4352
Osamu Nakamura 0:a40b9a259b52 4353 /**
Osamu Nakamura 0:a40b9a259b52 4354 * Encodes multiple messages (payload).
Osamu Nakamura 0:a40b9a259b52 4355 *
Osamu Nakamura 0:a40b9a259b52 4356 * <length>:data
Osamu Nakamura 0:a40b9a259b52 4357 *
Osamu Nakamura 0:a40b9a259b52 4358 * Example:
Osamu Nakamura 0:a40b9a259b52 4359 *
Osamu Nakamura 0:a40b9a259b52 4360 * 11:hello world2:hi
Osamu Nakamura 0:a40b9a259b52 4361 *
Osamu Nakamura 0:a40b9a259b52 4362 * If any contents are binary, they will be encoded as base64 strings. Base64
Osamu Nakamura 0:a40b9a259b52 4363 * encoded strings are marked with a b before the length specifier
Osamu Nakamura 0:a40b9a259b52 4364 *
Osamu Nakamura 0:a40b9a259b52 4365 * @param {Array} packets
Osamu Nakamura 0:a40b9a259b52 4366 * @api private
Osamu Nakamura 0:a40b9a259b52 4367 */
Osamu Nakamura 0:a40b9a259b52 4368
Osamu Nakamura 0:a40b9a259b52 4369 exports.encodePayload = function (packets, supportsBinary, callback) {
Osamu Nakamura 0:a40b9a259b52 4370 if (typeof supportsBinary == 'function') {
Osamu Nakamura 0:a40b9a259b52 4371 callback = supportsBinary;
Osamu Nakamura 0:a40b9a259b52 4372 supportsBinary = null;
Osamu Nakamura 0:a40b9a259b52 4373 }
Osamu Nakamura 0:a40b9a259b52 4374
Osamu Nakamura 0:a40b9a259b52 4375 var isBinary = hasBinary(packets);
Osamu Nakamura 0:a40b9a259b52 4376
Osamu Nakamura 0:a40b9a259b52 4377 if (supportsBinary && isBinary) {
Osamu Nakamura 0:a40b9a259b52 4378 if (Blob && !dontSendBlobs) {
Osamu Nakamura 0:a40b9a259b52 4379 return exports.encodePayloadAsBlob(packets, callback);
Osamu Nakamura 0:a40b9a259b52 4380 }
Osamu Nakamura 0:a40b9a259b52 4381
Osamu Nakamura 0:a40b9a259b52 4382 return exports.encodePayloadAsArrayBuffer(packets, callback);
Osamu Nakamura 0:a40b9a259b52 4383 }
Osamu Nakamura 0:a40b9a259b52 4384
Osamu Nakamura 0:a40b9a259b52 4385 if (!packets.length) {
Osamu Nakamura 0:a40b9a259b52 4386 return callback('0:');
Osamu Nakamura 0:a40b9a259b52 4387 }
Osamu Nakamura 0:a40b9a259b52 4388
Osamu Nakamura 0:a40b9a259b52 4389 function setLengthHeader(message) {
Osamu Nakamura 0:a40b9a259b52 4390 return message.length + ':' + message;
Osamu Nakamura 0:a40b9a259b52 4391 }
Osamu Nakamura 0:a40b9a259b52 4392
Osamu Nakamura 0:a40b9a259b52 4393 function encodeOne(packet, doneCallback) {
Osamu Nakamura 0:a40b9a259b52 4394 exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) {
Osamu Nakamura 0:a40b9a259b52 4395 doneCallback(null, setLengthHeader(message));
Osamu Nakamura 0:a40b9a259b52 4396 });
Osamu Nakamura 0:a40b9a259b52 4397 }
Osamu Nakamura 0:a40b9a259b52 4398
Osamu Nakamura 0:a40b9a259b52 4399 map(packets, encodeOne, function(err, results) {
Osamu Nakamura 0:a40b9a259b52 4400 return callback(results.join(''));
Osamu Nakamura 0:a40b9a259b52 4401 });
Osamu Nakamura 0:a40b9a259b52 4402 };
Osamu Nakamura 0:a40b9a259b52 4403
Osamu Nakamura 0:a40b9a259b52 4404 /**
Osamu Nakamura 0:a40b9a259b52 4405 * Async array map using after
Osamu Nakamura 0:a40b9a259b52 4406 */
Osamu Nakamura 0:a40b9a259b52 4407
Osamu Nakamura 0:a40b9a259b52 4408 function map(ary, each, done) {
Osamu Nakamura 0:a40b9a259b52 4409 var result = new Array(ary.length);
Osamu Nakamura 0:a40b9a259b52 4410 var next = after(ary.length, done);
Osamu Nakamura 0:a40b9a259b52 4411
Osamu Nakamura 0:a40b9a259b52 4412 var eachWithIndex = function(i, el, cb) {
Osamu Nakamura 0:a40b9a259b52 4413 each(el, function(error, msg) {
Osamu Nakamura 0:a40b9a259b52 4414 result[i] = msg;
Osamu Nakamura 0:a40b9a259b52 4415 cb(error, result);
Osamu Nakamura 0:a40b9a259b52 4416 });
Osamu Nakamura 0:a40b9a259b52 4417 };
Osamu Nakamura 0:a40b9a259b52 4418
Osamu Nakamura 0:a40b9a259b52 4419 for (var i = 0; i < ary.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4420 eachWithIndex(i, ary[i], next);
Osamu Nakamura 0:a40b9a259b52 4421 }
Osamu Nakamura 0:a40b9a259b52 4422 }
Osamu Nakamura 0:a40b9a259b52 4423
Osamu Nakamura 0:a40b9a259b52 4424 /*
Osamu Nakamura 0:a40b9a259b52 4425 * Decodes data when a payload is maybe expected. Possible binary contents are
Osamu Nakamura 0:a40b9a259b52 4426 * decoded from their base64 representation
Osamu Nakamura 0:a40b9a259b52 4427 *
Osamu Nakamura 0:a40b9a259b52 4428 * @param {String} data, callback method
Osamu Nakamura 0:a40b9a259b52 4429 * @api public
Osamu Nakamura 0:a40b9a259b52 4430 */
Osamu Nakamura 0:a40b9a259b52 4431
Osamu Nakamura 0:a40b9a259b52 4432 exports.decodePayload = function (data, binaryType, callback) {
Osamu Nakamura 0:a40b9a259b52 4433 if (typeof data != 'string') {
Osamu Nakamura 0:a40b9a259b52 4434 return exports.decodePayloadAsBinary(data, binaryType, callback);
Osamu Nakamura 0:a40b9a259b52 4435 }
Osamu Nakamura 0:a40b9a259b52 4436
Osamu Nakamura 0:a40b9a259b52 4437 if (typeof binaryType === 'function') {
Osamu Nakamura 0:a40b9a259b52 4438 callback = binaryType;
Osamu Nakamura 0:a40b9a259b52 4439 binaryType = null;
Osamu Nakamura 0:a40b9a259b52 4440 }
Osamu Nakamura 0:a40b9a259b52 4441
Osamu Nakamura 0:a40b9a259b52 4442 var packet;
Osamu Nakamura 0:a40b9a259b52 4443 if (data == '') {
Osamu Nakamura 0:a40b9a259b52 4444 // parser error - ignoring payload
Osamu Nakamura 0:a40b9a259b52 4445 return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4446 }
Osamu Nakamura 0:a40b9a259b52 4447
Osamu Nakamura 0:a40b9a259b52 4448 var length = ''
Osamu Nakamura 0:a40b9a259b52 4449 , n, msg;
Osamu Nakamura 0:a40b9a259b52 4450
Osamu Nakamura 0:a40b9a259b52 4451 for (var i = 0, l = data.length; i < l; i++) {
Osamu Nakamura 0:a40b9a259b52 4452 var chr = data.charAt(i);
Osamu Nakamura 0:a40b9a259b52 4453
Osamu Nakamura 0:a40b9a259b52 4454 if (':' != chr) {
Osamu Nakamura 0:a40b9a259b52 4455 length += chr;
Osamu Nakamura 0:a40b9a259b52 4456 } else {
Osamu Nakamura 0:a40b9a259b52 4457 if ('' == length || (length != (n = Number(length)))) {
Osamu Nakamura 0:a40b9a259b52 4458 // parser error - ignoring payload
Osamu Nakamura 0:a40b9a259b52 4459 return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4460 }
Osamu Nakamura 0:a40b9a259b52 4461
Osamu Nakamura 0:a40b9a259b52 4462 msg = data.substr(i + 1, n);
Osamu Nakamura 0:a40b9a259b52 4463
Osamu Nakamura 0:a40b9a259b52 4464 if (length != msg.length) {
Osamu Nakamura 0:a40b9a259b52 4465 // parser error - ignoring payload
Osamu Nakamura 0:a40b9a259b52 4466 return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4467 }
Osamu Nakamura 0:a40b9a259b52 4468
Osamu Nakamura 0:a40b9a259b52 4469 if (msg.length) {
Osamu Nakamura 0:a40b9a259b52 4470 packet = exports.decodePacket(msg, binaryType, true);
Osamu Nakamura 0:a40b9a259b52 4471
Osamu Nakamura 0:a40b9a259b52 4472 if (err.type == packet.type && err.data == packet.data) {
Osamu Nakamura 0:a40b9a259b52 4473 // parser error in individual packet - ignoring payload
Osamu Nakamura 0:a40b9a259b52 4474 return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4475 }
Osamu Nakamura 0:a40b9a259b52 4476
Osamu Nakamura 0:a40b9a259b52 4477 var ret = callback(packet, i + n, l);
Osamu Nakamura 0:a40b9a259b52 4478 if (false === ret) return;
Osamu Nakamura 0:a40b9a259b52 4479 }
Osamu Nakamura 0:a40b9a259b52 4480
Osamu Nakamura 0:a40b9a259b52 4481 // advance cursor
Osamu Nakamura 0:a40b9a259b52 4482 i += n;
Osamu Nakamura 0:a40b9a259b52 4483 length = '';
Osamu Nakamura 0:a40b9a259b52 4484 }
Osamu Nakamura 0:a40b9a259b52 4485 }
Osamu Nakamura 0:a40b9a259b52 4486
Osamu Nakamura 0:a40b9a259b52 4487 if (length != '') {
Osamu Nakamura 0:a40b9a259b52 4488 // parser error - ignoring payload
Osamu Nakamura 0:a40b9a259b52 4489 return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4490 }
Osamu Nakamura 0:a40b9a259b52 4491
Osamu Nakamura 0:a40b9a259b52 4492 };
Osamu Nakamura 0:a40b9a259b52 4493
Osamu Nakamura 0:a40b9a259b52 4494 /**
Osamu Nakamura 0:a40b9a259b52 4495 * Encodes multiple messages (payload) as binary.
Osamu Nakamura 0:a40b9a259b52 4496 *
Osamu Nakamura 0:a40b9a259b52 4497 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
Osamu Nakamura 0:a40b9a259b52 4498 * 255><data>
Osamu Nakamura 0:a40b9a259b52 4499 *
Osamu Nakamura 0:a40b9a259b52 4500 * Example:
Osamu Nakamura 0:a40b9a259b52 4501 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
Osamu Nakamura 0:a40b9a259b52 4502 *
Osamu Nakamura 0:a40b9a259b52 4503 * @param {Array} packets
Osamu Nakamura 0:a40b9a259b52 4504 * @return {ArrayBuffer} encoded payload
Osamu Nakamura 0:a40b9a259b52 4505 * @api private
Osamu Nakamura 0:a40b9a259b52 4506 */
Osamu Nakamura 0:a40b9a259b52 4507
Osamu Nakamura 0:a40b9a259b52 4508 exports.encodePayloadAsArrayBuffer = function(packets, callback) {
Osamu Nakamura 0:a40b9a259b52 4509 if (!packets.length) {
Osamu Nakamura 0:a40b9a259b52 4510 return callback(new ArrayBuffer(0));
Osamu Nakamura 0:a40b9a259b52 4511 }
Osamu Nakamura 0:a40b9a259b52 4512
Osamu Nakamura 0:a40b9a259b52 4513 function encodeOne(packet, doneCallback) {
Osamu Nakamura 0:a40b9a259b52 4514 exports.encodePacket(packet, true, true, function(data) {
Osamu Nakamura 0:a40b9a259b52 4515 return doneCallback(null, data);
Osamu Nakamura 0:a40b9a259b52 4516 });
Osamu Nakamura 0:a40b9a259b52 4517 }
Osamu Nakamura 0:a40b9a259b52 4518
Osamu Nakamura 0:a40b9a259b52 4519 map(packets, encodeOne, function(err, encodedPackets) {
Osamu Nakamura 0:a40b9a259b52 4520 var totalLength = encodedPackets.reduce(function(acc, p) {
Osamu Nakamura 0:a40b9a259b52 4521 var len;
Osamu Nakamura 0:a40b9a259b52 4522 if (typeof p === 'string'){
Osamu Nakamura 0:a40b9a259b52 4523 len = p.length;
Osamu Nakamura 0:a40b9a259b52 4524 } else {
Osamu Nakamura 0:a40b9a259b52 4525 len = p.byteLength;
Osamu Nakamura 0:a40b9a259b52 4526 }
Osamu Nakamura 0:a40b9a259b52 4527 return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
Osamu Nakamura 0:a40b9a259b52 4528 }, 0);
Osamu Nakamura 0:a40b9a259b52 4529
Osamu Nakamura 0:a40b9a259b52 4530 var resultArray = new Uint8Array(totalLength);
Osamu Nakamura 0:a40b9a259b52 4531
Osamu Nakamura 0:a40b9a259b52 4532 var bufferIndex = 0;
Osamu Nakamura 0:a40b9a259b52 4533 encodedPackets.forEach(function(p) {
Osamu Nakamura 0:a40b9a259b52 4534 var isString = typeof p === 'string';
Osamu Nakamura 0:a40b9a259b52 4535 var ab = p;
Osamu Nakamura 0:a40b9a259b52 4536 if (isString) {
Osamu Nakamura 0:a40b9a259b52 4537 var view = new Uint8Array(p.length);
Osamu Nakamura 0:a40b9a259b52 4538 for (var i = 0; i < p.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4539 view[i] = p.charCodeAt(i);
Osamu Nakamura 0:a40b9a259b52 4540 }
Osamu Nakamura 0:a40b9a259b52 4541 ab = view.buffer;
Osamu Nakamura 0:a40b9a259b52 4542 }
Osamu Nakamura 0:a40b9a259b52 4543
Osamu Nakamura 0:a40b9a259b52 4544 if (isString) { // not true binary
Osamu Nakamura 0:a40b9a259b52 4545 resultArray[bufferIndex++] = 0;
Osamu Nakamura 0:a40b9a259b52 4546 } else { // true binary
Osamu Nakamura 0:a40b9a259b52 4547 resultArray[bufferIndex++] = 1;
Osamu Nakamura 0:a40b9a259b52 4548 }
Osamu Nakamura 0:a40b9a259b52 4549
Osamu Nakamura 0:a40b9a259b52 4550 var lenStr = ab.byteLength.toString();
Osamu Nakamura 0:a40b9a259b52 4551 for (var i = 0; i < lenStr.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4552 resultArray[bufferIndex++] = parseInt(lenStr[i]);
Osamu Nakamura 0:a40b9a259b52 4553 }
Osamu Nakamura 0:a40b9a259b52 4554 resultArray[bufferIndex++] = 255;
Osamu Nakamura 0:a40b9a259b52 4555
Osamu Nakamura 0:a40b9a259b52 4556 var view = new Uint8Array(ab);
Osamu Nakamura 0:a40b9a259b52 4557 for (var i = 0; i < view.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4558 resultArray[bufferIndex++] = view[i];
Osamu Nakamura 0:a40b9a259b52 4559 }
Osamu Nakamura 0:a40b9a259b52 4560 });
Osamu Nakamura 0:a40b9a259b52 4561
Osamu Nakamura 0:a40b9a259b52 4562 return callback(resultArray.buffer);
Osamu Nakamura 0:a40b9a259b52 4563 });
Osamu Nakamura 0:a40b9a259b52 4564 };
Osamu Nakamura 0:a40b9a259b52 4565
Osamu Nakamura 0:a40b9a259b52 4566 /**
Osamu Nakamura 0:a40b9a259b52 4567 * Encode as Blob
Osamu Nakamura 0:a40b9a259b52 4568 */
Osamu Nakamura 0:a40b9a259b52 4569
Osamu Nakamura 0:a40b9a259b52 4570 exports.encodePayloadAsBlob = function(packets, callback) {
Osamu Nakamura 0:a40b9a259b52 4571 function encodeOne(packet, doneCallback) {
Osamu Nakamura 0:a40b9a259b52 4572 exports.encodePacket(packet, true, true, function(encoded) {
Osamu Nakamura 0:a40b9a259b52 4573 var binaryIdentifier = new Uint8Array(1);
Osamu Nakamura 0:a40b9a259b52 4574 binaryIdentifier[0] = 1;
Osamu Nakamura 0:a40b9a259b52 4575 if (typeof encoded === 'string') {
Osamu Nakamura 0:a40b9a259b52 4576 var view = new Uint8Array(encoded.length);
Osamu Nakamura 0:a40b9a259b52 4577 for (var i = 0; i < encoded.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4578 view[i] = encoded.charCodeAt(i);
Osamu Nakamura 0:a40b9a259b52 4579 }
Osamu Nakamura 0:a40b9a259b52 4580 encoded = view.buffer;
Osamu Nakamura 0:a40b9a259b52 4581 binaryIdentifier[0] = 0;
Osamu Nakamura 0:a40b9a259b52 4582 }
Osamu Nakamura 0:a40b9a259b52 4583
Osamu Nakamura 0:a40b9a259b52 4584 var len = (encoded instanceof ArrayBuffer)
Osamu Nakamura 0:a40b9a259b52 4585 ? encoded.byteLength
Osamu Nakamura 0:a40b9a259b52 4586 : encoded.size;
Osamu Nakamura 0:a40b9a259b52 4587
Osamu Nakamura 0:a40b9a259b52 4588 var lenStr = len.toString();
Osamu Nakamura 0:a40b9a259b52 4589 var lengthAry = new Uint8Array(lenStr.length + 1);
Osamu Nakamura 0:a40b9a259b52 4590 for (var i = 0; i < lenStr.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4591 lengthAry[i] = parseInt(lenStr[i]);
Osamu Nakamura 0:a40b9a259b52 4592 }
Osamu Nakamura 0:a40b9a259b52 4593 lengthAry[lenStr.length] = 255;
Osamu Nakamura 0:a40b9a259b52 4594
Osamu Nakamura 0:a40b9a259b52 4595 if (Blob) {
Osamu Nakamura 0:a40b9a259b52 4596 var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
Osamu Nakamura 0:a40b9a259b52 4597 doneCallback(null, blob);
Osamu Nakamura 0:a40b9a259b52 4598 }
Osamu Nakamura 0:a40b9a259b52 4599 });
Osamu Nakamura 0:a40b9a259b52 4600 }
Osamu Nakamura 0:a40b9a259b52 4601
Osamu Nakamura 0:a40b9a259b52 4602 map(packets, encodeOne, function(err, results) {
Osamu Nakamura 0:a40b9a259b52 4603 return callback(new Blob(results));
Osamu Nakamura 0:a40b9a259b52 4604 });
Osamu Nakamura 0:a40b9a259b52 4605 };
Osamu Nakamura 0:a40b9a259b52 4606
Osamu Nakamura 0:a40b9a259b52 4607 /*
Osamu Nakamura 0:a40b9a259b52 4608 * Decodes data when a payload is maybe expected. Strings are decoded by
Osamu Nakamura 0:a40b9a259b52 4609 * interpreting each byte as a key code for entries marked to start with 0. See
Osamu Nakamura 0:a40b9a259b52 4610 * description of encodePayloadAsBinary
Osamu Nakamura 0:a40b9a259b52 4611 *
Osamu Nakamura 0:a40b9a259b52 4612 * @param {ArrayBuffer} data, callback method
Osamu Nakamura 0:a40b9a259b52 4613 * @api public
Osamu Nakamura 0:a40b9a259b52 4614 */
Osamu Nakamura 0:a40b9a259b52 4615
Osamu Nakamura 0:a40b9a259b52 4616 exports.decodePayloadAsBinary = function (data, binaryType, callback) {
Osamu Nakamura 0:a40b9a259b52 4617 if (typeof binaryType === 'function') {
Osamu Nakamura 0:a40b9a259b52 4618 callback = binaryType;
Osamu Nakamura 0:a40b9a259b52 4619 binaryType = null;
Osamu Nakamura 0:a40b9a259b52 4620 }
Osamu Nakamura 0:a40b9a259b52 4621
Osamu Nakamura 0:a40b9a259b52 4622 var bufferTail = data;
Osamu Nakamura 0:a40b9a259b52 4623 var buffers = [];
Osamu Nakamura 0:a40b9a259b52 4624
Osamu Nakamura 0:a40b9a259b52 4625 var numberTooLong = false;
Osamu Nakamura 0:a40b9a259b52 4626 while (bufferTail.byteLength > 0) {
Osamu Nakamura 0:a40b9a259b52 4627 var tailArray = new Uint8Array(bufferTail);
Osamu Nakamura 0:a40b9a259b52 4628 var isString = tailArray[0] === 0;
Osamu Nakamura 0:a40b9a259b52 4629 var msgLength = '';
Osamu Nakamura 0:a40b9a259b52 4630
Osamu Nakamura 0:a40b9a259b52 4631 for (var i = 1; ; i++) {
Osamu Nakamura 0:a40b9a259b52 4632 if (tailArray[i] == 255) break;
Osamu Nakamura 0:a40b9a259b52 4633
Osamu Nakamura 0:a40b9a259b52 4634 if (msgLength.length > 310) {
Osamu Nakamura 0:a40b9a259b52 4635 numberTooLong = true;
Osamu Nakamura 0:a40b9a259b52 4636 break;
Osamu Nakamura 0:a40b9a259b52 4637 }
Osamu Nakamura 0:a40b9a259b52 4638
Osamu Nakamura 0:a40b9a259b52 4639 msgLength += tailArray[i];
Osamu Nakamura 0:a40b9a259b52 4640 }
Osamu Nakamura 0:a40b9a259b52 4641
Osamu Nakamura 0:a40b9a259b52 4642 if(numberTooLong) return callback(err, 0, 1);
Osamu Nakamura 0:a40b9a259b52 4643
Osamu Nakamura 0:a40b9a259b52 4644 bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
Osamu Nakamura 0:a40b9a259b52 4645 msgLength = parseInt(msgLength);
Osamu Nakamura 0:a40b9a259b52 4646
Osamu Nakamura 0:a40b9a259b52 4647 var msg = sliceBuffer(bufferTail, 0, msgLength);
Osamu Nakamura 0:a40b9a259b52 4648 if (isString) {
Osamu Nakamura 0:a40b9a259b52 4649 try {
Osamu Nakamura 0:a40b9a259b52 4650 msg = String.fromCharCode.apply(null, new Uint8Array(msg));
Osamu Nakamura 0:a40b9a259b52 4651 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 4652 // iPhone Safari doesn't let you apply to typed arrays
Osamu Nakamura 0:a40b9a259b52 4653 var typed = new Uint8Array(msg);
Osamu Nakamura 0:a40b9a259b52 4654 msg = '';
Osamu Nakamura 0:a40b9a259b52 4655 for (var i = 0; i < typed.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4656 msg += String.fromCharCode(typed[i]);
Osamu Nakamura 0:a40b9a259b52 4657 }
Osamu Nakamura 0:a40b9a259b52 4658 }
Osamu Nakamura 0:a40b9a259b52 4659 }
Osamu Nakamura 0:a40b9a259b52 4660
Osamu Nakamura 0:a40b9a259b52 4661 buffers.push(msg);
Osamu Nakamura 0:a40b9a259b52 4662 bufferTail = sliceBuffer(bufferTail, msgLength);
Osamu Nakamura 0:a40b9a259b52 4663 }
Osamu Nakamura 0:a40b9a259b52 4664
Osamu Nakamura 0:a40b9a259b52 4665 var total = buffers.length;
Osamu Nakamura 0:a40b9a259b52 4666 buffers.forEach(function(buffer, i) {
Osamu Nakamura 0:a40b9a259b52 4667 callback(exports.decodePacket(buffer, binaryType, true), i, total);
Osamu Nakamura 0:a40b9a259b52 4668 });
Osamu Nakamura 0:a40b9a259b52 4669 };
Osamu Nakamura 0:a40b9a259b52 4670
Osamu Nakamura 0:a40b9a259b52 4671 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 4672 },{"./keys":26,"after":27,"arraybuffer.slice":28,"base64-arraybuffer":29,"blob":30,"has-binary":31,"utf8":33}],26:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4673
Osamu Nakamura 0:a40b9a259b52 4674 /**
Osamu Nakamura 0:a40b9a259b52 4675 * Gets the keys for an object.
Osamu Nakamura 0:a40b9a259b52 4676 *
Osamu Nakamura 0:a40b9a259b52 4677 * @return {Array} keys
Osamu Nakamura 0:a40b9a259b52 4678 * @api private
Osamu Nakamura 0:a40b9a259b52 4679 */
Osamu Nakamura 0:a40b9a259b52 4680
Osamu Nakamura 0:a40b9a259b52 4681 module.exports = Object.keys || function keys (obj){
Osamu Nakamura 0:a40b9a259b52 4682 var arr = [];
Osamu Nakamura 0:a40b9a259b52 4683 var has = Object.prototype.hasOwnProperty;
Osamu Nakamura 0:a40b9a259b52 4684
Osamu Nakamura 0:a40b9a259b52 4685 for (var i in obj) {
Osamu Nakamura 0:a40b9a259b52 4686 if (has.call(obj, i)) {
Osamu Nakamura 0:a40b9a259b52 4687 arr.push(i);
Osamu Nakamura 0:a40b9a259b52 4688 }
Osamu Nakamura 0:a40b9a259b52 4689 }
Osamu Nakamura 0:a40b9a259b52 4690 return arr;
Osamu Nakamura 0:a40b9a259b52 4691 };
Osamu Nakamura 0:a40b9a259b52 4692
Osamu Nakamura 0:a40b9a259b52 4693 },{}],27:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4694 module.exports = after
Osamu Nakamura 0:a40b9a259b52 4695
Osamu Nakamura 0:a40b9a259b52 4696 function after(count, callback, err_cb) {
Osamu Nakamura 0:a40b9a259b52 4697 var bail = false
Osamu Nakamura 0:a40b9a259b52 4698 err_cb = err_cb || noop
Osamu Nakamura 0:a40b9a259b52 4699 proxy.count = count
Osamu Nakamura 0:a40b9a259b52 4700
Osamu Nakamura 0:a40b9a259b52 4701 return (count === 0) ? callback() : proxy
Osamu Nakamura 0:a40b9a259b52 4702
Osamu Nakamura 0:a40b9a259b52 4703 function proxy(err, result) {
Osamu Nakamura 0:a40b9a259b52 4704 if (proxy.count <= 0) {
Osamu Nakamura 0:a40b9a259b52 4705 throw new Error('after called too many times')
Osamu Nakamura 0:a40b9a259b52 4706 }
Osamu Nakamura 0:a40b9a259b52 4707 --proxy.count
Osamu Nakamura 0:a40b9a259b52 4708
Osamu Nakamura 0:a40b9a259b52 4709 // after first error, rest are passed to err_cb
Osamu Nakamura 0:a40b9a259b52 4710 if (err) {
Osamu Nakamura 0:a40b9a259b52 4711 bail = true
Osamu Nakamura 0:a40b9a259b52 4712 callback(err)
Osamu Nakamura 0:a40b9a259b52 4713 // future error callbacks will go to error handler
Osamu Nakamura 0:a40b9a259b52 4714 callback = err_cb
Osamu Nakamura 0:a40b9a259b52 4715 } else if (proxy.count === 0 && !bail) {
Osamu Nakamura 0:a40b9a259b52 4716 callback(null, result)
Osamu Nakamura 0:a40b9a259b52 4717 }
Osamu Nakamura 0:a40b9a259b52 4718 }
Osamu Nakamura 0:a40b9a259b52 4719 }
Osamu Nakamura 0:a40b9a259b52 4720
Osamu Nakamura 0:a40b9a259b52 4721 function noop() {}
Osamu Nakamura 0:a40b9a259b52 4722
Osamu Nakamura 0:a40b9a259b52 4723 },{}],28:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4724 /**
Osamu Nakamura 0:a40b9a259b52 4725 * An abstraction for slicing an arraybuffer even when
Osamu Nakamura 0:a40b9a259b52 4726 * ArrayBuffer.prototype.slice is not supported
Osamu Nakamura 0:a40b9a259b52 4727 *
Osamu Nakamura 0:a40b9a259b52 4728 * @api public
Osamu Nakamura 0:a40b9a259b52 4729 */
Osamu Nakamura 0:a40b9a259b52 4730
Osamu Nakamura 0:a40b9a259b52 4731 module.exports = function(arraybuffer, start, end) {
Osamu Nakamura 0:a40b9a259b52 4732 var bytes = arraybuffer.byteLength;
Osamu Nakamura 0:a40b9a259b52 4733 start = start || 0;
Osamu Nakamura 0:a40b9a259b52 4734 end = end || bytes;
Osamu Nakamura 0:a40b9a259b52 4735
Osamu Nakamura 0:a40b9a259b52 4736 if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
Osamu Nakamura 0:a40b9a259b52 4737
Osamu Nakamura 0:a40b9a259b52 4738 if (start < 0) { start += bytes; }
Osamu Nakamura 0:a40b9a259b52 4739 if (end < 0) { end += bytes; }
Osamu Nakamura 0:a40b9a259b52 4740 if (end > bytes) { end = bytes; }
Osamu Nakamura 0:a40b9a259b52 4741
Osamu Nakamura 0:a40b9a259b52 4742 if (start >= bytes || start >= end || bytes === 0) {
Osamu Nakamura 0:a40b9a259b52 4743 return new ArrayBuffer(0);
Osamu Nakamura 0:a40b9a259b52 4744 }
Osamu Nakamura 0:a40b9a259b52 4745
Osamu Nakamura 0:a40b9a259b52 4746 var abv = new Uint8Array(arraybuffer);
Osamu Nakamura 0:a40b9a259b52 4747 var result = new Uint8Array(end - start);
Osamu Nakamura 0:a40b9a259b52 4748 for (var i = start, ii = 0; i < end; i++, ii++) {
Osamu Nakamura 0:a40b9a259b52 4749 result[ii] = abv[i];
Osamu Nakamura 0:a40b9a259b52 4750 }
Osamu Nakamura 0:a40b9a259b52 4751 return result.buffer;
Osamu Nakamura 0:a40b9a259b52 4752 };
Osamu Nakamura 0:a40b9a259b52 4753
Osamu Nakamura 0:a40b9a259b52 4754 },{}],29:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4755 /*
Osamu Nakamura 0:a40b9a259b52 4756 * base64-arraybuffer
Osamu Nakamura 0:a40b9a259b52 4757 * https://github.com/niklasvh/base64-arraybuffer
Osamu Nakamura 0:a40b9a259b52 4758 *
Osamu Nakamura 0:a40b9a259b52 4759 * Copyright (c) 2012 Niklas von Hertzen
Osamu Nakamura 0:a40b9a259b52 4760 * Licensed under the MIT license.
Osamu Nakamura 0:a40b9a259b52 4761 */
Osamu Nakamura 0:a40b9a259b52 4762 (function(chars){
Osamu Nakamura 0:a40b9a259b52 4763 "use strict";
Osamu Nakamura 0:a40b9a259b52 4764
Osamu Nakamura 0:a40b9a259b52 4765 exports.encode = function(arraybuffer) {
Osamu Nakamura 0:a40b9a259b52 4766 var bytes = new Uint8Array(arraybuffer),
Osamu Nakamura 0:a40b9a259b52 4767 i, len = bytes.length, base64 = "";
Osamu Nakamura 0:a40b9a259b52 4768
Osamu Nakamura 0:a40b9a259b52 4769 for (i = 0; i < len; i+=3) {
Osamu Nakamura 0:a40b9a259b52 4770 base64 += chars[bytes[i] >> 2];
Osamu Nakamura 0:a40b9a259b52 4771 base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
Osamu Nakamura 0:a40b9a259b52 4772 base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
Osamu Nakamura 0:a40b9a259b52 4773 base64 += chars[bytes[i + 2] & 63];
Osamu Nakamura 0:a40b9a259b52 4774 }
Osamu Nakamura 0:a40b9a259b52 4775
Osamu Nakamura 0:a40b9a259b52 4776 if ((len % 3) === 2) {
Osamu Nakamura 0:a40b9a259b52 4777 base64 = base64.substring(0, base64.length - 1) + "=";
Osamu Nakamura 0:a40b9a259b52 4778 } else if (len % 3 === 1) {
Osamu Nakamura 0:a40b9a259b52 4779 base64 = base64.substring(0, base64.length - 2) + "==";
Osamu Nakamura 0:a40b9a259b52 4780 }
Osamu Nakamura 0:a40b9a259b52 4781
Osamu Nakamura 0:a40b9a259b52 4782 return base64;
Osamu Nakamura 0:a40b9a259b52 4783 };
Osamu Nakamura 0:a40b9a259b52 4784
Osamu Nakamura 0:a40b9a259b52 4785 exports.decode = function(base64) {
Osamu Nakamura 0:a40b9a259b52 4786 var bufferLength = base64.length * 0.75,
Osamu Nakamura 0:a40b9a259b52 4787 len = base64.length, i, p = 0,
Osamu Nakamura 0:a40b9a259b52 4788 encoded1, encoded2, encoded3, encoded4;
Osamu Nakamura 0:a40b9a259b52 4789
Osamu Nakamura 0:a40b9a259b52 4790 if (base64[base64.length - 1] === "=") {
Osamu Nakamura 0:a40b9a259b52 4791 bufferLength--;
Osamu Nakamura 0:a40b9a259b52 4792 if (base64[base64.length - 2] === "=") {
Osamu Nakamura 0:a40b9a259b52 4793 bufferLength--;
Osamu Nakamura 0:a40b9a259b52 4794 }
Osamu Nakamura 0:a40b9a259b52 4795 }
Osamu Nakamura 0:a40b9a259b52 4796
Osamu Nakamura 0:a40b9a259b52 4797 var arraybuffer = new ArrayBuffer(bufferLength),
Osamu Nakamura 0:a40b9a259b52 4798 bytes = new Uint8Array(arraybuffer);
Osamu Nakamura 0:a40b9a259b52 4799
Osamu Nakamura 0:a40b9a259b52 4800 for (i = 0; i < len; i+=4) {
Osamu Nakamura 0:a40b9a259b52 4801 encoded1 = chars.indexOf(base64[i]);
Osamu Nakamura 0:a40b9a259b52 4802 encoded2 = chars.indexOf(base64[i+1]);
Osamu Nakamura 0:a40b9a259b52 4803 encoded3 = chars.indexOf(base64[i+2]);
Osamu Nakamura 0:a40b9a259b52 4804 encoded4 = chars.indexOf(base64[i+3]);
Osamu Nakamura 0:a40b9a259b52 4805
Osamu Nakamura 0:a40b9a259b52 4806 bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
Osamu Nakamura 0:a40b9a259b52 4807 bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
Osamu Nakamura 0:a40b9a259b52 4808 bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
Osamu Nakamura 0:a40b9a259b52 4809 }
Osamu Nakamura 0:a40b9a259b52 4810
Osamu Nakamura 0:a40b9a259b52 4811 return arraybuffer;
Osamu Nakamura 0:a40b9a259b52 4812 };
Osamu Nakamura 0:a40b9a259b52 4813 })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
Osamu Nakamura 0:a40b9a259b52 4814
Osamu Nakamura 0:a40b9a259b52 4815 },{}],30:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4816 (function (global){
Osamu Nakamura 0:a40b9a259b52 4817 /**
Osamu Nakamura 0:a40b9a259b52 4818 * Create a blob builder even when vendor prefixes exist
Osamu Nakamura 0:a40b9a259b52 4819 */
Osamu Nakamura 0:a40b9a259b52 4820
Osamu Nakamura 0:a40b9a259b52 4821 var BlobBuilder = global.BlobBuilder
Osamu Nakamura 0:a40b9a259b52 4822 || global.WebKitBlobBuilder
Osamu Nakamura 0:a40b9a259b52 4823 || global.MSBlobBuilder
Osamu Nakamura 0:a40b9a259b52 4824 || global.MozBlobBuilder;
Osamu Nakamura 0:a40b9a259b52 4825
Osamu Nakamura 0:a40b9a259b52 4826 /**
Osamu Nakamura 0:a40b9a259b52 4827 * Check if Blob constructor is supported
Osamu Nakamura 0:a40b9a259b52 4828 */
Osamu Nakamura 0:a40b9a259b52 4829
Osamu Nakamura 0:a40b9a259b52 4830 var blobSupported = (function() {
Osamu Nakamura 0:a40b9a259b52 4831 try {
Osamu Nakamura 0:a40b9a259b52 4832 var b = new Blob(['hi']);
Osamu Nakamura 0:a40b9a259b52 4833 return b.size == 2;
Osamu Nakamura 0:a40b9a259b52 4834 } catch(e) {
Osamu Nakamura 0:a40b9a259b52 4835 return false;
Osamu Nakamura 0:a40b9a259b52 4836 }
Osamu Nakamura 0:a40b9a259b52 4837 })();
Osamu Nakamura 0:a40b9a259b52 4838
Osamu Nakamura 0:a40b9a259b52 4839 /**
Osamu Nakamura 0:a40b9a259b52 4840 * Check if BlobBuilder is supported
Osamu Nakamura 0:a40b9a259b52 4841 */
Osamu Nakamura 0:a40b9a259b52 4842
Osamu Nakamura 0:a40b9a259b52 4843 var blobBuilderSupported = BlobBuilder
Osamu Nakamura 0:a40b9a259b52 4844 && BlobBuilder.prototype.append
Osamu Nakamura 0:a40b9a259b52 4845 && BlobBuilder.prototype.getBlob;
Osamu Nakamura 0:a40b9a259b52 4846
Osamu Nakamura 0:a40b9a259b52 4847 function BlobBuilderConstructor(ary, options) {
Osamu Nakamura 0:a40b9a259b52 4848 options = options || {};
Osamu Nakamura 0:a40b9a259b52 4849
Osamu Nakamura 0:a40b9a259b52 4850 var bb = new BlobBuilder();
Osamu Nakamura 0:a40b9a259b52 4851 for (var i = 0; i < ary.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4852 bb.append(ary[i]);
Osamu Nakamura 0:a40b9a259b52 4853 }
Osamu Nakamura 0:a40b9a259b52 4854 return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
Osamu Nakamura 0:a40b9a259b52 4855 };
Osamu Nakamura 0:a40b9a259b52 4856
Osamu Nakamura 0:a40b9a259b52 4857 module.exports = (function() {
Osamu Nakamura 0:a40b9a259b52 4858 if (blobSupported) {
Osamu Nakamura 0:a40b9a259b52 4859 return global.Blob;
Osamu Nakamura 0:a40b9a259b52 4860 } else if (blobBuilderSupported) {
Osamu Nakamura 0:a40b9a259b52 4861 return BlobBuilderConstructor;
Osamu Nakamura 0:a40b9a259b52 4862 } else {
Osamu Nakamura 0:a40b9a259b52 4863 return undefined;
Osamu Nakamura 0:a40b9a259b52 4864 }
Osamu Nakamura 0:a40b9a259b52 4865 })();
Osamu Nakamura 0:a40b9a259b52 4866
Osamu Nakamura 0:a40b9a259b52 4867 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 4868 },{}],31:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4869 (function (global){
Osamu Nakamura 0:a40b9a259b52 4870
Osamu Nakamura 0:a40b9a259b52 4871 /*
Osamu Nakamura 0:a40b9a259b52 4872 * Module requirements.
Osamu Nakamura 0:a40b9a259b52 4873 */
Osamu Nakamura 0:a40b9a259b52 4874
Osamu Nakamura 0:a40b9a259b52 4875 var isArray = _dereq_('isarray');
Osamu Nakamura 0:a40b9a259b52 4876
Osamu Nakamura 0:a40b9a259b52 4877 /**
Osamu Nakamura 0:a40b9a259b52 4878 * Module exports.
Osamu Nakamura 0:a40b9a259b52 4879 */
Osamu Nakamura 0:a40b9a259b52 4880
Osamu Nakamura 0:a40b9a259b52 4881 module.exports = hasBinary;
Osamu Nakamura 0:a40b9a259b52 4882
Osamu Nakamura 0:a40b9a259b52 4883 /**
Osamu Nakamura 0:a40b9a259b52 4884 * Checks for binary data.
Osamu Nakamura 0:a40b9a259b52 4885 *
Osamu Nakamura 0:a40b9a259b52 4886 * Right now only Buffer and ArrayBuffer are supported..
Osamu Nakamura 0:a40b9a259b52 4887 *
Osamu Nakamura 0:a40b9a259b52 4888 * @param {Object} anything
Osamu Nakamura 0:a40b9a259b52 4889 * @api public
Osamu Nakamura 0:a40b9a259b52 4890 */
Osamu Nakamura 0:a40b9a259b52 4891
Osamu Nakamura 0:a40b9a259b52 4892 function hasBinary(data) {
Osamu Nakamura 0:a40b9a259b52 4893
Osamu Nakamura 0:a40b9a259b52 4894 function _hasBinary(obj) {
Osamu Nakamura 0:a40b9a259b52 4895 if (!obj) return false;
Osamu Nakamura 0:a40b9a259b52 4896
Osamu Nakamura 0:a40b9a259b52 4897 if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
Osamu Nakamura 0:a40b9a259b52 4898 (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
Osamu Nakamura 0:a40b9a259b52 4899 (global.Blob && obj instanceof Blob) ||
Osamu Nakamura 0:a40b9a259b52 4900 (global.File && obj instanceof File)
Osamu Nakamura 0:a40b9a259b52 4901 ) {
Osamu Nakamura 0:a40b9a259b52 4902 return true;
Osamu Nakamura 0:a40b9a259b52 4903 }
Osamu Nakamura 0:a40b9a259b52 4904
Osamu Nakamura 0:a40b9a259b52 4905 if (isArray(obj)) {
Osamu Nakamura 0:a40b9a259b52 4906 for (var i = 0; i < obj.length; i++) {
Osamu Nakamura 0:a40b9a259b52 4907 if (_hasBinary(obj[i])) {
Osamu Nakamura 0:a40b9a259b52 4908 return true;
Osamu Nakamura 0:a40b9a259b52 4909 }
Osamu Nakamura 0:a40b9a259b52 4910 }
Osamu Nakamura 0:a40b9a259b52 4911 } else if (obj && 'object' == typeof obj) {
Osamu Nakamura 0:a40b9a259b52 4912 if (obj.toJSON) {
Osamu Nakamura 0:a40b9a259b52 4913 obj = obj.toJSON();
Osamu Nakamura 0:a40b9a259b52 4914 }
Osamu Nakamura 0:a40b9a259b52 4915
Osamu Nakamura 0:a40b9a259b52 4916 for (var key in obj) {
Osamu Nakamura 0:a40b9a259b52 4917 if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) {
Osamu Nakamura 0:a40b9a259b52 4918 return true;
Osamu Nakamura 0:a40b9a259b52 4919 }
Osamu Nakamura 0:a40b9a259b52 4920 }
Osamu Nakamura 0:a40b9a259b52 4921 }
Osamu Nakamura 0:a40b9a259b52 4922
Osamu Nakamura 0:a40b9a259b52 4923 return false;
Osamu Nakamura 0:a40b9a259b52 4924 }
Osamu Nakamura 0:a40b9a259b52 4925
Osamu Nakamura 0:a40b9a259b52 4926 return _hasBinary(data);
Osamu Nakamura 0:a40b9a259b52 4927 }
Osamu Nakamura 0:a40b9a259b52 4928
Osamu Nakamura 0:a40b9a259b52 4929 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 4930 },{"isarray":32}],32:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4931 module.exports = Array.isArray || function (arr) {
Osamu Nakamura 0:a40b9a259b52 4932 return Object.prototype.toString.call(arr) == '[object Array]';
Osamu Nakamura 0:a40b9a259b52 4933 };
Osamu Nakamura 0:a40b9a259b52 4934
Osamu Nakamura 0:a40b9a259b52 4935 },{}],33:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 4936 (function (global){
Osamu Nakamura 0:a40b9a259b52 4937 /*! http://mths.be/utf8js v2.0.0 by @mathias */
Osamu Nakamura 0:a40b9a259b52 4938 ;(function(root) {
Osamu Nakamura 0:a40b9a259b52 4939
Osamu Nakamura 0:a40b9a259b52 4940 // Detect free variables `exports`
Osamu Nakamura 0:a40b9a259b52 4941 var freeExports = typeof exports == 'object' && exports;
Osamu Nakamura 0:a40b9a259b52 4942
Osamu Nakamura 0:a40b9a259b52 4943 // Detect free variable `module`
Osamu Nakamura 0:a40b9a259b52 4944 var freeModule = typeof module == 'object' && module &&
Osamu Nakamura 0:a40b9a259b52 4945 module.exports == freeExports && module;
Osamu Nakamura 0:a40b9a259b52 4946
Osamu Nakamura 0:a40b9a259b52 4947 // Detect free variable `global`, from Node.js or Browserified code,
Osamu Nakamura 0:a40b9a259b52 4948 // and use it as `root`
Osamu Nakamura 0:a40b9a259b52 4949 var freeGlobal = typeof global == 'object' && global;
Osamu Nakamura 0:a40b9a259b52 4950 if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
Osamu Nakamura 0:a40b9a259b52 4951 root = freeGlobal;
Osamu Nakamura 0:a40b9a259b52 4952 }
Osamu Nakamura 0:a40b9a259b52 4953
Osamu Nakamura 0:a40b9a259b52 4954 /*--------------------------------------------------------------------------*/
Osamu Nakamura 0:a40b9a259b52 4955
Osamu Nakamura 0:a40b9a259b52 4956 var stringFromCharCode = String.fromCharCode;
Osamu Nakamura 0:a40b9a259b52 4957
Osamu Nakamura 0:a40b9a259b52 4958 // Taken from http://mths.be/punycode
Osamu Nakamura 0:a40b9a259b52 4959 function ucs2decode(string) {
Osamu Nakamura 0:a40b9a259b52 4960 var output = [];
Osamu Nakamura 0:a40b9a259b52 4961 var counter = 0;
Osamu Nakamura 0:a40b9a259b52 4962 var length = string.length;
Osamu Nakamura 0:a40b9a259b52 4963 var value;
Osamu Nakamura 0:a40b9a259b52 4964 var extra;
Osamu Nakamura 0:a40b9a259b52 4965 while (counter < length) {
Osamu Nakamura 0:a40b9a259b52 4966 value = string.charCodeAt(counter++);
Osamu Nakamura 0:a40b9a259b52 4967 if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
Osamu Nakamura 0:a40b9a259b52 4968 // high surrogate, and there is a next character
Osamu Nakamura 0:a40b9a259b52 4969 extra = string.charCodeAt(counter++);
Osamu Nakamura 0:a40b9a259b52 4970 if ((extra & 0xFC00) == 0xDC00) { // low surrogate
Osamu Nakamura 0:a40b9a259b52 4971 output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
Osamu Nakamura 0:a40b9a259b52 4972 } else {
Osamu Nakamura 0:a40b9a259b52 4973 // unmatched surrogate; only append this code unit, in case the next
Osamu Nakamura 0:a40b9a259b52 4974 // code unit is the high surrogate of a surrogate pair
Osamu Nakamura 0:a40b9a259b52 4975 output.push(value);
Osamu Nakamura 0:a40b9a259b52 4976 counter--;
Osamu Nakamura 0:a40b9a259b52 4977 }
Osamu Nakamura 0:a40b9a259b52 4978 } else {
Osamu Nakamura 0:a40b9a259b52 4979 output.push(value);
Osamu Nakamura 0:a40b9a259b52 4980 }
Osamu Nakamura 0:a40b9a259b52 4981 }
Osamu Nakamura 0:a40b9a259b52 4982 return output;
Osamu Nakamura 0:a40b9a259b52 4983 }
Osamu Nakamura 0:a40b9a259b52 4984
Osamu Nakamura 0:a40b9a259b52 4985 // Taken from http://mths.be/punycode
Osamu Nakamura 0:a40b9a259b52 4986 function ucs2encode(array) {
Osamu Nakamura 0:a40b9a259b52 4987 var length = array.length;
Osamu Nakamura 0:a40b9a259b52 4988 var index = -1;
Osamu Nakamura 0:a40b9a259b52 4989 var value;
Osamu Nakamura 0:a40b9a259b52 4990 var output = '';
Osamu Nakamura 0:a40b9a259b52 4991 while (++index < length) {
Osamu Nakamura 0:a40b9a259b52 4992 value = array[index];
Osamu Nakamura 0:a40b9a259b52 4993 if (value > 0xFFFF) {
Osamu Nakamura 0:a40b9a259b52 4994 value -= 0x10000;
Osamu Nakamura 0:a40b9a259b52 4995 output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
Osamu Nakamura 0:a40b9a259b52 4996 value = 0xDC00 | value & 0x3FF;
Osamu Nakamura 0:a40b9a259b52 4997 }
Osamu Nakamura 0:a40b9a259b52 4998 output += stringFromCharCode(value);
Osamu Nakamura 0:a40b9a259b52 4999 }
Osamu Nakamura 0:a40b9a259b52 5000 return output;
Osamu Nakamura 0:a40b9a259b52 5001 }
Osamu Nakamura 0:a40b9a259b52 5002
Osamu Nakamura 0:a40b9a259b52 5003 /*--------------------------------------------------------------------------*/
Osamu Nakamura 0:a40b9a259b52 5004
Osamu Nakamura 0:a40b9a259b52 5005 function createByte(codePoint, shift) {
Osamu Nakamura 0:a40b9a259b52 5006 return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
Osamu Nakamura 0:a40b9a259b52 5007 }
Osamu Nakamura 0:a40b9a259b52 5008
Osamu Nakamura 0:a40b9a259b52 5009 function encodeCodePoint(codePoint) {
Osamu Nakamura 0:a40b9a259b52 5010 if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
Osamu Nakamura 0:a40b9a259b52 5011 return stringFromCharCode(codePoint);
Osamu Nakamura 0:a40b9a259b52 5012 }
Osamu Nakamura 0:a40b9a259b52 5013 var symbol = '';
Osamu Nakamura 0:a40b9a259b52 5014 if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
Osamu Nakamura 0:a40b9a259b52 5015 symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
Osamu Nakamura 0:a40b9a259b52 5016 }
Osamu Nakamura 0:a40b9a259b52 5017 else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
Osamu Nakamura 0:a40b9a259b52 5018 symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
Osamu Nakamura 0:a40b9a259b52 5019 symbol += createByte(codePoint, 6);
Osamu Nakamura 0:a40b9a259b52 5020 }
Osamu Nakamura 0:a40b9a259b52 5021 else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
Osamu Nakamura 0:a40b9a259b52 5022 symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
Osamu Nakamura 0:a40b9a259b52 5023 symbol += createByte(codePoint, 12);
Osamu Nakamura 0:a40b9a259b52 5024 symbol += createByte(codePoint, 6);
Osamu Nakamura 0:a40b9a259b52 5025 }
Osamu Nakamura 0:a40b9a259b52 5026 symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
Osamu Nakamura 0:a40b9a259b52 5027 return symbol;
Osamu Nakamura 0:a40b9a259b52 5028 }
Osamu Nakamura 0:a40b9a259b52 5029
Osamu Nakamura 0:a40b9a259b52 5030 function utf8encode(string) {
Osamu Nakamura 0:a40b9a259b52 5031 var codePoints = ucs2decode(string);
Osamu Nakamura 0:a40b9a259b52 5032
Osamu Nakamura 0:a40b9a259b52 5033 // console.log(JSON.stringify(codePoints.map(function(x) {
Osamu Nakamura 0:a40b9a259b52 5034 // return 'U+' + x.toString(16).toUpperCase();
Osamu Nakamura 0:a40b9a259b52 5035 // })));
Osamu Nakamura 0:a40b9a259b52 5036
Osamu Nakamura 0:a40b9a259b52 5037 var length = codePoints.length;
Osamu Nakamura 0:a40b9a259b52 5038 var index = -1;
Osamu Nakamura 0:a40b9a259b52 5039 var codePoint;
Osamu Nakamura 0:a40b9a259b52 5040 var byteString = '';
Osamu Nakamura 0:a40b9a259b52 5041 while (++index < length) {
Osamu Nakamura 0:a40b9a259b52 5042 codePoint = codePoints[index];
Osamu Nakamura 0:a40b9a259b52 5043 byteString += encodeCodePoint(codePoint);
Osamu Nakamura 0:a40b9a259b52 5044 }
Osamu Nakamura 0:a40b9a259b52 5045 return byteString;
Osamu Nakamura 0:a40b9a259b52 5046 }
Osamu Nakamura 0:a40b9a259b52 5047
Osamu Nakamura 0:a40b9a259b52 5048 /*--------------------------------------------------------------------------*/
Osamu Nakamura 0:a40b9a259b52 5049
Osamu Nakamura 0:a40b9a259b52 5050 function readContinuationByte() {
Osamu Nakamura 0:a40b9a259b52 5051 if (byteIndex >= byteCount) {
Osamu Nakamura 0:a40b9a259b52 5052 throw Error('Invalid byte index');
Osamu Nakamura 0:a40b9a259b52 5053 }
Osamu Nakamura 0:a40b9a259b52 5054
Osamu Nakamura 0:a40b9a259b52 5055 var continuationByte = byteArray[byteIndex] & 0xFF;
Osamu Nakamura 0:a40b9a259b52 5056 byteIndex++;
Osamu Nakamura 0:a40b9a259b52 5057
Osamu Nakamura 0:a40b9a259b52 5058 if ((continuationByte & 0xC0) == 0x80) {
Osamu Nakamura 0:a40b9a259b52 5059 return continuationByte & 0x3F;
Osamu Nakamura 0:a40b9a259b52 5060 }
Osamu Nakamura 0:a40b9a259b52 5061
Osamu Nakamura 0:a40b9a259b52 5062 // If we end up here, it’s not a continuation byte
Osamu Nakamura 0:a40b9a259b52 5063 throw Error('Invalid continuation byte');
Osamu Nakamura 0:a40b9a259b52 5064 }
Osamu Nakamura 0:a40b9a259b52 5065
Osamu Nakamura 0:a40b9a259b52 5066 function decodeSymbol() {
Osamu Nakamura 0:a40b9a259b52 5067 var byte1;
Osamu Nakamura 0:a40b9a259b52 5068 var byte2;
Osamu Nakamura 0:a40b9a259b52 5069 var byte3;
Osamu Nakamura 0:a40b9a259b52 5070 var byte4;
Osamu Nakamura 0:a40b9a259b52 5071 var codePoint;
Osamu Nakamura 0:a40b9a259b52 5072
Osamu Nakamura 0:a40b9a259b52 5073 if (byteIndex > byteCount) {
Osamu Nakamura 0:a40b9a259b52 5074 throw Error('Invalid byte index');
Osamu Nakamura 0:a40b9a259b52 5075 }
Osamu Nakamura 0:a40b9a259b52 5076
Osamu Nakamura 0:a40b9a259b52 5077 if (byteIndex == byteCount) {
Osamu Nakamura 0:a40b9a259b52 5078 return false;
Osamu Nakamura 0:a40b9a259b52 5079 }
Osamu Nakamura 0:a40b9a259b52 5080
Osamu Nakamura 0:a40b9a259b52 5081 // Read first byte
Osamu Nakamura 0:a40b9a259b52 5082 byte1 = byteArray[byteIndex] & 0xFF;
Osamu Nakamura 0:a40b9a259b52 5083 byteIndex++;
Osamu Nakamura 0:a40b9a259b52 5084
Osamu Nakamura 0:a40b9a259b52 5085 // 1-byte sequence (no continuation bytes)
Osamu Nakamura 0:a40b9a259b52 5086 if ((byte1 & 0x80) == 0) {
Osamu Nakamura 0:a40b9a259b52 5087 return byte1;
Osamu Nakamura 0:a40b9a259b52 5088 }
Osamu Nakamura 0:a40b9a259b52 5089
Osamu Nakamura 0:a40b9a259b52 5090 // 2-byte sequence
Osamu Nakamura 0:a40b9a259b52 5091 if ((byte1 & 0xE0) == 0xC0) {
Osamu Nakamura 0:a40b9a259b52 5092 var byte2 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5093 codePoint = ((byte1 & 0x1F) << 6) | byte2;
Osamu Nakamura 0:a40b9a259b52 5094 if (codePoint >= 0x80) {
Osamu Nakamura 0:a40b9a259b52 5095 return codePoint;
Osamu Nakamura 0:a40b9a259b52 5096 } else {
Osamu Nakamura 0:a40b9a259b52 5097 throw Error('Invalid continuation byte');
Osamu Nakamura 0:a40b9a259b52 5098 }
Osamu Nakamura 0:a40b9a259b52 5099 }
Osamu Nakamura 0:a40b9a259b52 5100
Osamu Nakamura 0:a40b9a259b52 5101 // 3-byte sequence (may include unpaired surrogates)
Osamu Nakamura 0:a40b9a259b52 5102 if ((byte1 & 0xF0) == 0xE0) {
Osamu Nakamura 0:a40b9a259b52 5103 byte2 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5104 byte3 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5105 codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
Osamu Nakamura 0:a40b9a259b52 5106 if (codePoint >= 0x0800) {
Osamu Nakamura 0:a40b9a259b52 5107 return codePoint;
Osamu Nakamura 0:a40b9a259b52 5108 } else {
Osamu Nakamura 0:a40b9a259b52 5109 throw Error('Invalid continuation byte');
Osamu Nakamura 0:a40b9a259b52 5110 }
Osamu Nakamura 0:a40b9a259b52 5111 }
Osamu Nakamura 0:a40b9a259b52 5112
Osamu Nakamura 0:a40b9a259b52 5113 // 4-byte sequence
Osamu Nakamura 0:a40b9a259b52 5114 if ((byte1 & 0xF8) == 0xF0) {
Osamu Nakamura 0:a40b9a259b52 5115 byte2 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5116 byte3 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5117 byte4 = readContinuationByte();
Osamu Nakamura 0:a40b9a259b52 5118 codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
Osamu Nakamura 0:a40b9a259b52 5119 (byte3 << 0x06) | byte4;
Osamu Nakamura 0:a40b9a259b52 5120 if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
Osamu Nakamura 0:a40b9a259b52 5121 return codePoint;
Osamu Nakamura 0:a40b9a259b52 5122 }
Osamu Nakamura 0:a40b9a259b52 5123 }
Osamu Nakamura 0:a40b9a259b52 5124
Osamu Nakamura 0:a40b9a259b52 5125 throw Error('Invalid UTF-8 detected');
Osamu Nakamura 0:a40b9a259b52 5126 }
Osamu Nakamura 0:a40b9a259b52 5127
Osamu Nakamura 0:a40b9a259b52 5128 var byteArray;
Osamu Nakamura 0:a40b9a259b52 5129 var byteCount;
Osamu Nakamura 0:a40b9a259b52 5130 var byteIndex;
Osamu Nakamura 0:a40b9a259b52 5131 function utf8decode(byteString) {
Osamu Nakamura 0:a40b9a259b52 5132 byteArray = ucs2decode(byteString);
Osamu Nakamura 0:a40b9a259b52 5133 byteCount = byteArray.length;
Osamu Nakamura 0:a40b9a259b52 5134 byteIndex = 0;
Osamu Nakamura 0:a40b9a259b52 5135 var codePoints = [];
Osamu Nakamura 0:a40b9a259b52 5136 var tmp;
Osamu Nakamura 0:a40b9a259b52 5137 while ((tmp = decodeSymbol()) !== false) {
Osamu Nakamura 0:a40b9a259b52 5138 codePoints.push(tmp);
Osamu Nakamura 0:a40b9a259b52 5139 }
Osamu Nakamura 0:a40b9a259b52 5140 return ucs2encode(codePoints);
Osamu Nakamura 0:a40b9a259b52 5141 }
Osamu Nakamura 0:a40b9a259b52 5142
Osamu Nakamura 0:a40b9a259b52 5143 /*--------------------------------------------------------------------------*/
Osamu Nakamura 0:a40b9a259b52 5144
Osamu Nakamura 0:a40b9a259b52 5145 var utf8 = {
Osamu Nakamura 0:a40b9a259b52 5146 'version': '2.0.0',
Osamu Nakamura 0:a40b9a259b52 5147 'encode': utf8encode,
Osamu Nakamura 0:a40b9a259b52 5148 'decode': utf8decode
Osamu Nakamura 0:a40b9a259b52 5149 };
Osamu Nakamura 0:a40b9a259b52 5150
Osamu Nakamura 0:a40b9a259b52 5151 // Some AMD build optimizers, like r.js, check for specific condition patterns
Osamu Nakamura 0:a40b9a259b52 5152 // like the following:
Osamu Nakamura 0:a40b9a259b52 5153 if (
Osamu Nakamura 0:a40b9a259b52 5154 typeof define == 'function' &&
Osamu Nakamura 0:a40b9a259b52 5155 typeof define.amd == 'object' &&
Osamu Nakamura 0:a40b9a259b52 5156 define.amd
Osamu Nakamura 0:a40b9a259b52 5157 ) {
Osamu Nakamura 0:a40b9a259b52 5158 define(function() {
Osamu Nakamura 0:a40b9a259b52 5159 return utf8;
Osamu Nakamura 0:a40b9a259b52 5160 });
Osamu Nakamura 0:a40b9a259b52 5161 } else if (freeExports && !freeExports.nodeType) {
Osamu Nakamura 0:a40b9a259b52 5162 if (freeModule) { // in Node.js or RingoJS v0.8.0+
Osamu Nakamura 0:a40b9a259b52 5163 freeModule.exports = utf8;
Osamu Nakamura 0:a40b9a259b52 5164 } else { // in Narwhal or RingoJS v0.7.0-
Osamu Nakamura 0:a40b9a259b52 5165 var object = {};
Osamu Nakamura 0:a40b9a259b52 5166 var hasOwnProperty = object.hasOwnProperty;
Osamu Nakamura 0:a40b9a259b52 5167 for (var key in utf8) {
Osamu Nakamura 0:a40b9a259b52 5168 hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
Osamu Nakamura 0:a40b9a259b52 5169 }
Osamu Nakamura 0:a40b9a259b52 5170 }
Osamu Nakamura 0:a40b9a259b52 5171 } else { // in Rhino or a web browser
Osamu Nakamura 0:a40b9a259b52 5172 root.utf8 = utf8;
Osamu Nakamura 0:a40b9a259b52 5173 }
Osamu Nakamura 0:a40b9a259b52 5174
Osamu Nakamura 0:a40b9a259b52 5175 }(this));
Osamu Nakamura 0:a40b9a259b52 5176
Osamu Nakamura 0:a40b9a259b52 5177 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 5178 },{}],34:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5179 (function (global){
Osamu Nakamura 0:a40b9a259b52 5180 /**
Osamu Nakamura 0:a40b9a259b52 5181 * JSON parse.
Osamu Nakamura 0:a40b9a259b52 5182 *
Osamu Nakamura 0:a40b9a259b52 5183 * @see Based on jQuery#parseJSON (MIT) and JSON2
Osamu Nakamura 0:a40b9a259b52 5184 * @api private
Osamu Nakamura 0:a40b9a259b52 5185 */
Osamu Nakamura 0:a40b9a259b52 5186
Osamu Nakamura 0:a40b9a259b52 5187 var rvalidchars = /^[\],:{}\s]*$/;
Osamu Nakamura 0:a40b9a259b52 5188 var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
Osamu Nakamura 0:a40b9a259b52 5189 var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
Osamu Nakamura 0:a40b9a259b52 5190 var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
Osamu Nakamura 0:a40b9a259b52 5191 var rtrimLeft = /^\s+/;
Osamu Nakamura 0:a40b9a259b52 5192 var rtrimRight = /\s+$/;
Osamu Nakamura 0:a40b9a259b52 5193
Osamu Nakamura 0:a40b9a259b52 5194 module.exports = function parsejson(data) {
Osamu Nakamura 0:a40b9a259b52 5195 if ('string' != typeof data || !data) {
Osamu Nakamura 0:a40b9a259b52 5196 return null;
Osamu Nakamura 0:a40b9a259b52 5197 }
Osamu Nakamura 0:a40b9a259b52 5198
Osamu Nakamura 0:a40b9a259b52 5199 data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
Osamu Nakamura 0:a40b9a259b52 5200
Osamu Nakamura 0:a40b9a259b52 5201 // Attempt to parse using the native JSON parser first
Osamu Nakamura 0:a40b9a259b52 5202 if (global.JSON && JSON.parse) {
Osamu Nakamura 0:a40b9a259b52 5203 return JSON.parse(data);
Osamu Nakamura 0:a40b9a259b52 5204 }
Osamu Nakamura 0:a40b9a259b52 5205
Osamu Nakamura 0:a40b9a259b52 5206 if (rvalidchars.test(data.replace(rvalidescape, '@')
Osamu Nakamura 0:a40b9a259b52 5207 .replace(rvalidtokens, ']')
Osamu Nakamura 0:a40b9a259b52 5208 .replace(rvalidbraces, ''))) {
Osamu Nakamura 0:a40b9a259b52 5209 return (new Function('return ' + data))();
Osamu Nakamura 0:a40b9a259b52 5210 }
Osamu Nakamura 0:a40b9a259b52 5211 };
Osamu Nakamura 0:a40b9a259b52 5212 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 5213 },{}],35:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5214 /**
Osamu Nakamura 0:a40b9a259b52 5215 * Compiles a querystring
Osamu Nakamura 0:a40b9a259b52 5216 * Returns string representation of the object
Osamu Nakamura 0:a40b9a259b52 5217 *
Osamu Nakamura 0:a40b9a259b52 5218 * @param {Object}
Osamu Nakamura 0:a40b9a259b52 5219 * @api private
Osamu Nakamura 0:a40b9a259b52 5220 */
Osamu Nakamura 0:a40b9a259b52 5221
Osamu Nakamura 0:a40b9a259b52 5222 exports.encode = function (obj) {
Osamu Nakamura 0:a40b9a259b52 5223 var str = '';
Osamu Nakamura 0:a40b9a259b52 5224
Osamu Nakamura 0:a40b9a259b52 5225 for (var i in obj) {
Osamu Nakamura 0:a40b9a259b52 5226 if (obj.hasOwnProperty(i)) {
Osamu Nakamura 0:a40b9a259b52 5227 if (str.length) str += '&';
Osamu Nakamura 0:a40b9a259b52 5228 str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
Osamu Nakamura 0:a40b9a259b52 5229 }
Osamu Nakamura 0:a40b9a259b52 5230 }
Osamu Nakamura 0:a40b9a259b52 5231
Osamu Nakamura 0:a40b9a259b52 5232 return str;
Osamu Nakamura 0:a40b9a259b52 5233 };
Osamu Nakamura 0:a40b9a259b52 5234
Osamu Nakamura 0:a40b9a259b52 5235 /**
Osamu Nakamura 0:a40b9a259b52 5236 * Parses a simple querystring into an object
Osamu Nakamura 0:a40b9a259b52 5237 *
Osamu Nakamura 0:a40b9a259b52 5238 * @param {String} qs
Osamu Nakamura 0:a40b9a259b52 5239 * @api private
Osamu Nakamura 0:a40b9a259b52 5240 */
Osamu Nakamura 0:a40b9a259b52 5241
Osamu Nakamura 0:a40b9a259b52 5242 exports.decode = function(qs){
Osamu Nakamura 0:a40b9a259b52 5243 var qry = {};
Osamu Nakamura 0:a40b9a259b52 5244 var pairs = qs.split('&');
Osamu Nakamura 0:a40b9a259b52 5245 for (var i = 0, l = pairs.length; i < l; i++) {
Osamu Nakamura 0:a40b9a259b52 5246 var pair = pairs[i].split('=');
Osamu Nakamura 0:a40b9a259b52 5247 qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
Osamu Nakamura 0:a40b9a259b52 5248 }
Osamu Nakamura 0:a40b9a259b52 5249 return qry;
Osamu Nakamura 0:a40b9a259b52 5250 };
Osamu Nakamura 0:a40b9a259b52 5251
Osamu Nakamura 0:a40b9a259b52 5252 },{}],36:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5253 /**
Osamu Nakamura 0:a40b9a259b52 5254 * Parses an URI
Osamu Nakamura 0:a40b9a259b52 5255 *
Osamu Nakamura 0:a40b9a259b52 5256 * @author Steven Levithan <stevenlevithan.com> (MIT license)
Osamu Nakamura 0:a40b9a259b52 5257 * @api private
Osamu Nakamura 0:a40b9a259b52 5258 */
Osamu Nakamura 0:a40b9a259b52 5259
Osamu Nakamura 0:a40b9a259b52 5260 var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
Osamu Nakamura 0:a40b9a259b52 5261
Osamu Nakamura 0:a40b9a259b52 5262 var parts = [
Osamu Nakamura 0:a40b9a259b52 5263 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
Osamu Nakamura 0:a40b9a259b52 5264 ];
Osamu Nakamura 0:a40b9a259b52 5265
Osamu Nakamura 0:a40b9a259b52 5266 module.exports = function parseuri(str) {
Osamu Nakamura 0:a40b9a259b52 5267 var src = str,
Osamu Nakamura 0:a40b9a259b52 5268 b = str.indexOf('['),
Osamu Nakamura 0:a40b9a259b52 5269 e = str.indexOf(']');
Osamu Nakamura 0:a40b9a259b52 5270
Osamu Nakamura 0:a40b9a259b52 5271 if (b != -1 && e != -1) {
Osamu Nakamura 0:a40b9a259b52 5272 str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
Osamu Nakamura 0:a40b9a259b52 5273 }
Osamu Nakamura 0:a40b9a259b52 5274
Osamu Nakamura 0:a40b9a259b52 5275 var m = re.exec(str || ''),
Osamu Nakamura 0:a40b9a259b52 5276 uri = {},
Osamu Nakamura 0:a40b9a259b52 5277 i = 14;
Osamu Nakamura 0:a40b9a259b52 5278
Osamu Nakamura 0:a40b9a259b52 5279 while (i--) {
Osamu Nakamura 0:a40b9a259b52 5280 uri[parts[i]] = m[i] || '';
Osamu Nakamura 0:a40b9a259b52 5281 }
Osamu Nakamura 0:a40b9a259b52 5282
Osamu Nakamura 0:a40b9a259b52 5283 if (b != -1 && e != -1) {
Osamu Nakamura 0:a40b9a259b52 5284 uri.source = src;
Osamu Nakamura 0:a40b9a259b52 5285 uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
Osamu Nakamura 0:a40b9a259b52 5286 uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
Osamu Nakamura 0:a40b9a259b52 5287 uri.ipv6uri = true;
Osamu Nakamura 0:a40b9a259b52 5288 }
Osamu Nakamura 0:a40b9a259b52 5289
Osamu Nakamura 0:a40b9a259b52 5290 return uri;
Osamu Nakamura 0:a40b9a259b52 5291 };
Osamu Nakamura 0:a40b9a259b52 5292
Osamu Nakamura 0:a40b9a259b52 5293 },{}],37:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5294
Osamu Nakamura 0:a40b9a259b52 5295 /**
Osamu Nakamura 0:a40b9a259b52 5296 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 5297 */
Osamu Nakamura 0:a40b9a259b52 5298
Osamu Nakamura 0:a40b9a259b52 5299 var global = (function() { return this; })();
Osamu Nakamura 0:a40b9a259b52 5300
Osamu Nakamura 0:a40b9a259b52 5301 /**
Osamu Nakamura 0:a40b9a259b52 5302 * WebSocket constructor.
Osamu Nakamura 0:a40b9a259b52 5303 */
Osamu Nakamura 0:a40b9a259b52 5304
Osamu Nakamura 0:a40b9a259b52 5305 var WebSocket = global.WebSocket || global.MozWebSocket;
Osamu Nakamura 0:a40b9a259b52 5306
Osamu Nakamura 0:a40b9a259b52 5307 /**
Osamu Nakamura 0:a40b9a259b52 5308 * Module exports.
Osamu Nakamura 0:a40b9a259b52 5309 */
Osamu Nakamura 0:a40b9a259b52 5310
Osamu Nakamura 0:a40b9a259b52 5311 module.exports = WebSocket ? ws : null;
Osamu Nakamura 0:a40b9a259b52 5312
Osamu Nakamura 0:a40b9a259b52 5313 /**
Osamu Nakamura 0:a40b9a259b52 5314 * WebSocket constructor.
Osamu Nakamura 0:a40b9a259b52 5315 *
Osamu Nakamura 0:a40b9a259b52 5316 * The third `opts` options object gets ignored in web browsers, since it's
Osamu Nakamura 0:a40b9a259b52 5317 * non-standard, and throws a TypeError if passed to the constructor.
Osamu Nakamura 0:a40b9a259b52 5318 * See: https://github.com/einaros/ws/issues/227
Osamu Nakamura 0:a40b9a259b52 5319 *
Osamu Nakamura 0:a40b9a259b52 5320 * @param {String} uri
Osamu Nakamura 0:a40b9a259b52 5321 * @param {Array} protocols (optional)
Osamu Nakamura 0:a40b9a259b52 5322 * @param {Object) opts (optional)
Osamu Nakamura 0:a40b9a259b52 5323 * @api public
Osamu Nakamura 0:a40b9a259b52 5324 */
Osamu Nakamura 0:a40b9a259b52 5325
Osamu Nakamura 0:a40b9a259b52 5326 function ws(uri, protocols, opts) {
Osamu Nakamura 0:a40b9a259b52 5327 var instance;
Osamu Nakamura 0:a40b9a259b52 5328 if (protocols) {
Osamu Nakamura 0:a40b9a259b52 5329 instance = new WebSocket(uri, protocols);
Osamu Nakamura 0:a40b9a259b52 5330 } else {
Osamu Nakamura 0:a40b9a259b52 5331 instance = new WebSocket(uri);
Osamu Nakamura 0:a40b9a259b52 5332 }
Osamu Nakamura 0:a40b9a259b52 5333 return instance;
Osamu Nakamura 0:a40b9a259b52 5334 }
Osamu Nakamura 0:a40b9a259b52 5335
Osamu Nakamura 0:a40b9a259b52 5336 if (WebSocket) ws.prototype = WebSocket.prototype;
Osamu Nakamura 0:a40b9a259b52 5337
Osamu Nakamura 0:a40b9a259b52 5338 },{}],38:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5339 (function (global){
Osamu Nakamura 0:a40b9a259b52 5340
Osamu Nakamura 0:a40b9a259b52 5341 /*
Osamu Nakamura 0:a40b9a259b52 5342 * Module requirements.
Osamu Nakamura 0:a40b9a259b52 5343 */
Osamu Nakamura 0:a40b9a259b52 5344
Osamu Nakamura 0:a40b9a259b52 5345 var isArray = _dereq_('isarray');
Osamu Nakamura 0:a40b9a259b52 5346
Osamu Nakamura 0:a40b9a259b52 5347 /**
Osamu Nakamura 0:a40b9a259b52 5348 * Module exports.
Osamu Nakamura 0:a40b9a259b52 5349 */
Osamu Nakamura 0:a40b9a259b52 5350
Osamu Nakamura 0:a40b9a259b52 5351 module.exports = hasBinary;
Osamu Nakamura 0:a40b9a259b52 5352
Osamu Nakamura 0:a40b9a259b52 5353 /**
Osamu Nakamura 0:a40b9a259b52 5354 * Checks for binary data.
Osamu Nakamura 0:a40b9a259b52 5355 *
Osamu Nakamura 0:a40b9a259b52 5356 * Right now only Buffer and ArrayBuffer are supported..
Osamu Nakamura 0:a40b9a259b52 5357 *
Osamu Nakamura 0:a40b9a259b52 5358 * @param {Object} anything
Osamu Nakamura 0:a40b9a259b52 5359 * @api public
Osamu Nakamura 0:a40b9a259b52 5360 */
Osamu Nakamura 0:a40b9a259b52 5361
Osamu Nakamura 0:a40b9a259b52 5362 function hasBinary(data) {
Osamu Nakamura 0:a40b9a259b52 5363
Osamu Nakamura 0:a40b9a259b52 5364 function _hasBinary(obj) {
Osamu Nakamura 0:a40b9a259b52 5365 if (!obj) return false;
Osamu Nakamura 0:a40b9a259b52 5366
Osamu Nakamura 0:a40b9a259b52 5367 if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
Osamu Nakamura 0:a40b9a259b52 5368 (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
Osamu Nakamura 0:a40b9a259b52 5369 (global.Blob && obj instanceof Blob) ||
Osamu Nakamura 0:a40b9a259b52 5370 (global.File && obj instanceof File)
Osamu Nakamura 0:a40b9a259b52 5371 ) {
Osamu Nakamura 0:a40b9a259b52 5372 return true;
Osamu Nakamura 0:a40b9a259b52 5373 }
Osamu Nakamura 0:a40b9a259b52 5374
Osamu Nakamura 0:a40b9a259b52 5375 if (isArray(obj)) {
Osamu Nakamura 0:a40b9a259b52 5376 for (var i = 0; i < obj.length; i++) {
Osamu Nakamura 0:a40b9a259b52 5377 if (_hasBinary(obj[i])) {
Osamu Nakamura 0:a40b9a259b52 5378 return true;
Osamu Nakamura 0:a40b9a259b52 5379 }
Osamu Nakamura 0:a40b9a259b52 5380 }
Osamu Nakamura 0:a40b9a259b52 5381 } else if (obj && 'object' == typeof obj) {
Osamu Nakamura 0:a40b9a259b52 5382 if (obj.toJSON) {
Osamu Nakamura 0:a40b9a259b52 5383 obj = obj.toJSON();
Osamu Nakamura 0:a40b9a259b52 5384 }
Osamu Nakamura 0:a40b9a259b52 5385
Osamu Nakamura 0:a40b9a259b52 5386 for (var key in obj) {
Osamu Nakamura 0:a40b9a259b52 5387 if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
Osamu Nakamura 0:a40b9a259b52 5388 return true;
Osamu Nakamura 0:a40b9a259b52 5389 }
Osamu Nakamura 0:a40b9a259b52 5390 }
Osamu Nakamura 0:a40b9a259b52 5391 }
Osamu Nakamura 0:a40b9a259b52 5392
Osamu Nakamura 0:a40b9a259b52 5393 return false;
Osamu Nakamura 0:a40b9a259b52 5394 }
Osamu Nakamura 0:a40b9a259b52 5395
Osamu Nakamura 0:a40b9a259b52 5396 return _hasBinary(data);
Osamu Nakamura 0:a40b9a259b52 5397 }
Osamu Nakamura 0:a40b9a259b52 5398
Osamu Nakamura 0:a40b9a259b52 5399 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 5400 },{"isarray":39}],39:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5401 module.exports=_dereq_(32)
Osamu Nakamura 0:a40b9a259b52 5402 },{}],40:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5403
Osamu Nakamura 0:a40b9a259b52 5404 /**
Osamu Nakamura 0:a40b9a259b52 5405 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 5406 */
Osamu Nakamura 0:a40b9a259b52 5407
Osamu Nakamura 0:a40b9a259b52 5408 var global = _dereq_('global');
Osamu Nakamura 0:a40b9a259b52 5409
Osamu Nakamura 0:a40b9a259b52 5410 /**
Osamu Nakamura 0:a40b9a259b52 5411 * Module exports.
Osamu Nakamura 0:a40b9a259b52 5412 *
Osamu Nakamura 0:a40b9a259b52 5413 * Logic borrowed from Modernizr:
Osamu Nakamura 0:a40b9a259b52 5414 *
Osamu Nakamura 0:a40b9a259b52 5415 * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
Osamu Nakamura 0:a40b9a259b52 5416 */
Osamu Nakamura 0:a40b9a259b52 5417
Osamu Nakamura 0:a40b9a259b52 5418 try {
Osamu Nakamura 0:a40b9a259b52 5419 module.exports = 'XMLHttpRequest' in global &&
Osamu Nakamura 0:a40b9a259b52 5420 'withCredentials' in new global.XMLHttpRequest();
Osamu Nakamura 0:a40b9a259b52 5421 } catch (err) {
Osamu Nakamura 0:a40b9a259b52 5422 // if XMLHttp support is disabled in IE then it will throw
Osamu Nakamura 0:a40b9a259b52 5423 // when trying to create
Osamu Nakamura 0:a40b9a259b52 5424 module.exports = false;
Osamu Nakamura 0:a40b9a259b52 5425 }
Osamu Nakamura 0:a40b9a259b52 5426
Osamu Nakamura 0:a40b9a259b52 5427 },{"global":41}],41:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5428
Osamu Nakamura 0:a40b9a259b52 5429 /**
Osamu Nakamura 0:a40b9a259b52 5430 * Returns `this`. Execute this without a "context" (i.e. without it being
Osamu Nakamura 0:a40b9a259b52 5431 * attached to an object of the left-hand side), and `this` points to the
Osamu Nakamura 0:a40b9a259b52 5432 * "global" scope of the current JS execution.
Osamu Nakamura 0:a40b9a259b52 5433 */
Osamu Nakamura 0:a40b9a259b52 5434
Osamu Nakamura 0:a40b9a259b52 5435 module.exports = (function () { return this; })();
Osamu Nakamura 0:a40b9a259b52 5436
Osamu Nakamura 0:a40b9a259b52 5437 },{}],42:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5438
Osamu Nakamura 0:a40b9a259b52 5439 var indexOf = [].indexOf;
Osamu Nakamura 0:a40b9a259b52 5440
Osamu Nakamura 0:a40b9a259b52 5441 module.exports = function(arr, obj){
Osamu Nakamura 0:a40b9a259b52 5442 if (indexOf) return arr.indexOf(obj);
Osamu Nakamura 0:a40b9a259b52 5443 for (var i = 0; i < arr.length; ++i) {
Osamu Nakamura 0:a40b9a259b52 5444 if (arr[i] === obj) return i;
Osamu Nakamura 0:a40b9a259b52 5445 }
Osamu Nakamura 0:a40b9a259b52 5446 return -1;
Osamu Nakamura 0:a40b9a259b52 5447 };
Osamu Nakamura 0:a40b9a259b52 5448 },{}],43:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5449
Osamu Nakamura 0:a40b9a259b52 5450 /**
Osamu Nakamura 0:a40b9a259b52 5451 * HOP ref.
Osamu Nakamura 0:a40b9a259b52 5452 */
Osamu Nakamura 0:a40b9a259b52 5453
Osamu Nakamura 0:a40b9a259b52 5454 var has = Object.prototype.hasOwnProperty;
Osamu Nakamura 0:a40b9a259b52 5455
Osamu Nakamura 0:a40b9a259b52 5456 /**
Osamu Nakamura 0:a40b9a259b52 5457 * Return own keys in `obj`.
Osamu Nakamura 0:a40b9a259b52 5458 *
Osamu Nakamura 0:a40b9a259b52 5459 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 5460 * @return {Array}
Osamu Nakamura 0:a40b9a259b52 5461 * @api public
Osamu Nakamura 0:a40b9a259b52 5462 */
Osamu Nakamura 0:a40b9a259b52 5463
Osamu Nakamura 0:a40b9a259b52 5464 exports.keys = Object.keys || function(obj){
Osamu Nakamura 0:a40b9a259b52 5465 var keys = [];
Osamu Nakamura 0:a40b9a259b52 5466 for (var key in obj) {
Osamu Nakamura 0:a40b9a259b52 5467 if (has.call(obj, key)) {
Osamu Nakamura 0:a40b9a259b52 5468 keys.push(key);
Osamu Nakamura 0:a40b9a259b52 5469 }
Osamu Nakamura 0:a40b9a259b52 5470 }
Osamu Nakamura 0:a40b9a259b52 5471 return keys;
Osamu Nakamura 0:a40b9a259b52 5472 };
Osamu Nakamura 0:a40b9a259b52 5473
Osamu Nakamura 0:a40b9a259b52 5474 /**
Osamu Nakamura 0:a40b9a259b52 5475 * Return own values in `obj`.
Osamu Nakamura 0:a40b9a259b52 5476 *
Osamu Nakamura 0:a40b9a259b52 5477 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 5478 * @return {Array}
Osamu Nakamura 0:a40b9a259b52 5479 * @api public
Osamu Nakamura 0:a40b9a259b52 5480 */
Osamu Nakamura 0:a40b9a259b52 5481
Osamu Nakamura 0:a40b9a259b52 5482 exports.values = function(obj){
Osamu Nakamura 0:a40b9a259b52 5483 var vals = [];
Osamu Nakamura 0:a40b9a259b52 5484 for (var key in obj) {
Osamu Nakamura 0:a40b9a259b52 5485 if (has.call(obj, key)) {
Osamu Nakamura 0:a40b9a259b52 5486 vals.push(obj[key]);
Osamu Nakamura 0:a40b9a259b52 5487 }
Osamu Nakamura 0:a40b9a259b52 5488 }
Osamu Nakamura 0:a40b9a259b52 5489 return vals;
Osamu Nakamura 0:a40b9a259b52 5490 };
Osamu Nakamura 0:a40b9a259b52 5491
Osamu Nakamura 0:a40b9a259b52 5492 /**
Osamu Nakamura 0:a40b9a259b52 5493 * Merge `b` into `a`.
Osamu Nakamura 0:a40b9a259b52 5494 *
Osamu Nakamura 0:a40b9a259b52 5495 * @param {Object} a
Osamu Nakamura 0:a40b9a259b52 5496 * @param {Object} b
Osamu Nakamura 0:a40b9a259b52 5497 * @return {Object} a
Osamu Nakamura 0:a40b9a259b52 5498 * @api public
Osamu Nakamura 0:a40b9a259b52 5499 */
Osamu Nakamura 0:a40b9a259b52 5500
Osamu Nakamura 0:a40b9a259b52 5501 exports.merge = function(a, b){
Osamu Nakamura 0:a40b9a259b52 5502 for (var key in b) {
Osamu Nakamura 0:a40b9a259b52 5503 if (has.call(b, key)) {
Osamu Nakamura 0:a40b9a259b52 5504 a[key] = b[key];
Osamu Nakamura 0:a40b9a259b52 5505 }
Osamu Nakamura 0:a40b9a259b52 5506 }
Osamu Nakamura 0:a40b9a259b52 5507 return a;
Osamu Nakamura 0:a40b9a259b52 5508 };
Osamu Nakamura 0:a40b9a259b52 5509
Osamu Nakamura 0:a40b9a259b52 5510 /**
Osamu Nakamura 0:a40b9a259b52 5511 * Return length of `obj`.
Osamu Nakamura 0:a40b9a259b52 5512 *
Osamu Nakamura 0:a40b9a259b52 5513 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 5514 * @return {Number}
Osamu Nakamura 0:a40b9a259b52 5515 * @api public
Osamu Nakamura 0:a40b9a259b52 5516 */
Osamu Nakamura 0:a40b9a259b52 5517
Osamu Nakamura 0:a40b9a259b52 5518 exports.length = function(obj){
Osamu Nakamura 0:a40b9a259b52 5519 return exports.keys(obj).length;
Osamu Nakamura 0:a40b9a259b52 5520 };
Osamu Nakamura 0:a40b9a259b52 5521
Osamu Nakamura 0:a40b9a259b52 5522 /**
Osamu Nakamura 0:a40b9a259b52 5523 * Check if `obj` is empty.
Osamu Nakamura 0:a40b9a259b52 5524 *
Osamu Nakamura 0:a40b9a259b52 5525 * @param {Object} obj
Osamu Nakamura 0:a40b9a259b52 5526 * @return {Boolean}
Osamu Nakamura 0:a40b9a259b52 5527 * @api public
Osamu Nakamura 0:a40b9a259b52 5528 */
Osamu Nakamura 0:a40b9a259b52 5529
Osamu Nakamura 0:a40b9a259b52 5530 exports.isEmpty = function(obj){
Osamu Nakamura 0:a40b9a259b52 5531 return 0 == exports.length(obj);
Osamu Nakamura 0:a40b9a259b52 5532 };
Osamu Nakamura 0:a40b9a259b52 5533 },{}],44:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5534 /**
Osamu Nakamura 0:a40b9a259b52 5535 * Parses an URI
Osamu Nakamura 0:a40b9a259b52 5536 *
Osamu Nakamura 0:a40b9a259b52 5537 * @author Steven Levithan <stevenlevithan.com> (MIT license)
Osamu Nakamura 0:a40b9a259b52 5538 * @api private
Osamu Nakamura 0:a40b9a259b52 5539 */
Osamu Nakamura 0:a40b9a259b52 5540
Osamu Nakamura 0:a40b9a259b52 5541 var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
Osamu Nakamura 0:a40b9a259b52 5542
Osamu Nakamura 0:a40b9a259b52 5543 var parts = [
Osamu Nakamura 0:a40b9a259b52 5544 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host'
Osamu Nakamura 0:a40b9a259b52 5545 , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
Osamu Nakamura 0:a40b9a259b52 5546 ];
Osamu Nakamura 0:a40b9a259b52 5547
Osamu Nakamura 0:a40b9a259b52 5548 module.exports = function parseuri(str) {
Osamu Nakamura 0:a40b9a259b52 5549 var m = re.exec(str || '')
Osamu Nakamura 0:a40b9a259b52 5550 , uri = {}
Osamu Nakamura 0:a40b9a259b52 5551 , i = 14;
Osamu Nakamura 0:a40b9a259b52 5552
Osamu Nakamura 0:a40b9a259b52 5553 while (i--) {
Osamu Nakamura 0:a40b9a259b52 5554 uri[parts[i]] = m[i] || '';
Osamu Nakamura 0:a40b9a259b52 5555 }
Osamu Nakamura 0:a40b9a259b52 5556
Osamu Nakamura 0:a40b9a259b52 5557 return uri;
Osamu Nakamura 0:a40b9a259b52 5558 };
Osamu Nakamura 0:a40b9a259b52 5559
Osamu Nakamura 0:a40b9a259b52 5560 },{}],45:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5561 (function (global){
Osamu Nakamura 0:a40b9a259b52 5562 /*global Blob,File*/
Osamu Nakamura 0:a40b9a259b52 5563
Osamu Nakamura 0:a40b9a259b52 5564 /**
Osamu Nakamura 0:a40b9a259b52 5565 * Module requirements
Osamu Nakamura 0:a40b9a259b52 5566 */
Osamu Nakamura 0:a40b9a259b52 5567
Osamu Nakamura 0:a40b9a259b52 5568 var isArray = _dereq_('isarray');
Osamu Nakamura 0:a40b9a259b52 5569 var isBuf = _dereq_('./is-buffer');
Osamu Nakamura 0:a40b9a259b52 5570
Osamu Nakamura 0:a40b9a259b52 5571 /**
Osamu Nakamura 0:a40b9a259b52 5572 * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
Osamu Nakamura 0:a40b9a259b52 5573 * Anything with blobs or files should be fed through removeBlobs before coming
Osamu Nakamura 0:a40b9a259b52 5574 * here.
Osamu Nakamura 0:a40b9a259b52 5575 *
Osamu Nakamura 0:a40b9a259b52 5576 * @param {Object} packet - socket.io event packet
Osamu Nakamura 0:a40b9a259b52 5577 * @return {Object} with deconstructed packet and list of buffers
Osamu Nakamura 0:a40b9a259b52 5578 * @api public
Osamu Nakamura 0:a40b9a259b52 5579 */
Osamu Nakamura 0:a40b9a259b52 5580
Osamu Nakamura 0:a40b9a259b52 5581 exports.deconstructPacket = function(packet){
Osamu Nakamura 0:a40b9a259b52 5582 var buffers = [];
Osamu Nakamura 0:a40b9a259b52 5583 var packetData = packet.data;
Osamu Nakamura 0:a40b9a259b52 5584
Osamu Nakamura 0:a40b9a259b52 5585 function _deconstructPacket(data) {
Osamu Nakamura 0:a40b9a259b52 5586 if (!data) return data;
Osamu Nakamura 0:a40b9a259b52 5587
Osamu Nakamura 0:a40b9a259b52 5588 if (isBuf(data)) {
Osamu Nakamura 0:a40b9a259b52 5589 var placeholder = { _placeholder: true, num: buffers.length };
Osamu Nakamura 0:a40b9a259b52 5590 buffers.push(data);
Osamu Nakamura 0:a40b9a259b52 5591 return placeholder;
Osamu Nakamura 0:a40b9a259b52 5592 } else if (isArray(data)) {
Osamu Nakamura 0:a40b9a259b52 5593 var newData = new Array(data.length);
Osamu Nakamura 0:a40b9a259b52 5594 for (var i = 0; i < data.length; i++) {
Osamu Nakamura 0:a40b9a259b52 5595 newData[i] = _deconstructPacket(data[i]);
Osamu Nakamura 0:a40b9a259b52 5596 }
Osamu Nakamura 0:a40b9a259b52 5597 return newData;
Osamu Nakamura 0:a40b9a259b52 5598 } else if ('object' == typeof data && !(data instanceof Date)) {
Osamu Nakamura 0:a40b9a259b52 5599 var newData = {};
Osamu Nakamura 0:a40b9a259b52 5600 for (var key in data) {
Osamu Nakamura 0:a40b9a259b52 5601 newData[key] = _deconstructPacket(data[key]);
Osamu Nakamura 0:a40b9a259b52 5602 }
Osamu Nakamura 0:a40b9a259b52 5603 return newData;
Osamu Nakamura 0:a40b9a259b52 5604 }
Osamu Nakamura 0:a40b9a259b52 5605 return data;
Osamu Nakamura 0:a40b9a259b52 5606 }
Osamu Nakamura 0:a40b9a259b52 5607
Osamu Nakamura 0:a40b9a259b52 5608 var pack = packet;
Osamu Nakamura 0:a40b9a259b52 5609 pack.data = _deconstructPacket(packetData);
Osamu Nakamura 0:a40b9a259b52 5610 pack.attachments = buffers.length; // number of binary 'attachments'
Osamu Nakamura 0:a40b9a259b52 5611 return {packet: pack, buffers: buffers};
Osamu Nakamura 0:a40b9a259b52 5612 };
Osamu Nakamura 0:a40b9a259b52 5613
Osamu Nakamura 0:a40b9a259b52 5614 /**
Osamu Nakamura 0:a40b9a259b52 5615 * Reconstructs a binary packet from its placeholder packet and buffers
Osamu Nakamura 0:a40b9a259b52 5616 *
Osamu Nakamura 0:a40b9a259b52 5617 * @param {Object} packet - event packet with placeholders
Osamu Nakamura 0:a40b9a259b52 5618 * @param {Array} buffers - binary buffers to put in placeholder positions
Osamu Nakamura 0:a40b9a259b52 5619 * @return {Object} reconstructed packet
Osamu Nakamura 0:a40b9a259b52 5620 * @api public
Osamu Nakamura 0:a40b9a259b52 5621 */
Osamu Nakamura 0:a40b9a259b52 5622
Osamu Nakamura 0:a40b9a259b52 5623 exports.reconstructPacket = function(packet, buffers) {
Osamu Nakamura 0:a40b9a259b52 5624 var curPlaceHolder = 0;
Osamu Nakamura 0:a40b9a259b52 5625
Osamu Nakamura 0:a40b9a259b52 5626 function _reconstructPacket(data) {
Osamu Nakamura 0:a40b9a259b52 5627 if (data && data._placeholder) {
Osamu Nakamura 0:a40b9a259b52 5628 var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
Osamu Nakamura 0:a40b9a259b52 5629 return buf;
Osamu Nakamura 0:a40b9a259b52 5630 } else if (isArray(data)) {
Osamu Nakamura 0:a40b9a259b52 5631 for (var i = 0; i < data.length; i++) {
Osamu Nakamura 0:a40b9a259b52 5632 data[i] = _reconstructPacket(data[i]);
Osamu Nakamura 0:a40b9a259b52 5633 }
Osamu Nakamura 0:a40b9a259b52 5634 return data;
Osamu Nakamura 0:a40b9a259b52 5635 } else if (data && 'object' == typeof data) {
Osamu Nakamura 0:a40b9a259b52 5636 for (var key in data) {
Osamu Nakamura 0:a40b9a259b52 5637 data[key] = _reconstructPacket(data[key]);
Osamu Nakamura 0:a40b9a259b52 5638 }
Osamu Nakamura 0:a40b9a259b52 5639 return data;
Osamu Nakamura 0:a40b9a259b52 5640 }
Osamu Nakamura 0:a40b9a259b52 5641 return data;
Osamu Nakamura 0:a40b9a259b52 5642 }
Osamu Nakamura 0:a40b9a259b52 5643
Osamu Nakamura 0:a40b9a259b52 5644 packet.data = _reconstructPacket(packet.data);
Osamu Nakamura 0:a40b9a259b52 5645 packet.attachments = undefined; // no longer useful
Osamu Nakamura 0:a40b9a259b52 5646 return packet;
Osamu Nakamura 0:a40b9a259b52 5647 };
Osamu Nakamura 0:a40b9a259b52 5648
Osamu Nakamura 0:a40b9a259b52 5649 /**
Osamu Nakamura 0:a40b9a259b52 5650 * Asynchronously removes Blobs or Files from data via
Osamu Nakamura 0:a40b9a259b52 5651 * FileReader's readAsArrayBuffer method. Used before encoding
Osamu Nakamura 0:a40b9a259b52 5652 * data as msgpack. Calls callback with the blobless data.
Osamu Nakamura 0:a40b9a259b52 5653 *
Osamu Nakamura 0:a40b9a259b52 5654 * @param {Object} data
Osamu Nakamura 0:a40b9a259b52 5655 * @param {Function} callback
Osamu Nakamura 0:a40b9a259b52 5656 * @api private
Osamu Nakamura 0:a40b9a259b52 5657 */
Osamu Nakamura 0:a40b9a259b52 5658
Osamu Nakamura 0:a40b9a259b52 5659 exports.removeBlobs = function(data, callback) {
Osamu Nakamura 0:a40b9a259b52 5660 function _removeBlobs(obj, curKey, containingObject) {
Osamu Nakamura 0:a40b9a259b52 5661 if (!obj) return obj;
Osamu Nakamura 0:a40b9a259b52 5662
Osamu Nakamura 0:a40b9a259b52 5663 // convert any blob
Osamu Nakamura 0:a40b9a259b52 5664 if ((global.Blob && obj instanceof Blob) ||
Osamu Nakamura 0:a40b9a259b52 5665 (global.File && obj instanceof File)) {
Osamu Nakamura 0:a40b9a259b52 5666 pendingBlobs++;
Osamu Nakamura 0:a40b9a259b52 5667
Osamu Nakamura 0:a40b9a259b52 5668 // async filereader
Osamu Nakamura 0:a40b9a259b52 5669 var fileReader = new FileReader();
Osamu Nakamura 0:a40b9a259b52 5670 fileReader.onload = function() { // this.result == arraybuffer
Osamu Nakamura 0:a40b9a259b52 5671 if (containingObject) {
Osamu Nakamura 0:a40b9a259b52 5672 containingObject[curKey] = this.result;
Osamu Nakamura 0:a40b9a259b52 5673 }
Osamu Nakamura 0:a40b9a259b52 5674 else {
Osamu Nakamura 0:a40b9a259b52 5675 bloblessData = this.result;
Osamu Nakamura 0:a40b9a259b52 5676 }
Osamu Nakamura 0:a40b9a259b52 5677
Osamu Nakamura 0:a40b9a259b52 5678 // if nothing pending its callback time
Osamu Nakamura 0:a40b9a259b52 5679 if(! --pendingBlobs) {
Osamu Nakamura 0:a40b9a259b52 5680 callback(bloblessData);
Osamu Nakamura 0:a40b9a259b52 5681 }
Osamu Nakamura 0:a40b9a259b52 5682 };
Osamu Nakamura 0:a40b9a259b52 5683
Osamu Nakamura 0:a40b9a259b52 5684 fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
Osamu Nakamura 0:a40b9a259b52 5685 } else if (isArray(obj)) { // handle array
Osamu Nakamura 0:a40b9a259b52 5686 for (var i = 0; i < obj.length; i++) {
Osamu Nakamura 0:a40b9a259b52 5687 _removeBlobs(obj[i], i, obj);
Osamu Nakamura 0:a40b9a259b52 5688 }
Osamu Nakamura 0:a40b9a259b52 5689 } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
Osamu Nakamura 0:a40b9a259b52 5690 for (var key in obj) {
Osamu Nakamura 0:a40b9a259b52 5691 _removeBlobs(obj[key], key, obj);
Osamu Nakamura 0:a40b9a259b52 5692 }
Osamu Nakamura 0:a40b9a259b52 5693 }
Osamu Nakamura 0:a40b9a259b52 5694 }
Osamu Nakamura 0:a40b9a259b52 5695
Osamu Nakamura 0:a40b9a259b52 5696 var pendingBlobs = 0;
Osamu Nakamura 0:a40b9a259b52 5697 var bloblessData = data;
Osamu Nakamura 0:a40b9a259b52 5698 _removeBlobs(bloblessData);
Osamu Nakamura 0:a40b9a259b52 5699 if (!pendingBlobs) {
Osamu Nakamura 0:a40b9a259b52 5700 callback(bloblessData);
Osamu Nakamura 0:a40b9a259b52 5701 }
Osamu Nakamura 0:a40b9a259b52 5702 };
Osamu Nakamura 0:a40b9a259b52 5703
Osamu Nakamura 0:a40b9a259b52 5704 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 5705 },{"./is-buffer":47,"isarray":48}],46:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 5706
Osamu Nakamura 0:a40b9a259b52 5707 /**
Osamu Nakamura 0:a40b9a259b52 5708 * Module dependencies.
Osamu Nakamura 0:a40b9a259b52 5709 */
Osamu Nakamura 0:a40b9a259b52 5710
Osamu Nakamura 0:a40b9a259b52 5711 var debug = _dereq_('debug')('socket.io-parser');
Osamu Nakamura 0:a40b9a259b52 5712 var json = _dereq_('json3');
Osamu Nakamura 0:a40b9a259b52 5713 var isArray = _dereq_('isarray');
Osamu Nakamura 0:a40b9a259b52 5714 var Emitter = _dereq_('component-emitter');
Osamu Nakamura 0:a40b9a259b52 5715 var binary = _dereq_('./binary');
Osamu Nakamura 0:a40b9a259b52 5716 var isBuf = _dereq_('./is-buffer');
Osamu Nakamura 0:a40b9a259b52 5717
Osamu Nakamura 0:a40b9a259b52 5718 /**
Osamu Nakamura 0:a40b9a259b52 5719 * Protocol version.
Osamu Nakamura 0:a40b9a259b52 5720 *
Osamu Nakamura 0:a40b9a259b52 5721 * @api public
Osamu Nakamura 0:a40b9a259b52 5722 */
Osamu Nakamura 0:a40b9a259b52 5723
Osamu Nakamura 0:a40b9a259b52 5724 exports.protocol = 4;
Osamu Nakamura 0:a40b9a259b52 5725
Osamu Nakamura 0:a40b9a259b52 5726 /**
Osamu Nakamura 0:a40b9a259b52 5727 * Packet types.
Osamu Nakamura 0:a40b9a259b52 5728 *
Osamu Nakamura 0:a40b9a259b52 5729 * @api public
Osamu Nakamura 0:a40b9a259b52 5730 */
Osamu Nakamura 0:a40b9a259b52 5731
Osamu Nakamura 0:a40b9a259b52 5732 exports.types = [
Osamu Nakamura 0:a40b9a259b52 5733 'CONNECT',
Osamu Nakamura 0:a40b9a259b52 5734 'DISCONNECT',
Osamu Nakamura 0:a40b9a259b52 5735 'EVENT',
Osamu Nakamura 0:a40b9a259b52 5736 'BINARY_EVENT',
Osamu Nakamura 0:a40b9a259b52 5737 'ACK',
Osamu Nakamura 0:a40b9a259b52 5738 'BINARY_ACK',
Osamu Nakamura 0:a40b9a259b52 5739 'ERROR'
Osamu Nakamura 0:a40b9a259b52 5740 ];
Osamu Nakamura 0:a40b9a259b52 5741
Osamu Nakamura 0:a40b9a259b52 5742 /**
Osamu Nakamura 0:a40b9a259b52 5743 * Packet type `connect`.
Osamu Nakamura 0:a40b9a259b52 5744 *
Osamu Nakamura 0:a40b9a259b52 5745 * @api public
Osamu Nakamura 0:a40b9a259b52 5746 */
Osamu Nakamura 0:a40b9a259b52 5747
Osamu Nakamura 0:a40b9a259b52 5748 exports.CONNECT = 0;
Osamu Nakamura 0:a40b9a259b52 5749
Osamu Nakamura 0:a40b9a259b52 5750 /**
Osamu Nakamura 0:a40b9a259b52 5751 * Packet type `disconnect`.
Osamu Nakamura 0:a40b9a259b52 5752 *
Osamu Nakamura 0:a40b9a259b52 5753 * @api public
Osamu Nakamura 0:a40b9a259b52 5754 */
Osamu Nakamura 0:a40b9a259b52 5755
Osamu Nakamura 0:a40b9a259b52 5756 exports.DISCONNECT = 1;
Osamu Nakamura 0:a40b9a259b52 5757
Osamu Nakamura 0:a40b9a259b52 5758 /**
Osamu Nakamura 0:a40b9a259b52 5759 * Packet type `event`.
Osamu Nakamura 0:a40b9a259b52 5760 *
Osamu Nakamura 0:a40b9a259b52 5761 * @api public
Osamu Nakamura 0:a40b9a259b52 5762 */
Osamu Nakamura 0:a40b9a259b52 5763
Osamu Nakamura 0:a40b9a259b52 5764 exports.EVENT = 2;
Osamu Nakamura 0:a40b9a259b52 5765
Osamu Nakamura 0:a40b9a259b52 5766 /**
Osamu Nakamura 0:a40b9a259b52 5767 * Packet type `ack`.
Osamu Nakamura 0:a40b9a259b52 5768 *
Osamu Nakamura 0:a40b9a259b52 5769 * @api public
Osamu Nakamura 0:a40b9a259b52 5770 */
Osamu Nakamura 0:a40b9a259b52 5771
Osamu Nakamura 0:a40b9a259b52 5772 exports.ACK = 3;
Osamu Nakamura 0:a40b9a259b52 5773
Osamu Nakamura 0:a40b9a259b52 5774 /**
Osamu Nakamura 0:a40b9a259b52 5775 * Packet type `error`.
Osamu Nakamura 0:a40b9a259b52 5776 *
Osamu Nakamura 0:a40b9a259b52 5777 * @api public
Osamu Nakamura 0:a40b9a259b52 5778 */
Osamu Nakamura 0:a40b9a259b52 5779
Osamu Nakamura 0:a40b9a259b52 5780 exports.ERROR = 4;
Osamu Nakamura 0:a40b9a259b52 5781
Osamu Nakamura 0:a40b9a259b52 5782 /**
Osamu Nakamura 0:a40b9a259b52 5783 * Packet type 'binary event'
Osamu Nakamura 0:a40b9a259b52 5784 *
Osamu Nakamura 0:a40b9a259b52 5785 * @api public
Osamu Nakamura 0:a40b9a259b52 5786 */
Osamu Nakamura 0:a40b9a259b52 5787
Osamu Nakamura 0:a40b9a259b52 5788 exports.BINARY_EVENT = 5;
Osamu Nakamura 0:a40b9a259b52 5789
Osamu Nakamura 0:a40b9a259b52 5790 /**
Osamu Nakamura 0:a40b9a259b52 5791 * Packet type `binary ack`. For acks with binary arguments.
Osamu Nakamura 0:a40b9a259b52 5792 *
Osamu Nakamura 0:a40b9a259b52 5793 * @api public
Osamu Nakamura 0:a40b9a259b52 5794 */
Osamu Nakamura 0:a40b9a259b52 5795
Osamu Nakamura 0:a40b9a259b52 5796 exports.BINARY_ACK = 6;
Osamu Nakamura 0:a40b9a259b52 5797
Osamu Nakamura 0:a40b9a259b52 5798 /**
Osamu Nakamura 0:a40b9a259b52 5799 * Encoder constructor.
Osamu Nakamura 0:a40b9a259b52 5800 *
Osamu Nakamura 0:a40b9a259b52 5801 * @api public
Osamu Nakamura 0:a40b9a259b52 5802 */
Osamu Nakamura 0:a40b9a259b52 5803
Osamu Nakamura 0:a40b9a259b52 5804 exports.Encoder = Encoder;
Osamu Nakamura 0:a40b9a259b52 5805
Osamu Nakamura 0:a40b9a259b52 5806 /**
Osamu Nakamura 0:a40b9a259b52 5807 * Decoder constructor.
Osamu Nakamura 0:a40b9a259b52 5808 *
Osamu Nakamura 0:a40b9a259b52 5809 * @api public
Osamu Nakamura 0:a40b9a259b52 5810 */
Osamu Nakamura 0:a40b9a259b52 5811
Osamu Nakamura 0:a40b9a259b52 5812 exports.Decoder = Decoder;
Osamu Nakamura 0:a40b9a259b52 5813
Osamu Nakamura 0:a40b9a259b52 5814 /**
Osamu Nakamura 0:a40b9a259b52 5815 * A socket.io Encoder instance
Osamu Nakamura 0:a40b9a259b52 5816 *
Osamu Nakamura 0:a40b9a259b52 5817 * @api public
Osamu Nakamura 0:a40b9a259b52 5818 */
Osamu Nakamura 0:a40b9a259b52 5819
Osamu Nakamura 0:a40b9a259b52 5820 function Encoder() {}
Osamu Nakamura 0:a40b9a259b52 5821
Osamu Nakamura 0:a40b9a259b52 5822 /**
Osamu Nakamura 0:a40b9a259b52 5823 * Encode a packet as a single string if non-binary, or as a
Osamu Nakamura 0:a40b9a259b52 5824 * buffer sequence, depending on packet type.
Osamu Nakamura 0:a40b9a259b52 5825 *
Osamu Nakamura 0:a40b9a259b52 5826 * @param {Object} obj - packet object
Osamu Nakamura 0:a40b9a259b52 5827 * @param {Function} callback - function to handle encodings (likely engine.write)
Osamu Nakamura 0:a40b9a259b52 5828 * @return Calls callback with Array of encodings
Osamu Nakamura 0:a40b9a259b52 5829 * @api public
Osamu Nakamura 0:a40b9a259b52 5830 */
Osamu Nakamura 0:a40b9a259b52 5831
Osamu Nakamura 0:a40b9a259b52 5832 Encoder.prototype.encode = function(obj, callback){
Osamu Nakamura 0:a40b9a259b52 5833 debug('encoding packet %j', obj);
Osamu Nakamura 0:a40b9a259b52 5834
Osamu Nakamura 0:a40b9a259b52 5835 if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
Osamu Nakamura 0:a40b9a259b52 5836 encodeAsBinary(obj, callback);
Osamu Nakamura 0:a40b9a259b52 5837 }
Osamu Nakamura 0:a40b9a259b52 5838 else {
Osamu Nakamura 0:a40b9a259b52 5839 var encoding = encodeAsString(obj);
Osamu Nakamura 0:a40b9a259b52 5840 callback([encoding]);
Osamu Nakamura 0:a40b9a259b52 5841 }
Osamu Nakamura 0:a40b9a259b52 5842 };
Osamu Nakamura 0:a40b9a259b52 5843
Osamu Nakamura 0:a40b9a259b52 5844 /**
Osamu Nakamura 0:a40b9a259b52 5845 * Encode packet as string.
Osamu Nakamura 0:a40b9a259b52 5846 *
Osamu Nakamura 0:a40b9a259b52 5847 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 5848 * @return {String} encoded
Osamu Nakamura 0:a40b9a259b52 5849 * @api private
Osamu Nakamura 0:a40b9a259b52 5850 */
Osamu Nakamura 0:a40b9a259b52 5851
Osamu Nakamura 0:a40b9a259b52 5852 function encodeAsString(obj) {
Osamu Nakamura 0:a40b9a259b52 5853 var str = '';
Osamu Nakamura 0:a40b9a259b52 5854 var nsp = false;
Osamu Nakamura 0:a40b9a259b52 5855
Osamu Nakamura 0:a40b9a259b52 5856 // first is type
Osamu Nakamura 0:a40b9a259b52 5857 str += obj.type;
Osamu Nakamura 0:a40b9a259b52 5858
Osamu Nakamura 0:a40b9a259b52 5859 // attachments if we have them
Osamu Nakamura 0:a40b9a259b52 5860 if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
Osamu Nakamura 0:a40b9a259b52 5861 str += obj.attachments;
Osamu Nakamura 0:a40b9a259b52 5862 str += '-';
Osamu Nakamura 0:a40b9a259b52 5863 }
Osamu Nakamura 0:a40b9a259b52 5864
Osamu Nakamura 0:a40b9a259b52 5865 // if we have a namespace other than `/`
Osamu Nakamura 0:a40b9a259b52 5866 // we append it followed by a comma `,`
Osamu Nakamura 0:a40b9a259b52 5867 if (obj.nsp && '/' != obj.nsp) {
Osamu Nakamura 0:a40b9a259b52 5868 nsp = true;
Osamu Nakamura 0:a40b9a259b52 5869 str += obj.nsp;
Osamu Nakamura 0:a40b9a259b52 5870 }
Osamu Nakamura 0:a40b9a259b52 5871
Osamu Nakamura 0:a40b9a259b52 5872 // immediately followed by the id
Osamu Nakamura 0:a40b9a259b52 5873 if (null != obj.id) {
Osamu Nakamura 0:a40b9a259b52 5874 if (nsp) {
Osamu Nakamura 0:a40b9a259b52 5875 str += ',';
Osamu Nakamura 0:a40b9a259b52 5876 nsp = false;
Osamu Nakamura 0:a40b9a259b52 5877 }
Osamu Nakamura 0:a40b9a259b52 5878 str += obj.id;
Osamu Nakamura 0:a40b9a259b52 5879 }
Osamu Nakamura 0:a40b9a259b52 5880
Osamu Nakamura 0:a40b9a259b52 5881 // json data
Osamu Nakamura 0:a40b9a259b52 5882 if (null != obj.data) {
Osamu Nakamura 0:a40b9a259b52 5883 if (nsp) str += ',';
Osamu Nakamura 0:a40b9a259b52 5884 str += json.stringify(obj.data);
Osamu Nakamura 0:a40b9a259b52 5885 }
Osamu Nakamura 0:a40b9a259b52 5886
Osamu Nakamura 0:a40b9a259b52 5887 debug('encoded %j as %s', obj, str);
Osamu Nakamura 0:a40b9a259b52 5888 return str;
Osamu Nakamura 0:a40b9a259b52 5889 }
Osamu Nakamura 0:a40b9a259b52 5890
Osamu Nakamura 0:a40b9a259b52 5891 /**
Osamu Nakamura 0:a40b9a259b52 5892 * Encode packet as 'buffer sequence' by removing blobs, and
Osamu Nakamura 0:a40b9a259b52 5893 * deconstructing packet into object with placeholders and
Osamu Nakamura 0:a40b9a259b52 5894 * a list of buffers.
Osamu Nakamura 0:a40b9a259b52 5895 *
Osamu Nakamura 0:a40b9a259b52 5896 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 5897 * @return {Buffer} encoded
Osamu Nakamura 0:a40b9a259b52 5898 * @api private
Osamu Nakamura 0:a40b9a259b52 5899 */
Osamu Nakamura 0:a40b9a259b52 5900
Osamu Nakamura 0:a40b9a259b52 5901 function encodeAsBinary(obj, callback) {
Osamu Nakamura 0:a40b9a259b52 5902
Osamu Nakamura 0:a40b9a259b52 5903 function writeEncoding(bloblessData) {
Osamu Nakamura 0:a40b9a259b52 5904 var deconstruction = binary.deconstructPacket(bloblessData);
Osamu Nakamura 0:a40b9a259b52 5905 var pack = encodeAsString(deconstruction.packet);
Osamu Nakamura 0:a40b9a259b52 5906 var buffers = deconstruction.buffers;
Osamu Nakamura 0:a40b9a259b52 5907
Osamu Nakamura 0:a40b9a259b52 5908 buffers.unshift(pack); // add packet info to beginning of data list
Osamu Nakamura 0:a40b9a259b52 5909 callback(buffers); // write all the buffers
Osamu Nakamura 0:a40b9a259b52 5910 }
Osamu Nakamura 0:a40b9a259b52 5911
Osamu Nakamura 0:a40b9a259b52 5912 binary.removeBlobs(obj, writeEncoding);
Osamu Nakamura 0:a40b9a259b52 5913 }
Osamu Nakamura 0:a40b9a259b52 5914
Osamu Nakamura 0:a40b9a259b52 5915 /**
Osamu Nakamura 0:a40b9a259b52 5916 * A socket.io Decoder instance
Osamu Nakamura 0:a40b9a259b52 5917 *
Osamu Nakamura 0:a40b9a259b52 5918 * @return {Object} decoder
Osamu Nakamura 0:a40b9a259b52 5919 * @api public
Osamu Nakamura 0:a40b9a259b52 5920 */
Osamu Nakamura 0:a40b9a259b52 5921
Osamu Nakamura 0:a40b9a259b52 5922 function Decoder() {
Osamu Nakamura 0:a40b9a259b52 5923 this.reconstructor = null;
Osamu Nakamura 0:a40b9a259b52 5924 }
Osamu Nakamura 0:a40b9a259b52 5925
Osamu Nakamura 0:a40b9a259b52 5926 /**
Osamu Nakamura 0:a40b9a259b52 5927 * Mix in `Emitter` with Decoder.
Osamu Nakamura 0:a40b9a259b52 5928 */
Osamu Nakamura 0:a40b9a259b52 5929
Osamu Nakamura 0:a40b9a259b52 5930 Emitter(Decoder.prototype);
Osamu Nakamura 0:a40b9a259b52 5931
Osamu Nakamura 0:a40b9a259b52 5932 /**
Osamu Nakamura 0:a40b9a259b52 5933 * Decodes an ecoded packet string into packet JSON.
Osamu Nakamura 0:a40b9a259b52 5934 *
Osamu Nakamura 0:a40b9a259b52 5935 * @param {String} obj - encoded packet
Osamu Nakamura 0:a40b9a259b52 5936 * @return {Object} packet
Osamu Nakamura 0:a40b9a259b52 5937 * @api public
Osamu Nakamura 0:a40b9a259b52 5938 */
Osamu Nakamura 0:a40b9a259b52 5939
Osamu Nakamura 0:a40b9a259b52 5940 Decoder.prototype.add = function(obj) {
Osamu Nakamura 0:a40b9a259b52 5941 var packet;
Osamu Nakamura 0:a40b9a259b52 5942 if ('string' == typeof obj) {
Osamu Nakamura 0:a40b9a259b52 5943 packet = decodeString(obj);
Osamu Nakamura 0:a40b9a259b52 5944 if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
Osamu Nakamura 0:a40b9a259b52 5945 this.reconstructor = new BinaryReconstructor(packet);
Osamu Nakamura 0:a40b9a259b52 5946
Osamu Nakamura 0:a40b9a259b52 5947 // no attachments, labeled binary but no binary data to follow
Osamu Nakamura 0:a40b9a259b52 5948 if (this.reconstructor.reconPack.attachments === 0) {
Osamu Nakamura 0:a40b9a259b52 5949 this.emit('decoded', packet);
Osamu Nakamura 0:a40b9a259b52 5950 }
Osamu Nakamura 0:a40b9a259b52 5951 } else { // non-binary full packet
Osamu Nakamura 0:a40b9a259b52 5952 this.emit('decoded', packet);
Osamu Nakamura 0:a40b9a259b52 5953 }
Osamu Nakamura 0:a40b9a259b52 5954 }
Osamu Nakamura 0:a40b9a259b52 5955 else if (isBuf(obj) || obj.base64) { // raw binary data
Osamu Nakamura 0:a40b9a259b52 5956 if (!this.reconstructor) {
Osamu Nakamura 0:a40b9a259b52 5957 throw new Error('got binary data when not reconstructing a packet');
Osamu Nakamura 0:a40b9a259b52 5958 } else {
Osamu Nakamura 0:a40b9a259b52 5959 packet = this.reconstructor.takeBinaryData(obj);
Osamu Nakamura 0:a40b9a259b52 5960 if (packet) { // received final buffer
Osamu Nakamura 0:a40b9a259b52 5961 this.reconstructor = null;
Osamu Nakamura 0:a40b9a259b52 5962 this.emit('decoded', packet);
Osamu Nakamura 0:a40b9a259b52 5963 }
Osamu Nakamura 0:a40b9a259b52 5964 }
Osamu Nakamura 0:a40b9a259b52 5965 }
Osamu Nakamura 0:a40b9a259b52 5966 else {
Osamu Nakamura 0:a40b9a259b52 5967 throw new Error('Unknown type: ' + obj);
Osamu Nakamura 0:a40b9a259b52 5968 }
Osamu Nakamura 0:a40b9a259b52 5969 };
Osamu Nakamura 0:a40b9a259b52 5970
Osamu Nakamura 0:a40b9a259b52 5971 /**
Osamu Nakamura 0:a40b9a259b52 5972 * Decode a packet String (JSON data)
Osamu Nakamura 0:a40b9a259b52 5973 *
Osamu Nakamura 0:a40b9a259b52 5974 * @param {String} str
Osamu Nakamura 0:a40b9a259b52 5975 * @return {Object} packet
Osamu Nakamura 0:a40b9a259b52 5976 * @api private
Osamu Nakamura 0:a40b9a259b52 5977 */
Osamu Nakamura 0:a40b9a259b52 5978
Osamu Nakamura 0:a40b9a259b52 5979 function decodeString(str) {
Osamu Nakamura 0:a40b9a259b52 5980 var p = {};
Osamu Nakamura 0:a40b9a259b52 5981 var i = 0;
Osamu Nakamura 0:a40b9a259b52 5982
Osamu Nakamura 0:a40b9a259b52 5983 // look up type
Osamu Nakamura 0:a40b9a259b52 5984 p.type = Number(str.charAt(0));
Osamu Nakamura 0:a40b9a259b52 5985 if (null == exports.types[p.type]) return error();
Osamu Nakamura 0:a40b9a259b52 5986
Osamu Nakamura 0:a40b9a259b52 5987 // look up attachments if type binary
Osamu Nakamura 0:a40b9a259b52 5988 if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
Osamu Nakamura 0:a40b9a259b52 5989 var buf = '';
Osamu Nakamura 0:a40b9a259b52 5990 while (str.charAt(++i) != '-') {
Osamu Nakamura 0:a40b9a259b52 5991 buf += str.charAt(i);
Osamu Nakamura 0:a40b9a259b52 5992 if (i == str.length) break;
Osamu Nakamura 0:a40b9a259b52 5993 }
Osamu Nakamura 0:a40b9a259b52 5994 if (buf != Number(buf) || str.charAt(i) != '-') {
Osamu Nakamura 0:a40b9a259b52 5995 throw new Error('Illegal attachments');
Osamu Nakamura 0:a40b9a259b52 5996 }
Osamu Nakamura 0:a40b9a259b52 5997 p.attachments = Number(buf);
Osamu Nakamura 0:a40b9a259b52 5998 }
Osamu Nakamura 0:a40b9a259b52 5999
Osamu Nakamura 0:a40b9a259b52 6000 // look up namespace (if any)
Osamu Nakamura 0:a40b9a259b52 6001 if ('/' == str.charAt(i + 1)) {
Osamu Nakamura 0:a40b9a259b52 6002 p.nsp = '';
Osamu Nakamura 0:a40b9a259b52 6003 while (++i) {
Osamu Nakamura 0:a40b9a259b52 6004 var c = str.charAt(i);
Osamu Nakamura 0:a40b9a259b52 6005 if (',' == c) break;
Osamu Nakamura 0:a40b9a259b52 6006 p.nsp += c;
Osamu Nakamura 0:a40b9a259b52 6007 if (i == str.length) break;
Osamu Nakamura 0:a40b9a259b52 6008 }
Osamu Nakamura 0:a40b9a259b52 6009 } else {
Osamu Nakamura 0:a40b9a259b52 6010 p.nsp = '/';
Osamu Nakamura 0:a40b9a259b52 6011 }
Osamu Nakamura 0:a40b9a259b52 6012
Osamu Nakamura 0:a40b9a259b52 6013 // look up id
Osamu Nakamura 0:a40b9a259b52 6014 var next = str.charAt(i + 1);
Osamu Nakamura 0:a40b9a259b52 6015 if ('' !== next && Number(next) == next) {
Osamu Nakamura 0:a40b9a259b52 6016 p.id = '';
Osamu Nakamura 0:a40b9a259b52 6017 while (++i) {
Osamu Nakamura 0:a40b9a259b52 6018 var c = str.charAt(i);
Osamu Nakamura 0:a40b9a259b52 6019 if (null == c || Number(c) != c) {
Osamu Nakamura 0:a40b9a259b52 6020 --i;
Osamu Nakamura 0:a40b9a259b52 6021 break;
Osamu Nakamura 0:a40b9a259b52 6022 }
Osamu Nakamura 0:a40b9a259b52 6023 p.id += str.charAt(i);
Osamu Nakamura 0:a40b9a259b52 6024 if (i == str.length) break;
Osamu Nakamura 0:a40b9a259b52 6025 }
Osamu Nakamura 0:a40b9a259b52 6026 p.id = Number(p.id);
Osamu Nakamura 0:a40b9a259b52 6027 }
Osamu Nakamura 0:a40b9a259b52 6028
Osamu Nakamura 0:a40b9a259b52 6029 // look up json data
Osamu Nakamura 0:a40b9a259b52 6030 if (str.charAt(++i)) {
Osamu Nakamura 0:a40b9a259b52 6031 try {
Osamu Nakamura 0:a40b9a259b52 6032 p.data = json.parse(str.substr(i));
Osamu Nakamura 0:a40b9a259b52 6033 } catch(e){
Osamu Nakamura 0:a40b9a259b52 6034 return error();
Osamu Nakamura 0:a40b9a259b52 6035 }
Osamu Nakamura 0:a40b9a259b52 6036 }
Osamu Nakamura 0:a40b9a259b52 6037
Osamu Nakamura 0:a40b9a259b52 6038 debug('decoded %s as %j', str, p);
Osamu Nakamura 0:a40b9a259b52 6039 return p;
Osamu Nakamura 0:a40b9a259b52 6040 }
Osamu Nakamura 0:a40b9a259b52 6041
Osamu Nakamura 0:a40b9a259b52 6042 /**
Osamu Nakamura 0:a40b9a259b52 6043 * Deallocates a parser's resources
Osamu Nakamura 0:a40b9a259b52 6044 *
Osamu Nakamura 0:a40b9a259b52 6045 * @api public
Osamu Nakamura 0:a40b9a259b52 6046 */
Osamu Nakamura 0:a40b9a259b52 6047
Osamu Nakamura 0:a40b9a259b52 6048 Decoder.prototype.destroy = function() {
Osamu Nakamura 0:a40b9a259b52 6049 if (this.reconstructor) {
Osamu Nakamura 0:a40b9a259b52 6050 this.reconstructor.finishedReconstruction();
Osamu Nakamura 0:a40b9a259b52 6051 }
Osamu Nakamura 0:a40b9a259b52 6052 };
Osamu Nakamura 0:a40b9a259b52 6053
Osamu Nakamura 0:a40b9a259b52 6054 /**
Osamu Nakamura 0:a40b9a259b52 6055 * A manager of a binary event's 'buffer sequence'. Should
Osamu Nakamura 0:a40b9a259b52 6056 * be constructed whenever a packet of type BINARY_EVENT is
Osamu Nakamura 0:a40b9a259b52 6057 * decoded.
Osamu Nakamura 0:a40b9a259b52 6058 *
Osamu Nakamura 0:a40b9a259b52 6059 * @param {Object} packet
Osamu Nakamura 0:a40b9a259b52 6060 * @return {BinaryReconstructor} initialized reconstructor
Osamu Nakamura 0:a40b9a259b52 6061 * @api private
Osamu Nakamura 0:a40b9a259b52 6062 */
Osamu Nakamura 0:a40b9a259b52 6063
Osamu Nakamura 0:a40b9a259b52 6064 function BinaryReconstructor(packet) {
Osamu Nakamura 0:a40b9a259b52 6065 this.reconPack = packet;
Osamu Nakamura 0:a40b9a259b52 6066 this.buffers = [];
Osamu Nakamura 0:a40b9a259b52 6067 }
Osamu Nakamura 0:a40b9a259b52 6068
Osamu Nakamura 0:a40b9a259b52 6069 /**
Osamu Nakamura 0:a40b9a259b52 6070 * Method to be called when binary data received from connection
Osamu Nakamura 0:a40b9a259b52 6071 * after a BINARY_EVENT packet.
Osamu Nakamura 0:a40b9a259b52 6072 *
Osamu Nakamura 0:a40b9a259b52 6073 * @param {Buffer | ArrayBuffer} binData - the raw binary data received
Osamu Nakamura 0:a40b9a259b52 6074 * @return {null | Object} returns null if more binary data is expected or
Osamu Nakamura 0:a40b9a259b52 6075 * a reconstructed packet object if all buffers have been received.
Osamu Nakamura 0:a40b9a259b52 6076 * @api private
Osamu Nakamura 0:a40b9a259b52 6077 */
Osamu Nakamura 0:a40b9a259b52 6078
Osamu Nakamura 0:a40b9a259b52 6079 BinaryReconstructor.prototype.takeBinaryData = function(binData) {
Osamu Nakamura 0:a40b9a259b52 6080 this.buffers.push(binData);
Osamu Nakamura 0:a40b9a259b52 6081 if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
Osamu Nakamura 0:a40b9a259b52 6082 var packet = binary.reconstructPacket(this.reconPack, this.buffers);
Osamu Nakamura 0:a40b9a259b52 6083 this.finishedReconstruction();
Osamu Nakamura 0:a40b9a259b52 6084 return packet;
Osamu Nakamura 0:a40b9a259b52 6085 }
Osamu Nakamura 0:a40b9a259b52 6086 return null;
Osamu Nakamura 0:a40b9a259b52 6087 };
Osamu Nakamura 0:a40b9a259b52 6088
Osamu Nakamura 0:a40b9a259b52 6089 /**
Osamu Nakamura 0:a40b9a259b52 6090 * Cleans up binary packet reconstruction variables.
Osamu Nakamura 0:a40b9a259b52 6091 *
Osamu Nakamura 0:a40b9a259b52 6092 * @api private
Osamu Nakamura 0:a40b9a259b52 6093 */
Osamu Nakamura 0:a40b9a259b52 6094
Osamu Nakamura 0:a40b9a259b52 6095 BinaryReconstructor.prototype.finishedReconstruction = function() {
Osamu Nakamura 0:a40b9a259b52 6096 this.reconPack = null;
Osamu Nakamura 0:a40b9a259b52 6097 this.buffers = [];
Osamu Nakamura 0:a40b9a259b52 6098 };
Osamu Nakamura 0:a40b9a259b52 6099
Osamu Nakamura 0:a40b9a259b52 6100 function error(data){
Osamu Nakamura 0:a40b9a259b52 6101 return {
Osamu Nakamura 0:a40b9a259b52 6102 type: exports.ERROR,
Osamu Nakamura 0:a40b9a259b52 6103 data: 'parser error'
Osamu Nakamura 0:a40b9a259b52 6104 };
Osamu Nakamura 0:a40b9a259b52 6105 }
Osamu Nakamura 0:a40b9a259b52 6106
Osamu Nakamura 0:a40b9a259b52 6107 },{"./binary":45,"./is-buffer":47,"component-emitter":9,"debug":10,"isarray":48,"json3":49}],47:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 6108 (function (global){
Osamu Nakamura 0:a40b9a259b52 6109
Osamu Nakamura 0:a40b9a259b52 6110 module.exports = isBuf;
Osamu Nakamura 0:a40b9a259b52 6111
Osamu Nakamura 0:a40b9a259b52 6112 /**
Osamu Nakamura 0:a40b9a259b52 6113 * Returns true if obj is a buffer or an arraybuffer.
Osamu Nakamura 0:a40b9a259b52 6114 *
Osamu Nakamura 0:a40b9a259b52 6115 * @api private
Osamu Nakamura 0:a40b9a259b52 6116 */
Osamu Nakamura 0:a40b9a259b52 6117
Osamu Nakamura 0:a40b9a259b52 6118 function isBuf(obj) {
Osamu Nakamura 0:a40b9a259b52 6119 return (global.Buffer && global.Buffer.isBuffer(obj)) ||
Osamu Nakamura 0:a40b9a259b52 6120 (global.ArrayBuffer && obj instanceof ArrayBuffer);
Osamu Nakamura 0:a40b9a259b52 6121 }
Osamu Nakamura 0:a40b9a259b52 6122
Osamu Nakamura 0:a40b9a259b52 6123 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Osamu Nakamura 0:a40b9a259b52 6124 },{}],48:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 6125 module.exports=_dereq_(32)
Osamu Nakamura 0:a40b9a259b52 6126 },{}],49:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 6127 /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */
Osamu Nakamura 0:a40b9a259b52 6128 ;(function (window) {
Osamu Nakamura 0:a40b9a259b52 6129 // Convenience aliases.
Osamu Nakamura 0:a40b9a259b52 6130 var getClass = {}.toString, isProperty, forEach, undef;
Osamu Nakamura 0:a40b9a259b52 6131
Osamu Nakamura 0:a40b9a259b52 6132 // Detect the `define` function exposed by asynchronous module loaders. The
Osamu Nakamura 0:a40b9a259b52 6133 // strict `define` check is necessary for compatibility with `r.js`.
Osamu Nakamura 0:a40b9a259b52 6134 var isLoader = typeof define === "function" && define.amd;
Osamu Nakamura 0:a40b9a259b52 6135
Osamu Nakamura 0:a40b9a259b52 6136 // Detect native implementations.
Osamu Nakamura 0:a40b9a259b52 6137 var nativeJSON = typeof JSON == "object" && JSON;
Osamu Nakamura 0:a40b9a259b52 6138
Osamu Nakamura 0:a40b9a259b52 6139 // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if
Osamu Nakamura 0:a40b9a259b52 6140 // available.
Osamu Nakamura 0:a40b9a259b52 6141 var JSON3 = typeof exports == "object" && exports && !exports.nodeType && exports;
Osamu Nakamura 0:a40b9a259b52 6142
Osamu Nakamura 0:a40b9a259b52 6143 if (JSON3 && nativeJSON) {
Osamu Nakamura 0:a40b9a259b52 6144 // Explicitly delegate to the native `stringify` and `parse`
Osamu Nakamura 0:a40b9a259b52 6145 // implementations in CommonJS environments.
Osamu Nakamura 0:a40b9a259b52 6146 JSON3.stringify = nativeJSON.stringify;
Osamu Nakamura 0:a40b9a259b52 6147 JSON3.parse = nativeJSON.parse;
Osamu Nakamura 0:a40b9a259b52 6148 } else {
Osamu Nakamura 0:a40b9a259b52 6149 // Export for web browsers, JavaScript engines, and asynchronous module
Osamu Nakamura 0:a40b9a259b52 6150 // loaders, using the global `JSON` object if available.
Osamu Nakamura 0:a40b9a259b52 6151 JSON3 = window.JSON = nativeJSON || {};
Osamu Nakamura 0:a40b9a259b52 6152 }
Osamu Nakamura 0:a40b9a259b52 6153
Osamu Nakamura 0:a40b9a259b52 6154 // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
Osamu Nakamura 0:a40b9a259b52 6155 var isExtended = new Date(-3509827334573292);
Osamu Nakamura 0:a40b9a259b52 6156 try {
Osamu Nakamura 0:a40b9a259b52 6157 // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
Osamu Nakamura 0:a40b9a259b52 6158 // results for certain dates in Opera >= 10.53.
Osamu Nakamura 0:a40b9a259b52 6159 isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
Osamu Nakamura 0:a40b9a259b52 6160 // Safari < 2.0.2 stores the internal millisecond time value correctly,
Osamu Nakamura 0:a40b9a259b52 6161 // but clips the values returned by the date methods to the range of
Osamu Nakamura 0:a40b9a259b52 6162 // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
Osamu Nakamura 0:a40b9a259b52 6163 isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
Osamu Nakamura 0:a40b9a259b52 6164 } catch (exception) {}
Osamu Nakamura 0:a40b9a259b52 6165
Osamu Nakamura 0:a40b9a259b52 6166 // Internal: Determines whether the native `JSON.stringify` and `parse`
Osamu Nakamura 0:a40b9a259b52 6167 // implementations are spec-compliant. Based on work by Ken Snyder.
Osamu Nakamura 0:a40b9a259b52 6168 function has(name) {
Osamu Nakamura 0:a40b9a259b52 6169 if (has[name] !== undef) {
Osamu Nakamura 0:a40b9a259b52 6170 // Return cached feature test result.
Osamu Nakamura 0:a40b9a259b52 6171 return has[name];
Osamu Nakamura 0:a40b9a259b52 6172 }
Osamu Nakamura 0:a40b9a259b52 6173
Osamu Nakamura 0:a40b9a259b52 6174 var isSupported;
Osamu Nakamura 0:a40b9a259b52 6175 if (name == "bug-string-char-index") {
Osamu Nakamura 0:a40b9a259b52 6176 // IE <= 7 doesn't support accessing string characters using square
Osamu Nakamura 0:a40b9a259b52 6177 // bracket notation. IE 8 only supports this for primitives.
Osamu Nakamura 0:a40b9a259b52 6178 isSupported = "a"[0] != "a";
Osamu Nakamura 0:a40b9a259b52 6179 } else if (name == "json") {
Osamu Nakamura 0:a40b9a259b52 6180 // Indicates whether both `JSON.stringify` and `JSON.parse` are
Osamu Nakamura 0:a40b9a259b52 6181 // supported.
Osamu Nakamura 0:a40b9a259b52 6182 isSupported = has("json-stringify") && has("json-parse");
Osamu Nakamura 0:a40b9a259b52 6183 } else {
Osamu Nakamura 0:a40b9a259b52 6184 var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
Osamu Nakamura 0:a40b9a259b52 6185 // Test `JSON.stringify`.
Osamu Nakamura 0:a40b9a259b52 6186 if (name == "json-stringify") {
Osamu Nakamura 0:a40b9a259b52 6187 var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended;
Osamu Nakamura 0:a40b9a259b52 6188 if (stringifySupported) {
Osamu Nakamura 0:a40b9a259b52 6189 // A test function object with a custom `toJSON` method.
Osamu Nakamura 0:a40b9a259b52 6190 (value = function () {
Osamu Nakamura 0:a40b9a259b52 6191 return 1;
Osamu Nakamura 0:a40b9a259b52 6192 }).toJSON = value;
Osamu Nakamura 0:a40b9a259b52 6193 try {
Osamu Nakamura 0:a40b9a259b52 6194 stringifySupported =
Osamu Nakamura 0:a40b9a259b52 6195 // Firefox 3.1b1 and b2 serialize string, number, and boolean
Osamu Nakamura 0:a40b9a259b52 6196 // primitives as object literals.
Osamu Nakamura 0:a40b9a259b52 6197 stringify(0) === "0" &&
Osamu Nakamura 0:a40b9a259b52 6198 // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
Osamu Nakamura 0:a40b9a259b52 6199 // literals.
Osamu Nakamura 0:a40b9a259b52 6200 stringify(new Number()) === "0" &&
Osamu Nakamura 0:a40b9a259b52 6201 stringify(new String()) == '""' &&
Osamu Nakamura 0:a40b9a259b52 6202 // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
Osamu Nakamura 0:a40b9a259b52 6203 // does not define a canonical JSON representation (this applies to
Osamu Nakamura 0:a40b9a259b52 6204 // objects with `toJSON` properties as well, *unless* they are nested
Osamu Nakamura 0:a40b9a259b52 6205 // within an object or array).
Osamu Nakamura 0:a40b9a259b52 6206 stringify(getClass) === undef &&
Osamu Nakamura 0:a40b9a259b52 6207 // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
Osamu Nakamura 0:a40b9a259b52 6208 // FF 3.1b3 pass this test.
Osamu Nakamura 0:a40b9a259b52 6209 stringify(undef) === undef &&
Osamu Nakamura 0:a40b9a259b52 6210 // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
Osamu Nakamura 0:a40b9a259b52 6211 // respectively, if the value is omitted entirely.
Osamu Nakamura 0:a40b9a259b52 6212 stringify() === undef &&
Osamu Nakamura 0:a40b9a259b52 6213 // FF 3.1b1, 2 throw an error if the given value is not a number,
Osamu Nakamura 0:a40b9a259b52 6214 // string, array, object, Boolean, or `null` literal. This applies to
Osamu Nakamura 0:a40b9a259b52 6215 // objects with custom `toJSON` methods as well, unless they are nested
Osamu Nakamura 0:a40b9a259b52 6216 // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
Osamu Nakamura 0:a40b9a259b52 6217 // methods entirely.
Osamu Nakamura 0:a40b9a259b52 6218 stringify(value) === "1" &&
Osamu Nakamura 0:a40b9a259b52 6219 stringify([value]) == "[1]" &&
Osamu Nakamura 0:a40b9a259b52 6220 // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
Osamu Nakamura 0:a40b9a259b52 6221 // `"[null]"`.
Osamu Nakamura 0:a40b9a259b52 6222 stringify([undef]) == "[null]" &&
Osamu Nakamura 0:a40b9a259b52 6223 // YUI 3.0.0b1 fails to serialize `null` literals.
Osamu Nakamura 0:a40b9a259b52 6224 stringify(null) == "null" &&
Osamu Nakamura 0:a40b9a259b52 6225 // FF 3.1b1, 2 halts serialization if an array contains a function:
Osamu Nakamura 0:a40b9a259b52 6226 // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
Osamu Nakamura 0:a40b9a259b52 6227 // elides non-JSON values from objects and arrays, unless they
Osamu Nakamura 0:a40b9a259b52 6228 // define custom `toJSON` methods.
Osamu Nakamura 0:a40b9a259b52 6229 stringify([undef, getClass, null]) == "[null,null,null]" &&
Osamu Nakamura 0:a40b9a259b52 6230 // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
Osamu Nakamura 0:a40b9a259b52 6231 // where character escape codes are expected (e.g., `\b` => `\u0008`).
Osamu Nakamura 0:a40b9a259b52 6232 stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
Osamu Nakamura 0:a40b9a259b52 6233 // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
Osamu Nakamura 0:a40b9a259b52 6234 stringify(null, value) === "1" &&
Osamu Nakamura 0:a40b9a259b52 6235 stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
Osamu Nakamura 0:a40b9a259b52 6236 // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
Osamu Nakamura 0:a40b9a259b52 6237 // serialize extended years.
Osamu Nakamura 0:a40b9a259b52 6238 stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
Osamu Nakamura 0:a40b9a259b52 6239 // The milliseconds are optional in ES 5, but required in 5.1.
Osamu Nakamura 0:a40b9a259b52 6240 stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
Osamu Nakamura 0:a40b9a259b52 6241 // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
Osamu Nakamura 0:a40b9a259b52 6242 // four-digit years instead of six-digit years. Credits: @Yaffle.
Osamu Nakamura 0:a40b9a259b52 6243 stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
Osamu Nakamura 0:a40b9a259b52 6244 // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
Osamu Nakamura 0:a40b9a259b52 6245 // values less than 1000. Credits: @Yaffle.
Osamu Nakamura 0:a40b9a259b52 6246 stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
Osamu Nakamura 0:a40b9a259b52 6247 } catch (exception) {
Osamu Nakamura 0:a40b9a259b52 6248 stringifySupported = false;
Osamu Nakamura 0:a40b9a259b52 6249 }
Osamu Nakamura 0:a40b9a259b52 6250 }
Osamu Nakamura 0:a40b9a259b52 6251 isSupported = stringifySupported;
Osamu Nakamura 0:a40b9a259b52 6252 }
Osamu Nakamura 0:a40b9a259b52 6253 // Test `JSON.parse`.
Osamu Nakamura 0:a40b9a259b52 6254 if (name == "json-parse") {
Osamu Nakamura 0:a40b9a259b52 6255 var parse = JSON3.parse;
Osamu Nakamura 0:a40b9a259b52 6256 if (typeof parse == "function") {
Osamu Nakamura 0:a40b9a259b52 6257 try {
Osamu Nakamura 0:a40b9a259b52 6258 // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
Osamu Nakamura 0:a40b9a259b52 6259 // Conforming implementations should also coerce the initial argument to
Osamu Nakamura 0:a40b9a259b52 6260 // a string prior to parsing.
Osamu Nakamura 0:a40b9a259b52 6261 if (parse("0") === 0 && !parse(false)) {
Osamu Nakamura 0:a40b9a259b52 6262 // Simple parsing test.
Osamu Nakamura 0:a40b9a259b52 6263 value = parse(serialized);
Osamu Nakamura 0:a40b9a259b52 6264 var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
Osamu Nakamura 0:a40b9a259b52 6265 if (parseSupported) {
Osamu Nakamura 0:a40b9a259b52 6266 try {
Osamu Nakamura 0:a40b9a259b52 6267 // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
Osamu Nakamura 0:a40b9a259b52 6268 parseSupported = !parse('"\t"');
Osamu Nakamura 0:a40b9a259b52 6269 } catch (exception) {}
Osamu Nakamura 0:a40b9a259b52 6270 if (parseSupported) {
Osamu Nakamura 0:a40b9a259b52 6271 try {
Osamu Nakamura 0:a40b9a259b52 6272 // FF 4.0 and 4.0.1 allow leading `+` signs and leading
Osamu Nakamura 0:a40b9a259b52 6273 // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
Osamu Nakamura 0:a40b9a259b52 6274 // certain octal literals.
Osamu Nakamura 0:a40b9a259b52 6275 parseSupported = parse("01") !== 1;
Osamu Nakamura 0:a40b9a259b52 6276 } catch (exception) {}
Osamu Nakamura 0:a40b9a259b52 6277 }
Osamu Nakamura 0:a40b9a259b52 6278 if (parseSupported) {
Osamu Nakamura 0:a40b9a259b52 6279 try {
Osamu Nakamura 0:a40b9a259b52 6280 // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
Osamu Nakamura 0:a40b9a259b52 6281 // points. These environments, along with FF 3.1b1 and 2,
Osamu Nakamura 0:a40b9a259b52 6282 // also allow trailing commas in JSON objects and arrays.
Osamu Nakamura 0:a40b9a259b52 6283 parseSupported = parse("1.") !== 1;
Osamu Nakamura 0:a40b9a259b52 6284 } catch (exception) {}
Osamu Nakamura 0:a40b9a259b52 6285 }
Osamu Nakamura 0:a40b9a259b52 6286 }
Osamu Nakamura 0:a40b9a259b52 6287 }
Osamu Nakamura 0:a40b9a259b52 6288 } catch (exception) {
Osamu Nakamura 0:a40b9a259b52 6289 parseSupported = false;
Osamu Nakamura 0:a40b9a259b52 6290 }
Osamu Nakamura 0:a40b9a259b52 6291 }
Osamu Nakamura 0:a40b9a259b52 6292 isSupported = parseSupported;
Osamu Nakamura 0:a40b9a259b52 6293 }
Osamu Nakamura 0:a40b9a259b52 6294 }
Osamu Nakamura 0:a40b9a259b52 6295 return has[name] = !!isSupported;
Osamu Nakamura 0:a40b9a259b52 6296 }
Osamu Nakamura 0:a40b9a259b52 6297
Osamu Nakamura 0:a40b9a259b52 6298 if (!has("json")) {
Osamu Nakamura 0:a40b9a259b52 6299 // Common `[[Class]]` name aliases.
Osamu Nakamura 0:a40b9a259b52 6300 var functionClass = "[object Function]";
Osamu Nakamura 0:a40b9a259b52 6301 var dateClass = "[object Date]";
Osamu Nakamura 0:a40b9a259b52 6302 var numberClass = "[object Number]";
Osamu Nakamura 0:a40b9a259b52 6303 var stringClass = "[object String]";
Osamu Nakamura 0:a40b9a259b52 6304 var arrayClass = "[object Array]";
Osamu Nakamura 0:a40b9a259b52 6305 var booleanClass = "[object Boolean]";
Osamu Nakamura 0:a40b9a259b52 6306
Osamu Nakamura 0:a40b9a259b52 6307 // Detect incomplete support for accessing string characters by index.
Osamu Nakamura 0:a40b9a259b52 6308 var charIndexBuggy = has("bug-string-char-index");
Osamu Nakamura 0:a40b9a259b52 6309
Osamu Nakamura 0:a40b9a259b52 6310 // Define additional utility methods if the `Date` methods are buggy.
Osamu Nakamura 0:a40b9a259b52 6311 if (!isExtended) {
Osamu Nakamura 0:a40b9a259b52 6312 var floor = Math.floor;
Osamu Nakamura 0:a40b9a259b52 6313 // A mapping between the months of the year and the number of days between
Osamu Nakamura 0:a40b9a259b52 6314 // January 1st and the first of the respective month.
Osamu Nakamura 0:a40b9a259b52 6315 var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
Osamu Nakamura 0:a40b9a259b52 6316 // Internal: Calculates the number of days between the Unix epoch and the
Osamu Nakamura 0:a40b9a259b52 6317 // first day of the given month.
Osamu Nakamura 0:a40b9a259b52 6318 var getDay = function (year, month) {
Osamu Nakamura 0:a40b9a259b52 6319 return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
Osamu Nakamura 0:a40b9a259b52 6320 };
Osamu Nakamura 0:a40b9a259b52 6321 }
Osamu Nakamura 0:a40b9a259b52 6322
Osamu Nakamura 0:a40b9a259b52 6323 // Internal: Determines if a property is a direct property of the given
Osamu Nakamura 0:a40b9a259b52 6324 // object. Delegates to the native `Object#hasOwnProperty` method.
Osamu Nakamura 0:a40b9a259b52 6325 if (!(isProperty = {}.hasOwnProperty)) {
Osamu Nakamura 0:a40b9a259b52 6326 isProperty = function (property) {
Osamu Nakamura 0:a40b9a259b52 6327 var members = {}, constructor;
Osamu Nakamura 0:a40b9a259b52 6328 if ((members.__proto__ = null, members.__proto__ = {
Osamu Nakamura 0:a40b9a259b52 6329 // The *proto* property cannot be set multiple times in recent
Osamu Nakamura 0:a40b9a259b52 6330 // versions of Firefox and SeaMonkey.
Osamu Nakamura 0:a40b9a259b52 6331 "toString": 1
Osamu Nakamura 0:a40b9a259b52 6332 }, members).toString != getClass) {
Osamu Nakamura 0:a40b9a259b52 6333 // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
Osamu Nakamura 0:a40b9a259b52 6334 // supports the mutable *proto* property.
Osamu Nakamura 0:a40b9a259b52 6335 isProperty = function (property) {
Osamu Nakamura 0:a40b9a259b52 6336 // Capture and break the object's prototype chain (see section 8.6.2
Osamu Nakamura 0:a40b9a259b52 6337 // of the ES 5.1 spec). The parenthesized expression prevents an
Osamu Nakamura 0:a40b9a259b52 6338 // unsafe transformation by the Closure Compiler.
Osamu Nakamura 0:a40b9a259b52 6339 var original = this.__proto__, result = property in (this.__proto__ = null, this);
Osamu Nakamura 0:a40b9a259b52 6340 // Restore the original prototype chain.
Osamu Nakamura 0:a40b9a259b52 6341 this.__proto__ = original;
Osamu Nakamura 0:a40b9a259b52 6342 return result;
Osamu Nakamura 0:a40b9a259b52 6343 };
Osamu Nakamura 0:a40b9a259b52 6344 } else {
Osamu Nakamura 0:a40b9a259b52 6345 // Capture a reference to the top-level `Object` constructor.
Osamu Nakamura 0:a40b9a259b52 6346 constructor = members.constructor;
Osamu Nakamura 0:a40b9a259b52 6347 // Use the `constructor` property to simulate `Object#hasOwnProperty` in
Osamu Nakamura 0:a40b9a259b52 6348 // other environments.
Osamu Nakamura 0:a40b9a259b52 6349 isProperty = function (property) {
Osamu Nakamura 0:a40b9a259b52 6350 var parent = (this.constructor || constructor).prototype;
Osamu Nakamura 0:a40b9a259b52 6351 return property in this && !(property in parent && this[property] === parent[property]);
Osamu Nakamura 0:a40b9a259b52 6352 };
Osamu Nakamura 0:a40b9a259b52 6353 }
Osamu Nakamura 0:a40b9a259b52 6354 members = null;
Osamu Nakamura 0:a40b9a259b52 6355 return isProperty.call(this, property);
Osamu Nakamura 0:a40b9a259b52 6356 };
Osamu Nakamura 0:a40b9a259b52 6357 }
Osamu Nakamura 0:a40b9a259b52 6358
Osamu Nakamura 0:a40b9a259b52 6359 // Internal: A set of primitive types used by `isHostType`.
Osamu Nakamura 0:a40b9a259b52 6360 var PrimitiveTypes = {
Osamu Nakamura 0:a40b9a259b52 6361 'boolean': 1,
Osamu Nakamura 0:a40b9a259b52 6362 'number': 1,
Osamu Nakamura 0:a40b9a259b52 6363 'string': 1,
Osamu Nakamura 0:a40b9a259b52 6364 'undefined': 1
Osamu Nakamura 0:a40b9a259b52 6365 };
Osamu Nakamura 0:a40b9a259b52 6366
Osamu Nakamura 0:a40b9a259b52 6367 // Internal: Determines if the given object `property` value is a
Osamu Nakamura 0:a40b9a259b52 6368 // non-primitive.
Osamu Nakamura 0:a40b9a259b52 6369 var isHostType = function (object, property) {
Osamu Nakamura 0:a40b9a259b52 6370 var type = typeof object[property];
Osamu Nakamura 0:a40b9a259b52 6371 return type == 'object' ? !!object[property] : !PrimitiveTypes[type];
Osamu Nakamura 0:a40b9a259b52 6372 };
Osamu Nakamura 0:a40b9a259b52 6373
Osamu Nakamura 0:a40b9a259b52 6374 // Internal: Normalizes the `for...in` iteration algorithm across
Osamu Nakamura 0:a40b9a259b52 6375 // environments. Each enumerated key is yielded to a `callback` function.
Osamu Nakamura 0:a40b9a259b52 6376 forEach = function (object, callback) {
Osamu Nakamura 0:a40b9a259b52 6377 var size = 0, Properties, members, property;
Osamu Nakamura 0:a40b9a259b52 6378
Osamu Nakamura 0:a40b9a259b52 6379 // Tests for bugs in the current environment's `for...in` algorithm. The
Osamu Nakamura 0:a40b9a259b52 6380 // `valueOf` property inherits the non-enumerable flag from
Osamu Nakamura 0:a40b9a259b52 6381 // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
Osamu Nakamura 0:a40b9a259b52 6382 (Properties = function () {
Osamu Nakamura 0:a40b9a259b52 6383 this.valueOf = 0;
Osamu Nakamura 0:a40b9a259b52 6384 }).prototype.valueOf = 0;
Osamu Nakamura 0:a40b9a259b52 6385
Osamu Nakamura 0:a40b9a259b52 6386 // Iterate over a new instance of the `Properties` class.
Osamu Nakamura 0:a40b9a259b52 6387 members = new Properties();
Osamu Nakamura 0:a40b9a259b52 6388 for (property in members) {
Osamu Nakamura 0:a40b9a259b52 6389 // Ignore all properties inherited from `Object.prototype`.
Osamu Nakamura 0:a40b9a259b52 6390 if (isProperty.call(members, property)) {
Osamu Nakamura 0:a40b9a259b52 6391 size++;
Osamu Nakamura 0:a40b9a259b52 6392 }
Osamu Nakamura 0:a40b9a259b52 6393 }
Osamu Nakamura 0:a40b9a259b52 6394 Properties = members = null;
Osamu Nakamura 0:a40b9a259b52 6395
Osamu Nakamura 0:a40b9a259b52 6396 // Normalize the iteration algorithm.
Osamu Nakamura 0:a40b9a259b52 6397 if (!size) {
Osamu Nakamura 0:a40b9a259b52 6398 // A list of non-enumerable properties inherited from `Object.prototype`.
Osamu Nakamura 0:a40b9a259b52 6399 members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
Osamu Nakamura 0:a40b9a259b52 6400 // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
Osamu Nakamura 0:a40b9a259b52 6401 // properties.
Osamu Nakamura 0:a40b9a259b52 6402 forEach = function (object, callback) {
Osamu Nakamura 0:a40b9a259b52 6403 var isFunction = getClass.call(object) == functionClass, property, length;
Osamu Nakamura 0:a40b9a259b52 6404 var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty;
Osamu Nakamura 0:a40b9a259b52 6405 for (property in object) {
Osamu Nakamura 0:a40b9a259b52 6406 // Gecko <= 1.0 enumerates the `prototype` property of functions under
Osamu Nakamura 0:a40b9a259b52 6407 // certain conditions; IE does not.
Osamu Nakamura 0:a40b9a259b52 6408 if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
Osamu Nakamura 0:a40b9a259b52 6409 callback(property);
Osamu Nakamura 0:a40b9a259b52 6410 }
Osamu Nakamura 0:a40b9a259b52 6411 }
Osamu Nakamura 0:a40b9a259b52 6412 // Manually invoke the callback for each non-enumerable property.
Osamu Nakamura 0:a40b9a259b52 6413 for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
Osamu Nakamura 0:a40b9a259b52 6414 };
Osamu Nakamura 0:a40b9a259b52 6415 } else if (size == 2) {
Osamu Nakamura 0:a40b9a259b52 6416 // Safari <= 2.0.4 enumerates shadowed properties twice.
Osamu Nakamura 0:a40b9a259b52 6417 forEach = function (object, callback) {
Osamu Nakamura 0:a40b9a259b52 6418 // Create a set of iterated properties.
Osamu Nakamura 0:a40b9a259b52 6419 var members = {}, isFunction = getClass.call(object) == functionClass, property;
Osamu Nakamura 0:a40b9a259b52 6420 for (property in object) {
Osamu Nakamura 0:a40b9a259b52 6421 // Store each property name to prevent double enumeration. The
Osamu Nakamura 0:a40b9a259b52 6422 // `prototype` property of functions is not enumerated due to cross-
Osamu Nakamura 0:a40b9a259b52 6423 // environment inconsistencies.
Osamu Nakamura 0:a40b9a259b52 6424 if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
Osamu Nakamura 0:a40b9a259b52 6425 callback(property);
Osamu Nakamura 0:a40b9a259b52 6426 }
Osamu Nakamura 0:a40b9a259b52 6427 }
Osamu Nakamura 0:a40b9a259b52 6428 };
Osamu Nakamura 0:a40b9a259b52 6429 } else {
Osamu Nakamura 0:a40b9a259b52 6430 // No bugs detected; use the standard `for...in` algorithm.
Osamu Nakamura 0:a40b9a259b52 6431 forEach = function (object, callback) {
Osamu Nakamura 0:a40b9a259b52 6432 var isFunction = getClass.call(object) == functionClass, property, isConstructor;
Osamu Nakamura 0:a40b9a259b52 6433 for (property in object) {
Osamu Nakamura 0:a40b9a259b52 6434 if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
Osamu Nakamura 0:a40b9a259b52 6435 callback(property);
Osamu Nakamura 0:a40b9a259b52 6436 }
Osamu Nakamura 0:a40b9a259b52 6437 }
Osamu Nakamura 0:a40b9a259b52 6438 // Manually invoke the callback for the `constructor` property due to
Osamu Nakamura 0:a40b9a259b52 6439 // cross-environment inconsistencies.
Osamu Nakamura 0:a40b9a259b52 6440 if (isConstructor || isProperty.call(object, (property = "constructor"))) {
Osamu Nakamura 0:a40b9a259b52 6441 callback(property);
Osamu Nakamura 0:a40b9a259b52 6442 }
Osamu Nakamura 0:a40b9a259b52 6443 };
Osamu Nakamura 0:a40b9a259b52 6444 }
Osamu Nakamura 0:a40b9a259b52 6445 return forEach(object, callback);
Osamu Nakamura 0:a40b9a259b52 6446 };
Osamu Nakamura 0:a40b9a259b52 6447
Osamu Nakamura 0:a40b9a259b52 6448 // Public: Serializes a JavaScript `value` as a JSON string. The optional
Osamu Nakamura 0:a40b9a259b52 6449 // `filter` argument may specify either a function that alters how object and
Osamu Nakamura 0:a40b9a259b52 6450 // array members are serialized, or an array of strings and numbers that
Osamu Nakamura 0:a40b9a259b52 6451 // indicates which properties should be serialized. The optional `width`
Osamu Nakamura 0:a40b9a259b52 6452 // argument may be either a string or number that specifies the indentation
Osamu Nakamura 0:a40b9a259b52 6453 // level of the output.
Osamu Nakamura 0:a40b9a259b52 6454 if (!has("json-stringify")) {
Osamu Nakamura 0:a40b9a259b52 6455 // Internal: A map of control characters and their escaped equivalents.
Osamu Nakamura 0:a40b9a259b52 6456 var Escapes = {
Osamu Nakamura 0:a40b9a259b52 6457 92: "\\\\",
Osamu Nakamura 0:a40b9a259b52 6458 34: '\\"',
Osamu Nakamura 0:a40b9a259b52 6459 8: "\\b",
Osamu Nakamura 0:a40b9a259b52 6460 12: "\\f",
Osamu Nakamura 0:a40b9a259b52 6461 10: "\\n",
Osamu Nakamura 0:a40b9a259b52 6462 13: "\\r",
Osamu Nakamura 0:a40b9a259b52 6463 9: "\\t"
Osamu Nakamura 0:a40b9a259b52 6464 };
Osamu Nakamura 0:a40b9a259b52 6465
Osamu Nakamura 0:a40b9a259b52 6466 // Internal: Converts `value` into a zero-padded string such that its
Osamu Nakamura 0:a40b9a259b52 6467 // length is at least equal to `width`. The `width` must be <= 6.
Osamu Nakamura 0:a40b9a259b52 6468 var leadingZeroes = "000000";
Osamu Nakamura 0:a40b9a259b52 6469 var toPaddedString = function (width, value) {
Osamu Nakamura 0:a40b9a259b52 6470 // The `|| 0` expression is necessary to work around a bug in
Osamu Nakamura 0:a40b9a259b52 6471 // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
Osamu Nakamura 0:a40b9a259b52 6472 return (leadingZeroes + (value || 0)).slice(-width);
Osamu Nakamura 0:a40b9a259b52 6473 };
Osamu Nakamura 0:a40b9a259b52 6474
Osamu Nakamura 0:a40b9a259b52 6475 // Internal: Double-quotes a string `value`, replacing all ASCII control
Osamu Nakamura 0:a40b9a259b52 6476 // characters (characters with code unit values between 0 and 31) with
Osamu Nakamura 0:a40b9a259b52 6477 // their escaped equivalents. This is an implementation of the
Osamu Nakamura 0:a40b9a259b52 6478 // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
Osamu Nakamura 0:a40b9a259b52 6479 var unicodePrefix = "\\u00";
Osamu Nakamura 0:a40b9a259b52 6480 var quote = function (value) {
Osamu Nakamura 0:a40b9a259b52 6481 var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols;
Osamu Nakamura 0:a40b9a259b52 6482 if (isLarge) {
Osamu Nakamura 0:a40b9a259b52 6483 symbols = value.split("");
Osamu Nakamura 0:a40b9a259b52 6484 }
Osamu Nakamura 0:a40b9a259b52 6485 for (; index < length; index++) {
Osamu Nakamura 0:a40b9a259b52 6486 var charCode = value.charCodeAt(index);
Osamu Nakamura 0:a40b9a259b52 6487 // If the character is a control character, append its Unicode or
Osamu Nakamura 0:a40b9a259b52 6488 // shorthand escape sequence; otherwise, append the character as-is.
Osamu Nakamura 0:a40b9a259b52 6489 switch (charCode) {
Osamu Nakamura 0:a40b9a259b52 6490 case 8: case 9: case 10: case 12: case 13: case 34: case 92:
Osamu Nakamura 0:a40b9a259b52 6491 result += Escapes[charCode];
Osamu Nakamura 0:a40b9a259b52 6492 break;
Osamu Nakamura 0:a40b9a259b52 6493 default:
Osamu Nakamura 0:a40b9a259b52 6494 if (charCode < 32) {
Osamu Nakamura 0:a40b9a259b52 6495 result += unicodePrefix + toPaddedString(2, charCode.toString(16));
Osamu Nakamura 0:a40b9a259b52 6496 break;
Osamu Nakamura 0:a40b9a259b52 6497 }
Osamu Nakamura 0:a40b9a259b52 6498 result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index];
Osamu Nakamura 0:a40b9a259b52 6499 }
Osamu Nakamura 0:a40b9a259b52 6500 }
Osamu Nakamura 0:a40b9a259b52 6501 return result + '"';
Osamu Nakamura 0:a40b9a259b52 6502 };
Osamu Nakamura 0:a40b9a259b52 6503
Osamu Nakamura 0:a40b9a259b52 6504 // Internal: Recursively serializes an object. Implements the
Osamu Nakamura 0:a40b9a259b52 6505 // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
Osamu Nakamura 0:a40b9a259b52 6506 var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
Osamu Nakamura 0:a40b9a259b52 6507 var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
Osamu Nakamura 0:a40b9a259b52 6508 try {
Osamu Nakamura 0:a40b9a259b52 6509 // Necessary for host object support.
Osamu Nakamura 0:a40b9a259b52 6510 value = object[property];
Osamu Nakamura 0:a40b9a259b52 6511 } catch (exception) {}
Osamu Nakamura 0:a40b9a259b52 6512 if (typeof value == "object" && value) {
Osamu Nakamura 0:a40b9a259b52 6513 className = getClass.call(value);
Osamu Nakamura 0:a40b9a259b52 6514 if (className == dateClass && !isProperty.call(value, "toJSON")) {
Osamu Nakamura 0:a40b9a259b52 6515 if (value > -1 / 0 && value < 1 / 0) {
Osamu Nakamura 0:a40b9a259b52 6516 // Dates are serialized according to the `Date#toJSON` method
Osamu Nakamura 0:a40b9a259b52 6517 // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
Osamu Nakamura 0:a40b9a259b52 6518 // for the ISO 8601 date time string format.
Osamu Nakamura 0:a40b9a259b52 6519 if (getDay) {
Osamu Nakamura 0:a40b9a259b52 6520 // Manually compute the year, month, date, hours, minutes,
Osamu Nakamura 0:a40b9a259b52 6521 // seconds, and milliseconds if the `getUTC*` methods are
Osamu Nakamura 0:a40b9a259b52 6522 // buggy. Adapted from @Yaffle's `date-shim` project.
Osamu Nakamura 0:a40b9a259b52 6523 date = floor(value / 864e5);
Osamu Nakamura 0:a40b9a259b52 6524 for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
Osamu Nakamura 0:a40b9a259b52 6525 for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
Osamu Nakamura 0:a40b9a259b52 6526 date = 1 + date - getDay(year, month);
Osamu Nakamura 0:a40b9a259b52 6527 // The `time` value specifies the time within the day (see ES
Osamu Nakamura 0:a40b9a259b52 6528 // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
Osamu Nakamura 0:a40b9a259b52 6529 // to compute `A modulo B`, as the `%` operator does not
Osamu Nakamura 0:a40b9a259b52 6530 // correspond to the `modulo` operation for negative numbers.
Osamu Nakamura 0:a40b9a259b52 6531 time = (value % 864e5 + 864e5) % 864e5;
Osamu Nakamura 0:a40b9a259b52 6532 // The hours, minutes, seconds, and milliseconds are obtained by
Osamu Nakamura 0:a40b9a259b52 6533 // decomposing the time within the day. See section 15.9.1.10.
Osamu Nakamura 0:a40b9a259b52 6534 hours = floor(time / 36e5) % 24;
Osamu Nakamura 0:a40b9a259b52 6535 minutes = floor(time / 6e4) % 60;
Osamu Nakamura 0:a40b9a259b52 6536 seconds = floor(time / 1e3) % 60;
Osamu Nakamura 0:a40b9a259b52 6537 milliseconds = time % 1e3;
Osamu Nakamura 0:a40b9a259b52 6538 } else {
Osamu Nakamura 0:a40b9a259b52 6539 year = value.getUTCFullYear();
Osamu Nakamura 0:a40b9a259b52 6540 month = value.getUTCMonth();
Osamu Nakamura 0:a40b9a259b52 6541 date = value.getUTCDate();
Osamu Nakamura 0:a40b9a259b52 6542 hours = value.getUTCHours();
Osamu Nakamura 0:a40b9a259b52 6543 minutes = value.getUTCMinutes();
Osamu Nakamura 0:a40b9a259b52 6544 seconds = value.getUTCSeconds();
Osamu Nakamura 0:a40b9a259b52 6545 milliseconds = value.getUTCMilliseconds();
Osamu Nakamura 0:a40b9a259b52 6546 }
Osamu Nakamura 0:a40b9a259b52 6547 // Serialize extended years correctly.
Osamu Nakamura 0:a40b9a259b52 6548 value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
Osamu Nakamura 0:a40b9a259b52 6549 "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
Osamu Nakamura 0:a40b9a259b52 6550 // Months, dates, hours, minutes, and seconds should have two
Osamu Nakamura 0:a40b9a259b52 6551 // digits; milliseconds should have three.
Osamu Nakamura 0:a40b9a259b52 6552 "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
Osamu Nakamura 0:a40b9a259b52 6553 // Milliseconds are optional in ES 5.0, but required in 5.1.
Osamu Nakamura 0:a40b9a259b52 6554 "." + toPaddedString(3, milliseconds) + "Z";
Osamu Nakamura 0:a40b9a259b52 6555 } else {
Osamu Nakamura 0:a40b9a259b52 6556 value = null;
Osamu Nakamura 0:a40b9a259b52 6557 }
Osamu Nakamura 0:a40b9a259b52 6558 } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
Osamu Nakamura 0:a40b9a259b52 6559 // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
Osamu Nakamura 0:a40b9a259b52 6560 // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
Osamu Nakamura 0:a40b9a259b52 6561 // ignores all `toJSON` methods on these objects unless they are
Osamu Nakamura 0:a40b9a259b52 6562 // defined directly on an instance.
Osamu Nakamura 0:a40b9a259b52 6563 value = value.toJSON(property);
Osamu Nakamura 0:a40b9a259b52 6564 }
Osamu Nakamura 0:a40b9a259b52 6565 }
Osamu Nakamura 0:a40b9a259b52 6566 if (callback) {
Osamu Nakamura 0:a40b9a259b52 6567 // If a replacement function was provided, call it to obtain the value
Osamu Nakamura 0:a40b9a259b52 6568 // for serialization.
Osamu Nakamura 0:a40b9a259b52 6569 value = callback.call(object, property, value);
Osamu Nakamura 0:a40b9a259b52 6570 }
Osamu Nakamura 0:a40b9a259b52 6571 if (value === null) {
Osamu Nakamura 0:a40b9a259b52 6572 return "null";
Osamu Nakamura 0:a40b9a259b52 6573 }
Osamu Nakamura 0:a40b9a259b52 6574 className = getClass.call(value);
Osamu Nakamura 0:a40b9a259b52 6575 if (className == booleanClass) {
Osamu Nakamura 0:a40b9a259b52 6576 // Booleans are represented literally.
Osamu Nakamura 0:a40b9a259b52 6577 return "" + value;
Osamu Nakamura 0:a40b9a259b52 6578 } else if (className == numberClass) {
Osamu Nakamura 0:a40b9a259b52 6579 // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
Osamu Nakamura 0:a40b9a259b52 6580 // `"null"`.
Osamu Nakamura 0:a40b9a259b52 6581 return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
Osamu Nakamura 0:a40b9a259b52 6582 } else if (className == stringClass) {
Osamu Nakamura 0:a40b9a259b52 6583 // Strings are double-quoted and escaped.
Osamu Nakamura 0:a40b9a259b52 6584 return quote("" + value);
Osamu Nakamura 0:a40b9a259b52 6585 }
Osamu Nakamura 0:a40b9a259b52 6586 // Recursively serialize objects and arrays.
Osamu Nakamura 0:a40b9a259b52 6587 if (typeof value == "object") {
Osamu Nakamura 0:a40b9a259b52 6588 // Check for cyclic structures. This is a linear search; performance
Osamu Nakamura 0:a40b9a259b52 6589 // is inversely proportional to the number of unique nested objects.
Osamu Nakamura 0:a40b9a259b52 6590 for (length = stack.length; length--;) {
Osamu Nakamura 0:a40b9a259b52 6591 if (stack[length] === value) {
Osamu Nakamura 0:a40b9a259b52 6592 // Cyclic structures cannot be serialized by `JSON.stringify`.
Osamu Nakamura 0:a40b9a259b52 6593 throw TypeError();
Osamu Nakamura 0:a40b9a259b52 6594 }
Osamu Nakamura 0:a40b9a259b52 6595 }
Osamu Nakamura 0:a40b9a259b52 6596 // Add the object to the stack of traversed objects.
Osamu Nakamura 0:a40b9a259b52 6597 stack.push(value);
Osamu Nakamura 0:a40b9a259b52 6598 results = [];
Osamu Nakamura 0:a40b9a259b52 6599 // Save the current indentation level and indent one additional level.
Osamu Nakamura 0:a40b9a259b52 6600 prefix = indentation;
Osamu Nakamura 0:a40b9a259b52 6601 indentation += whitespace;
Osamu Nakamura 0:a40b9a259b52 6602 if (className == arrayClass) {
Osamu Nakamura 0:a40b9a259b52 6603 // Recursively serialize array elements.
Osamu Nakamura 0:a40b9a259b52 6604 for (index = 0, length = value.length; index < length; index++) {
Osamu Nakamura 0:a40b9a259b52 6605 element = serialize(index, value, callback, properties, whitespace, indentation, stack);
Osamu Nakamura 0:a40b9a259b52 6606 results.push(element === undef ? "null" : element);
Osamu Nakamura 0:a40b9a259b52 6607 }
Osamu Nakamura 0:a40b9a259b52 6608 result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
Osamu Nakamura 0:a40b9a259b52 6609 } else {
Osamu Nakamura 0:a40b9a259b52 6610 // Recursively serialize object members. Members are selected from
Osamu Nakamura 0:a40b9a259b52 6611 // either a user-specified list of property names, or the object
Osamu Nakamura 0:a40b9a259b52 6612 // itself.
Osamu Nakamura 0:a40b9a259b52 6613 forEach(properties || value, function (property) {
Osamu Nakamura 0:a40b9a259b52 6614 var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
Osamu Nakamura 0:a40b9a259b52 6615 if (element !== undef) {
Osamu Nakamura 0:a40b9a259b52 6616 // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
Osamu Nakamura 0:a40b9a259b52 6617 // is not the empty string, let `member` {quote(property) + ":"}
Osamu Nakamura 0:a40b9a259b52 6618 // be the concatenation of `member` and the `space` character."
Osamu Nakamura 0:a40b9a259b52 6619 // The "`space` character" refers to the literal space
Osamu Nakamura 0:a40b9a259b52 6620 // character, not the `space` {width} argument provided to
Osamu Nakamura 0:a40b9a259b52 6621 // `JSON.stringify`.
Osamu Nakamura 0:a40b9a259b52 6622 results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
Osamu Nakamura 0:a40b9a259b52 6623 }
Osamu Nakamura 0:a40b9a259b52 6624 });
Osamu Nakamura 0:a40b9a259b52 6625 result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
Osamu Nakamura 0:a40b9a259b52 6626 }
Osamu Nakamura 0:a40b9a259b52 6627 // Remove the object from the traversed object stack.
Osamu Nakamura 0:a40b9a259b52 6628 stack.pop();
Osamu Nakamura 0:a40b9a259b52 6629 return result;
Osamu Nakamura 0:a40b9a259b52 6630 }
Osamu Nakamura 0:a40b9a259b52 6631 };
Osamu Nakamura 0:a40b9a259b52 6632
Osamu Nakamura 0:a40b9a259b52 6633 // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
Osamu Nakamura 0:a40b9a259b52 6634 JSON3.stringify = function (source, filter, width) {
Osamu Nakamura 0:a40b9a259b52 6635 var whitespace, callback, properties, className;
Osamu Nakamura 0:a40b9a259b52 6636 if (typeof filter == "function" || typeof filter == "object" && filter) {
Osamu Nakamura 0:a40b9a259b52 6637 if ((className = getClass.call(filter)) == functionClass) {
Osamu Nakamura 0:a40b9a259b52 6638 callback = filter;
Osamu Nakamura 0:a40b9a259b52 6639 } else if (className == arrayClass) {
Osamu Nakamura 0:a40b9a259b52 6640 // Convert the property names array into a makeshift set.
Osamu Nakamura 0:a40b9a259b52 6641 properties = {};
Osamu Nakamura 0:a40b9a259b52 6642 for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
Osamu Nakamura 0:a40b9a259b52 6643 }
Osamu Nakamura 0:a40b9a259b52 6644 }
Osamu Nakamura 0:a40b9a259b52 6645 if (width) {
Osamu Nakamura 0:a40b9a259b52 6646 if ((className = getClass.call(width)) == numberClass) {
Osamu Nakamura 0:a40b9a259b52 6647 // Convert the `width` to an integer and create a string containing
Osamu Nakamura 0:a40b9a259b52 6648 // `width` number of space characters.
Osamu Nakamura 0:a40b9a259b52 6649 if ((width -= width % 1) > 0) {
Osamu Nakamura 0:a40b9a259b52 6650 for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
Osamu Nakamura 0:a40b9a259b52 6651 }
Osamu Nakamura 0:a40b9a259b52 6652 } else if (className == stringClass) {
Osamu Nakamura 0:a40b9a259b52 6653 whitespace = width.length <= 10 ? width : width.slice(0, 10);
Osamu Nakamura 0:a40b9a259b52 6654 }
Osamu Nakamura 0:a40b9a259b52 6655 }
Osamu Nakamura 0:a40b9a259b52 6656 // Opera <= 7.54u2 discards the values associated with empty string keys
Osamu Nakamura 0:a40b9a259b52 6657 // (`""`) only if they are used directly within an object member list
Osamu Nakamura 0:a40b9a259b52 6658 // (e.g., `!("" in { "": 1})`).
Osamu Nakamura 0:a40b9a259b52 6659 return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
Osamu Nakamura 0:a40b9a259b52 6660 };
Osamu Nakamura 0:a40b9a259b52 6661 }
Osamu Nakamura 0:a40b9a259b52 6662
Osamu Nakamura 0:a40b9a259b52 6663 // Public: Parses a JSON source string.
Osamu Nakamura 0:a40b9a259b52 6664 if (!has("json-parse")) {
Osamu Nakamura 0:a40b9a259b52 6665 var fromCharCode = String.fromCharCode;
Osamu Nakamura 0:a40b9a259b52 6666
Osamu Nakamura 0:a40b9a259b52 6667 // Internal: A map of escaped control characters and their unescaped
Osamu Nakamura 0:a40b9a259b52 6668 // equivalents.
Osamu Nakamura 0:a40b9a259b52 6669 var Unescapes = {
Osamu Nakamura 0:a40b9a259b52 6670 92: "\\",
Osamu Nakamura 0:a40b9a259b52 6671 34: '"',
Osamu Nakamura 0:a40b9a259b52 6672 47: "/",
Osamu Nakamura 0:a40b9a259b52 6673 98: "\b",
Osamu Nakamura 0:a40b9a259b52 6674 116: "\t",
Osamu Nakamura 0:a40b9a259b52 6675 110: "\n",
Osamu Nakamura 0:a40b9a259b52 6676 102: "\f",
Osamu Nakamura 0:a40b9a259b52 6677 114: "\r"
Osamu Nakamura 0:a40b9a259b52 6678 };
Osamu Nakamura 0:a40b9a259b52 6679
Osamu Nakamura 0:a40b9a259b52 6680 // Internal: Stores the parser state.
Osamu Nakamura 0:a40b9a259b52 6681 var Index, Source;
Osamu Nakamura 0:a40b9a259b52 6682
Osamu Nakamura 0:a40b9a259b52 6683 // Internal: Resets the parser state and throws a `SyntaxError`.
Osamu Nakamura 0:a40b9a259b52 6684 var abort = function() {
Osamu Nakamura 0:a40b9a259b52 6685 Index = Source = null;
Osamu Nakamura 0:a40b9a259b52 6686 throw SyntaxError();
Osamu Nakamura 0:a40b9a259b52 6687 };
Osamu Nakamura 0:a40b9a259b52 6688
Osamu Nakamura 0:a40b9a259b52 6689 // Internal: Returns the next token, or `"$"` if the parser has reached
Osamu Nakamura 0:a40b9a259b52 6690 // the end of the source string. A token may be a string, number, `null`
Osamu Nakamura 0:a40b9a259b52 6691 // literal, or Boolean literal.
Osamu Nakamura 0:a40b9a259b52 6692 var lex = function () {
Osamu Nakamura 0:a40b9a259b52 6693 var source = Source, length = source.length, value, begin, position, isSigned, charCode;
Osamu Nakamura 0:a40b9a259b52 6694 while (Index < length) {
Osamu Nakamura 0:a40b9a259b52 6695 charCode = source.charCodeAt(Index);
Osamu Nakamura 0:a40b9a259b52 6696 switch (charCode) {
Osamu Nakamura 0:a40b9a259b52 6697 case 9: case 10: case 13: case 32:
Osamu Nakamura 0:a40b9a259b52 6698 // Skip whitespace tokens, including tabs, carriage returns, line
Osamu Nakamura 0:a40b9a259b52 6699 // feeds, and space characters.
Osamu Nakamura 0:a40b9a259b52 6700 Index++;
Osamu Nakamura 0:a40b9a259b52 6701 break;
Osamu Nakamura 0:a40b9a259b52 6702 case 123: case 125: case 91: case 93: case 58: case 44:
Osamu Nakamura 0:a40b9a259b52 6703 // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
Osamu Nakamura 0:a40b9a259b52 6704 // the current position.
Osamu Nakamura 0:a40b9a259b52 6705 value = charIndexBuggy ? source.charAt(Index) : source[Index];
Osamu Nakamura 0:a40b9a259b52 6706 Index++;
Osamu Nakamura 0:a40b9a259b52 6707 return value;
Osamu Nakamura 0:a40b9a259b52 6708 case 34:
Osamu Nakamura 0:a40b9a259b52 6709 // `"` delimits a JSON string; advance to the next character and
Osamu Nakamura 0:a40b9a259b52 6710 // begin parsing the string. String tokens are prefixed with the
Osamu Nakamura 0:a40b9a259b52 6711 // sentinel `@` character to distinguish them from punctuators and
Osamu Nakamura 0:a40b9a259b52 6712 // end-of-string tokens.
Osamu Nakamura 0:a40b9a259b52 6713 for (value = "@", Index++; Index < length;) {
Osamu Nakamura 0:a40b9a259b52 6714 charCode = source.charCodeAt(Index);
Osamu Nakamura 0:a40b9a259b52 6715 if (charCode < 32) {
Osamu Nakamura 0:a40b9a259b52 6716 // Unescaped ASCII control characters (those with a code unit
Osamu Nakamura 0:a40b9a259b52 6717 // less than the space character) are not permitted.
Osamu Nakamura 0:a40b9a259b52 6718 abort();
Osamu Nakamura 0:a40b9a259b52 6719 } else if (charCode == 92) {
Osamu Nakamura 0:a40b9a259b52 6720 // A reverse solidus (`\`) marks the beginning of an escaped
Osamu Nakamura 0:a40b9a259b52 6721 // control character (including `"`, `\`, and `/`) or Unicode
Osamu Nakamura 0:a40b9a259b52 6722 // escape sequence.
Osamu Nakamura 0:a40b9a259b52 6723 charCode = source.charCodeAt(++Index);
Osamu Nakamura 0:a40b9a259b52 6724 switch (charCode) {
Osamu Nakamura 0:a40b9a259b52 6725 case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
Osamu Nakamura 0:a40b9a259b52 6726 // Revive escaped control characters.
Osamu Nakamura 0:a40b9a259b52 6727 value += Unescapes[charCode];
Osamu Nakamura 0:a40b9a259b52 6728 Index++;
Osamu Nakamura 0:a40b9a259b52 6729 break;
Osamu Nakamura 0:a40b9a259b52 6730 case 117:
Osamu Nakamura 0:a40b9a259b52 6731 // `\u` marks the beginning of a Unicode escape sequence.
Osamu Nakamura 0:a40b9a259b52 6732 // Advance to the first character and validate the
Osamu Nakamura 0:a40b9a259b52 6733 // four-digit code point.
Osamu Nakamura 0:a40b9a259b52 6734 begin = ++Index;
Osamu Nakamura 0:a40b9a259b52 6735 for (position = Index + 4; Index < position; Index++) {
Osamu Nakamura 0:a40b9a259b52 6736 charCode = source.charCodeAt(Index);
Osamu Nakamura 0:a40b9a259b52 6737 // A valid sequence comprises four hexdigits (case-
Osamu Nakamura 0:a40b9a259b52 6738 // insensitive) that form a single hexadecimal value.
Osamu Nakamura 0:a40b9a259b52 6739 if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
Osamu Nakamura 0:a40b9a259b52 6740 // Invalid Unicode escape sequence.
Osamu Nakamura 0:a40b9a259b52 6741 abort();
Osamu Nakamura 0:a40b9a259b52 6742 }
Osamu Nakamura 0:a40b9a259b52 6743 }
Osamu Nakamura 0:a40b9a259b52 6744 // Revive the escaped character.
Osamu Nakamura 0:a40b9a259b52 6745 value += fromCharCode("0x" + source.slice(begin, Index));
Osamu Nakamura 0:a40b9a259b52 6746 break;
Osamu Nakamura 0:a40b9a259b52 6747 default:
Osamu Nakamura 0:a40b9a259b52 6748 // Invalid escape sequence.
Osamu Nakamura 0:a40b9a259b52 6749 abort();
Osamu Nakamura 0:a40b9a259b52 6750 }
Osamu Nakamura 0:a40b9a259b52 6751 } else {
Osamu Nakamura 0:a40b9a259b52 6752 if (charCode == 34) {
Osamu Nakamura 0:a40b9a259b52 6753 // An unescaped double-quote character marks the end of the
Osamu Nakamura 0:a40b9a259b52 6754 // string.
Osamu Nakamura 0:a40b9a259b52 6755 break;
Osamu Nakamura 0:a40b9a259b52 6756 }
Osamu Nakamura 0:a40b9a259b52 6757 charCode = source.charCodeAt(Index);
Osamu Nakamura 0:a40b9a259b52 6758 begin = Index;
Osamu Nakamura 0:a40b9a259b52 6759 // Optimize for the common case where a string is valid.
Osamu Nakamura 0:a40b9a259b52 6760 while (charCode >= 32 && charCode != 92 && charCode != 34) {
Osamu Nakamura 0:a40b9a259b52 6761 charCode = source.charCodeAt(++Index);
Osamu Nakamura 0:a40b9a259b52 6762 }
Osamu Nakamura 0:a40b9a259b52 6763 // Append the string as-is.
Osamu Nakamura 0:a40b9a259b52 6764 value += source.slice(begin, Index);
Osamu Nakamura 0:a40b9a259b52 6765 }
Osamu Nakamura 0:a40b9a259b52 6766 }
Osamu Nakamura 0:a40b9a259b52 6767 if (source.charCodeAt(Index) == 34) {
Osamu Nakamura 0:a40b9a259b52 6768 // Advance to the next character and return the revived string.
Osamu Nakamura 0:a40b9a259b52 6769 Index++;
Osamu Nakamura 0:a40b9a259b52 6770 return value;
Osamu Nakamura 0:a40b9a259b52 6771 }
Osamu Nakamura 0:a40b9a259b52 6772 // Unterminated string.
Osamu Nakamura 0:a40b9a259b52 6773 abort();
Osamu Nakamura 0:a40b9a259b52 6774 default:
Osamu Nakamura 0:a40b9a259b52 6775 // Parse numbers and literals.
Osamu Nakamura 0:a40b9a259b52 6776 begin = Index;
Osamu Nakamura 0:a40b9a259b52 6777 // Advance past the negative sign, if one is specified.
Osamu Nakamura 0:a40b9a259b52 6778 if (charCode == 45) {
Osamu Nakamura 0:a40b9a259b52 6779 isSigned = true;
Osamu Nakamura 0:a40b9a259b52 6780 charCode = source.charCodeAt(++Index);
Osamu Nakamura 0:a40b9a259b52 6781 }
Osamu Nakamura 0:a40b9a259b52 6782 // Parse an integer or floating-point value.
Osamu Nakamura 0:a40b9a259b52 6783 if (charCode >= 48 && charCode <= 57) {
Osamu Nakamura 0:a40b9a259b52 6784 // Leading zeroes are interpreted as octal literals.
Osamu Nakamura 0:a40b9a259b52 6785 if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
Osamu Nakamura 0:a40b9a259b52 6786 // Illegal octal literal.
Osamu Nakamura 0:a40b9a259b52 6787 abort();
Osamu Nakamura 0:a40b9a259b52 6788 }
Osamu Nakamura 0:a40b9a259b52 6789 isSigned = false;
Osamu Nakamura 0:a40b9a259b52 6790 // Parse the integer component.
Osamu Nakamura 0:a40b9a259b52 6791 for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
Osamu Nakamura 0:a40b9a259b52 6792 // Floats cannot contain a leading decimal point; however, this
Osamu Nakamura 0:a40b9a259b52 6793 // case is already accounted for by the parser.
Osamu Nakamura 0:a40b9a259b52 6794 if (source.charCodeAt(Index) == 46) {
Osamu Nakamura 0:a40b9a259b52 6795 position = ++Index;
Osamu Nakamura 0:a40b9a259b52 6796 // Parse the decimal component.
Osamu Nakamura 0:a40b9a259b52 6797 for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
Osamu Nakamura 0:a40b9a259b52 6798 if (position == Index) {
Osamu Nakamura 0:a40b9a259b52 6799 // Illegal trailing decimal.
Osamu Nakamura 0:a40b9a259b52 6800 abort();
Osamu Nakamura 0:a40b9a259b52 6801 }
Osamu Nakamura 0:a40b9a259b52 6802 Index = position;
Osamu Nakamura 0:a40b9a259b52 6803 }
Osamu Nakamura 0:a40b9a259b52 6804 // Parse exponents. The `e` denoting the exponent is
Osamu Nakamura 0:a40b9a259b52 6805 // case-insensitive.
Osamu Nakamura 0:a40b9a259b52 6806 charCode = source.charCodeAt(Index);
Osamu Nakamura 0:a40b9a259b52 6807 if (charCode == 101 || charCode == 69) {
Osamu Nakamura 0:a40b9a259b52 6808 charCode = source.charCodeAt(++Index);
Osamu Nakamura 0:a40b9a259b52 6809 // Skip past the sign following the exponent, if one is
Osamu Nakamura 0:a40b9a259b52 6810 // specified.
Osamu Nakamura 0:a40b9a259b52 6811 if (charCode == 43 || charCode == 45) {
Osamu Nakamura 0:a40b9a259b52 6812 Index++;
Osamu Nakamura 0:a40b9a259b52 6813 }
Osamu Nakamura 0:a40b9a259b52 6814 // Parse the exponential component.
Osamu Nakamura 0:a40b9a259b52 6815 for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
Osamu Nakamura 0:a40b9a259b52 6816 if (position == Index) {
Osamu Nakamura 0:a40b9a259b52 6817 // Illegal empty exponent.
Osamu Nakamura 0:a40b9a259b52 6818 abort();
Osamu Nakamura 0:a40b9a259b52 6819 }
Osamu Nakamura 0:a40b9a259b52 6820 Index = position;
Osamu Nakamura 0:a40b9a259b52 6821 }
Osamu Nakamura 0:a40b9a259b52 6822 // Coerce the parsed value to a JavaScript number.
Osamu Nakamura 0:a40b9a259b52 6823 return +source.slice(begin, Index);
Osamu Nakamura 0:a40b9a259b52 6824 }
Osamu Nakamura 0:a40b9a259b52 6825 // A negative sign may only precede numbers.
Osamu Nakamura 0:a40b9a259b52 6826 if (isSigned) {
Osamu Nakamura 0:a40b9a259b52 6827 abort();
Osamu Nakamura 0:a40b9a259b52 6828 }
Osamu Nakamura 0:a40b9a259b52 6829 // `true`, `false`, and `null` literals.
Osamu Nakamura 0:a40b9a259b52 6830 if (source.slice(Index, Index + 4) == "true") {
Osamu Nakamura 0:a40b9a259b52 6831 Index += 4;
Osamu Nakamura 0:a40b9a259b52 6832 return true;
Osamu Nakamura 0:a40b9a259b52 6833 } else if (source.slice(Index, Index + 5) == "false") {
Osamu Nakamura 0:a40b9a259b52 6834 Index += 5;
Osamu Nakamura 0:a40b9a259b52 6835 return false;
Osamu Nakamura 0:a40b9a259b52 6836 } else if (source.slice(Index, Index + 4) == "null") {
Osamu Nakamura 0:a40b9a259b52 6837 Index += 4;
Osamu Nakamura 0:a40b9a259b52 6838 return null;
Osamu Nakamura 0:a40b9a259b52 6839 }
Osamu Nakamura 0:a40b9a259b52 6840 // Unrecognized token.
Osamu Nakamura 0:a40b9a259b52 6841 abort();
Osamu Nakamura 0:a40b9a259b52 6842 }
Osamu Nakamura 0:a40b9a259b52 6843 }
Osamu Nakamura 0:a40b9a259b52 6844 // Return the sentinel `$` character if the parser has reached the end
Osamu Nakamura 0:a40b9a259b52 6845 // of the source string.
Osamu Nakamura 0:a40b9a259b52 6846 return "$";
Osamu Nakamura 0:a40b9a259b52 6847 };
Osamu Nakamura 0:a40b9a259b52 6848
Osamu Nakamura 0:a40b9a259b52 6849 // Internal: Parses a JSON `value` token.
Osamu Nakamura 0:a40b9a259b52 6850 var get = function (value) {
Osamu Nakamura 0:a40b9a259b52 6851 var results, hasMembers;
Osamu Nakamura 0:a40b9a259b52 6852 if (value == "$") {
Osamu Nakamura 0:a40b9a259b52 6853 // Unexpected end of input.
Osamu Nakamura 0:a40b9a259b52 6854 abort();
Osamu Nakamura 0:a40b9a259b52 6855 }
Osamu Nakamura 0:a40b9a259b52 6856 if (typeof value == "string") {
Osamu Nakamura 0:a40b9a259b52 6857 if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
Osamu Nakamura 0:a40b9a259b52 6858 // Remove the sentinel `@` character.
Osamu Nakamura 0:a40b9a259b52 6859 return value.slice(1);
Osamu Nakamura 0:a40b9a259b52 6860 }
Osamu Nakamura 0:a40b9a259b52 6861 // Parse object and array literals.
Osamu Nakamura 0:a40b9a259b52 6862 if (value == "[") {
Osamu Nakamura 0:a40b9a259b52 6863 // Parses a JSON array, returning a new JavaScript array.
Osamu Nakamura 0:a40b9a259b52 6864 results = [];
Osamu Nakamura 0:a40b9a259b52 6865 for (;; hasMembers || (hasMembers = true)) {
Osamu Nakamura 0:a40b9a259b52 6866 value = lex();
Osamu Nakamura 0:a40b9a259b52 6867 // A closing square bracket marks the end of the array literal.
Osamu Nakamura 0:a40b9a259b52 6868 if (value == "]") {
Osamu Nakamura 0:a40b9a259b52 6869 break;
Osamu Nakamura 0:a40b9a259b52 6870 }
Osamu Nakamura 0:a40b9a259b52 6871 // If the array literal contains elements, the current token
Osamu Nakamura 0:a40b9a259b52 6872 // should be a comma separating the previous element from the
Osamu Nakamura 0:a40b9a259b52 6873 // next.
Osamu Nakamura 0:a40b9a259b52 6874 if (hasMembers) {
Osamu Nakamura 0:a40b9a259b52 6875 if (value == ",") {
Osamu Nakamura 0:a40b9a259b52 6876 value = lex();
Osamu Nakamura 0:a40b9a259b52 6877 if (value == "]") {
Osamu Nakamura 0:a40b9a259b52 6878 // Unexpected trailing `,` in array literal.
Osamu Nakamura 0:a40b9a259b52 6879 abort();
Osamu Nakamura 0:a40b9a259b52 6880 }
Osamu Nakamura 0:a40b9a259b52 6881 } else {
Osamu Nakamura 0:a40b9a259b52 6882 // A `,` must separate each array element.
Osamu Nakamura 0:a40b9a259b52 6883 abort();
Osamu Nakamura 0:a40b9a259b52 6884 }
Osamu Nakamura 0:a40b9a259b52 6885 }
Osamu Nakamura 0:a40b9a259b52 6886 // Elisions and leading commas are not permitted.
Osamu Nakamura 0:a40b9a259b52 6887 if (value == ",") {
Osamu Nakamura 0:a40b9a259b52 6888 abort();
Osamu Nakamura 0:a40b9a259b52 6889 }
Osamu Nakamura 0:a40b9a259b52 6890 results.push(get(value));
Osamu Nakamura 0:a40b9a259b52 6891 }
Osamu Nakamura 0:a40b9a259b52 6892 return results;
Osamu Nakamura 0:a40b9a259b52 6893 } else if (value == "{") {
Osamu Nakamura 0:a40b9a259b52 6894 // Parses a JSON object, returning a new JavaScript object.
Osamu Nakamura 0:a40b9a259b52 6895 results = {};
Osamu Nakamura 0:a40b9a259b52 6896 for (;; hasMembers || (hasMembers = true)) {
Osamu Nakamura 0:a40b9a259b52 6897 value = lex();
Osamu Nakamura 0:a40b9a259b52 6898 // A closing curly brace marks the end of the object literal.
Osamu Nakamura 0:a40b9a259b52 6899 if (value == "}") {
Osamu Nakamura 0:a40b9a259b52 6900 break;
Osamu Nakamura 0:a40b9a259b52 6901 }
Osamu Nakamura 0:a40b9a259b52 6902 // If the object literal contains members, the current token
Osamu Nakamura 0:a40b9a259b52 6903 // should be a comma separator.
Osamu Nakamura 0:a40b9a259b52 6904 if (hasMembers) {
Osamu Nakamura 0:a40b9a259b52 6905 if (value == ",") {
Osamu Nakamura 0:a40b9a259b52 6906 value = lex();
Osamu Nakamura 0:a40b9a259b52 6907 if (value == "}") {
Osamu Nakamura 0:a40b9a259b52 6908 // Unexpected trailing `,` in object literal.
Osamu Nakamura 0:a40b9a259b52 6909 abort();
Osamu Nakamura 0:a40b9a259b52 6910 }
Osamu Nakamura 0:a40b9a259b52 6911 } else {
Osamu Nakamura 0:a40b9a259b52 6912 // A `,` must separate each object member.
Osamu Nakamura 0:a40b9a259b52 6913 abort();
Osamu Nakamura 0:a40b9a259b52 6914 }
Osamu Nakamura 0:a40b9a259b52 6915 }
Osamu Nakamura 0:a40b9a259b52 6916 // Leading commas are not permitted, object property names must be
Osamu Nakamura 0:a40b9a259b52 6917 // double-quoted strings, and a `:` must separate each property
Osamu Nakamura 0:a40b9a259b52 6918 // name and value.
Osamu Nakamura 0:a40b9a259b52 6919 if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
Osamu Nakamura 0:a40b9a259b52 6920 abort();
Osamu Nakamura 0:a40b9a259b52 6921 }
Osamu Nakamura 0:a40b9a259b52 6922 results[value.slice(1)] = get(lex());
Osamu Nakamura 0:a40b9a259b52 6923 }
Osamu Nakamura 0:a40b9a259b52 6924 return results;
Osamu Nakamura 0:a40b9a259b52 6925 }
Osamu Nakamura 0:a40b9a259b52 6926 // Unexpected token encountered.
Osamu Nakamura 0:a40b9a259b52 6927 abort();
Osamu Nakamura 0:a40b9a259b52 6928 }
Osamu Nakamura 0:a40b9a259b52 6929 return value;
Osamu Nakamura 0:a40b9a259b52 6930 };
Osamu Nakamura 0:a40b9a259b52 6931
Osamu Nakamura 0:a40b9a259b52 6932 // Internal: Updates a traversed object member.
Osamu Nakamura 0:a40b9a259b52 6933 var update = function(source, property, callback) {
Osamu Nakamura 0:a40b9a259b52 6934 var element = walk(source, property, callback);
Osamu Nakamura 0:a40b9a259b52 6935 if (element === undef) {
Osamu Nakamura 0:a40b9a259b52 6936 delete source[property];
Osamu Nakamura 0:a40b9a259b52 6937 } else {
Osamu Nakamura 0:a40b9a259b52 6938 source[property] = element;
Osamu Nakamura 0:a40b9a259b52 6939 }
Osamu Nakamura 0:a40b9a259b52 6940 };
Osamu Nakamura 0:a40b9a259b52 6941
Osamu Nakamura 0:a40b9a259b52 6942 // Internal: Recursively traverses a parsed JSON object, invoking the
Osamu Nakamura 0:a40b9a259b52 6943 // `callback` function for each value. This is an implementation of the
Osamu Nakamura 0:a40b9a259b52 6944 // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
Osamu Nakamura 0:a40b9a259b52 6945 var walk = function (source, property, callback) {
Osamu Nakamura 0:a40b9a259b52 6946 var value = source[property], length;
Osamu Nakamura 0:a40b9a259b52 6947 if (typeof value == "object" && value) {
Osamu Nakamura 0:a40b9a259b52 6948 // `forEach` can't be used to traverse an array in Opera <= 8.54
Osamu Nakamura 0:a40b9a259b52 6949 // because its `Object#hasOwnProperty` implementation returns `false`
Osamu Nakamura 0:a40b9a259b52 6950 // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
Osamu Nakamura 0:a40b9a259b52 6951 if (getClass.call(value) == arrayClass) {
Osamu Nakamura 0:a40b9a259b52 6952 for (length = value.length; length--;) {
Osamu Nakamura 0:a40b9a259b52 6953 update(value, length, callback);
Osamu Nakamura 0:a40b9a259b52 6954 }
Osamu Nakamura 0:a40b9a259b52 6955 } else {
Osamu Nakamura 0:a40b9a259b52 6956 forEach(value, function (property) {
Osamu Nakamura 0:a40b9a259b52 6957 update(value, property, callback);
Osamu Nakamura 0:a40b9a259b52 6958 });
Osamu Nakamura 0:a40b9a259b52 6959 }
Osamu Nakamura 0:a40b9a259b52 6960 }
Osamu Nakamura 0:a40b9a259b52 6961 return callback.call(source, property, value);
Osamu Nakamura 0:a40b9a259b52 6962 };
Osamu Nakamura 0:a40b9a259b52 6963
Osamu Nakamura 0:a40b9a259b52 6964 // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
Osamu Nakamura 0:a40b9a259b52 6965 JSON3.parse = function (source, callback) {
Osamu Nakamura 0:a40b9a259b52 6966 var result, value;
Osamu Nakamura 0:a40b9a259b52 6967 Index = 0;
Osamu Nakamura 0:a40b9a259b52 6968 Source = "" + source;
Osamu Nakamura 0:a40b9a259b52 6969 result = get(lex());
Osamu Nakamura 0:a40b9a259b52 6970 // If a JSON string contains multiple tokens, it is invalid.
Osamu Nakamura 0:a40b9a259b52 6971 if (lex() != "$") {
Osamu Nakamura 0:a40b9a259b52 6972 abort();
Osamu Nakamura 0:a40b9a259b52 6973 }
Osamu Nakamura 0:a40b9a259b52 6974 // Reset the parser state.
Osamu Nakamura 0:a40b9a259b52 6975 Index = Source = null;
Osamu Nakamura 0:a40b9a259b52 6976 return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
Osamu Nakamura 0:a40b9a259b52 6977 };
Osamu Nakamura 0:a40b9a259b52 6978 }
Osamu Nakamura 0:a40b9a259b52 6979 }
Osamu Nakamura 0:a40b9a259b52 6980
Osamu Nakamura 0:a40b9a259b52 6981 // Export for asynchronous module loaders.
Osamu Nakamura 0:a40b9a259b52 6982 if (isLoader) {
Osamu Nakamura 0:a40b9a259b52 6983 define(function () {
Osamu Nakamura 0:a40b9a259b52 6984 return JSON3;
Osamu Nakamura 0:a40b9a259b52 6985 });
Osamu Nakamura 0:a40b9a259b52 6986 }
Osamu Nakamura 0:a40b9a259b52 6987 }(this));
Osamu Nakamura 0:a40b9a259b52 6988
Osamu Nakamura 0:a40b9a259b52 6989 },{}],50:[function(_dereq_,module,exports){
Osamu Nakamura 0:a40b9a259b52 6990 module.exports = toArray
Osamu Nakamura 0:a40b9a259b52 6991
Osamu Nakamura 0:a40b9a259b52 6992 function toArray(list, index) {
Osamu Nakamura 0:a40b9a259b52 6993 var array = []
Osamu Nakamura 0:a40b9a259b52 6994
Osamu Nakamura 0:a40b9a259b52 6995 index = index || 0
Osamu Nakamura 0:a40b9a259b52 6996
Osamu Nakamura 0:a40b9a259b52 6997 for (var i = index || 0; i < list.length; i++) {
Osamu Nakamura 0:a40b9a259b52 6998 array[i - index] = list[i]
Osamu Nakamura 0:a40b9a259b52 6999 }
Osamu Nakamura 0:a40b9a259b52 7000
Osamu Nakamura 0:a40b9a259b52 7001 return array
Osamu Nakamura 0:a40b9a259b52 7002 }
Osamu Nakamura 0:a40b9a259b52 7003
Osamu Nakamura 0:a40b9a259b52 7004 },{}]},{},[1])
Osamu Nakamura 0:a40b9a259b52 7005 (1)
Osamu Nakamura 0:a40b9a259b52 7006 });